Это многостраничный печатный вид этого раздела. Нажмите что бы печатать.

Вернуться к обычному просмотру страницы.

Пакет OAuth2 языка программирования Go

Пакет oauth2 содержит реализацию клиента для спецификации OAuth 2.0.
sequenceDiagram
    participant ClientApp
    participant User
    participant AuthServer
    participant ResourceServer

    %% Регистрация нового пользователя
    Note over ClientApp: 1. Создание нового пользователя
    ClientApp->>AuthServer: POST /register (не часть OAuth)
    AuthServer-->>ClientApp: client_id, client_secret

    %% Авторизация (Authorization Code Flow)
    Note over ClientApp,User: 2. Авторизация пользователя
    ClientApp->>User: Redirect to AuthURL (config.AuthCodeURL())
    User->>AuthServer: Авторизация/согласие
    AuthServer->>User: Redirect с code и state
    User->>ClientApp: Передача code
    ClientApp->>AuthServer: Exchange code на token (config.Exchange())
    AuthServer-->>ClientApp: access_token, refresh_token

    %% Использование токена
    Note over ClientApp,ResourceServer: 3. Доступ к ресурсам
    ClientApp->>ResourceServer: Запрос с токеном (transport)
    ResourceServer-->>ClientApp: Данные пользователя

    %% Другие поддерживаемые события
    Note over ClientApp,AuthServer: 4. Другие сценарии

    %% Refresh Token Flow
    ClientApp->>AuthServer: Запрос нового токена (TokenSource.Token())
    AuthServer-->>ClientApp: Новый access_token

    %% Client Credentials Flow
    ClientApp->>AuthServer: Запрос токена (clientcredentials.Config)
    AuthServer-->>ClientApp: Сервисный токен

    %% Device Flow
    ClientApp->>AuthServer: Запрос device code (DeviceAuth())
    AuthServer-->>ClientApp: user_code, verification_uri
    User->>AuthServer: Ввод user_code
    ClientApp->>AuthServer: Polling для токена (DeviceAccessToken())
    AuthServer-->>ClientApp: Устройственный токен

Ключевые элементы модели:

  1. Типы пакета OAuth2:

    • Config - основной объект конфигурации
    • Endpoint - URLs сервера авторизации
    • Token - содержит access/refresh токены
    • TokenSource - механизм обновления токенов
    • Transport - HTTP-транспорт с авторизацией
  2. Основные методы:

    • AuthCodeURL() - генерация URL авторизации
    • Exchange() - обмен code на токен
    • Client() - создание авторизованного HTTP-клиента
    • TokenSource() - автоматическое обновление токенов
  3. Поддерживаемые потоки:

    • Authorization Code Flow (основной)
    • Client Credentials Flow (для сервисов)
    • Device Flow (для ТВ/IoT)
    • Refresh Token Flow
  4. Дополнительные компоненты:

    • PKCE (защита от CSRF)
    • Различные AuthStyle (методы аутентификации)
    • Кастомные AuthCodeOption

Эта модель охватывает полный жизненный цикл OAuth 2.0 в Go-приложениях, от регистрации клиента до доступа к защищенным ресурсам.

Переменные

var HTTPClient internal.ContextKey

HTTPClient - это ключ контекста, используемый с context.WithValue для ассоциации *http.Client с контекстом.

var NoContext = context.TODO()

NoContext - контекст по умолчанию, который следует использовать, если не применяется собственный context.Context.

Устарело: Вместо этого используйте context.Background или context.TODO.


Функции

func GenerateVerifier

func GenerateVerifier() string

GenerateVerifier генерирует верификатор кода PKCE со случайными 32 октетами. Соответствует рекомендациям RFC 7636.

Новый верификатор должен генерироваться для каждой авторизации. Полученный верификатор следует передавать в Config.AuthCodeURL или Config.DeviceAuth с S256ChallengeOption, а в Config.Exchange или Config.DeviceAccessToken - с VerifierOption.

func NewClient

func NewClient(ctx context.Context, src TokenSource) *http.Client

NewClient создает *http.Client из context.Context и TokenSource. Возвращенный клиент действителен только в течение времени жизни контекста.

Примечание: если пользовательский *http.Client предоставлен через context.Context, он используется только для получения токена и не влияет на *http.Client, возвращаемый из NewClient.

Особый случай: если src равен nil, возвращается не-OAuth2 клиент с использованием предоставленного контекста.

func RegisterBrokenAuthHeaderProvider

Устарело.

func S256ChallengeFromVerifier

func S256ChallengeFromVerifier(verifier string) string

S256ChallengeFromVerifier возвращает challenge-код PKCE, полученный из верификатора методом S256.

Предпочтительнее использовать S256ChallengeOption, где это возможно.


Типы

type AuthCodeOption

type AuthCodeOption interface {
	// содержит неэкспортируемые методы
}

AuthCodeOption передается в Config.AuthCodeURL.

Варианты:

var (
	// AccessTypeOnline и AccessTypeOffline - параметры для Options.AuthCodeURL.
	// Они изменяют поле "access_type" в URL, возвращаемом AuthCodeURL.
	AccessTypeOnline  AuthCodeOption = SetAuthURLParam("access_type", "online")
	AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline")

	// ApprovalForce требует от пользователя подтверждения запроса разрешений
	ApprovalForce AuthCodeOption = SetAuthURLParam("prompt", "consent")
)

func S256ChallengeOption

func S256ChallengeOption(verifier string) AuthCodeOption

S256ChallengeOption создает PKCE challenge из верификатора методом S256. Должен передаваться только в Config.AuthCodeURL или Config.DeviceAuth.

func SetAuthURLParam

func SetAuthURLParam(key, value string) AuthCodeOption

SetAuthURLParam создает AuthCodeOption для передачи параметров key/value на endpoint авторизации провайдера.

func VerifierOption

func VerifierOption(verifier string) AuthCodeOption

VerifierOption возвращает AuthCodeOption с верификатором кода PKCE. Должен передаваться только в Config.Exchange или Config.DeviceAccessToken.


type AuthStyle

type AuthStyle int

AuthStyle определяет способ аутентификации запросов токенов.

Варианты:

const (
	// Автоопределение стиля аутентификации
	AuthStyleAutoDetect AuthStyle = 0
	
	// Передача client_id и client_secret в теле POST
	AuthStyleInParams AuthStyle = 1
	
	// Использование HTTP Basic Authorization OAuth2 RFC 6749 section 2.3.1.
	AuthStyleInHeader AuthStyle = 2
)

type Config

type Config struct {
    // ClientID - публичный идентификатор вашего приложения,
    // выдается провайдером при регистрации OAuth-клиента
    ClientID     string
    
    // ClientSecret - секретный ключ вашего приложения,
    // должен храниться безопасно (не в клиентском коде)
    ClientSecret string
    
    // Endpoint - содержит URL-адреса сервера авторизации:
    //   AuthURL - endpoint для получения authorization code
    //   TokenURL - endpoint для обмена code на access token
    Endpoint     Endpoint
    
    // RedirectURL - URL, на который провайдер перенаправит
    // пользователя после авторизации. Должен точно совпадать
    // с URL, зарегистрированным у провайдера
    RedirectURL  string
    
    // Scopes - запрашиваемые области доступа (разрешения),
    // определяют, к каким ресурсам будет доступ у приложения
    Scopes       []string
}

Config описывает стандартный 3-этапный OAuth2-поток с информацией о клиентском приложении и URL endpoint’ов сервера.

Пример
package main

import (
	"context"
	"fmt"
	"log"

	"golang.org/x/oauth2"
)

func main() {
	ctx := context.Background()
	conf := &oauth2.Config{
		ClientID:     "ВАШ_CLIENT_ID", 
		ClientSecret: "ВАШ_CLIENT_SECRET",
		Scopes:       []string{"ДОСТУП1", "ДОСТУП2"},
		Endpoint: oauth2.Endpoint{
			AuthURL:  "https://provider.com/o/oauth2/auth",  // URL авторизации
			TokenURL: "https://provider.com/o/oauth2/token", // URL получения токена
		},
	}

	// Используем PKCE для защиты от CSRF атак
	// Спецификация: https://www.ietf.org/archive/id/draft-ietf-oauth-security-topics-22.html#name-countermeasures-6
	verifier := oauth2.GenerateVerifier() // Генерируем верификатор для PKCE

	// Перенаправляем пользователя на страницу согласия для запроса разрешений
	// на указанные выше области доступа (scopes)
	url := conf.AuthCodeURL(
		"state",                          // Уникальный state для защиты
		oauth2.AccessTypeOffline,          // Запрашиваем refresh-токен  
		oauth2.S256ChallengeOption(verifier), // Добавляем PKCE challenge
	)
	fmt.Printf("Перейдите по URL для авторизации: %v", url)

	// Получаем authorization code из redirect URL.
	// Exchange выполнит обмен кода на токен доступа.
	// HTTP клиент от conf.Client будет автоматически обновлять токен.
	var code string
	if _, err := fmt.Scan(&code); err != nil {
		log.Fatal(err)
	}
	
	// Обмениваем код на токен, передавая верификатор PKCE
	tok, err := conf.Exchange(ctx, code, oauth2.VerifierOption(verifier))
	if err != nil {
		log.Fatal(err)
	}

	// Создаем HTTP клиент с автоматическим обновлением токенов
	client := conf.Client(ctx, tok)
	client.Get("...") // Делаем авторизованные запросы
}
Пример CustomHTTP
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"time"

	"golang.org/x/oauth2"
)

func main() {
	ctx := context.Background()

	// Конфигурация OAuth2 клиента
	conf := &oauth2.Config{
		ClientID:     "ВАШ_CLIENT_ID",      // Идентификатор клиента
		ClientSecret: "ВАШ_CLIENT_SECRET",  // Секретный ключ клиента
		Scopes:       []string{"ДОСТУП1", "ДОСТУП2"},  // Запрашиваемые разрешения
		Endpoint: oauth2.Endpoint{
			TokenURL: "https://provider.com/o/oauth2/token",  // URL для получения токена
			AuthURL:  "https://provider.com/o/oauth2/auth",   // URL для авторизации
		},
	}

	// Перенаправляем пользователя на страницу авторизации для получения разрешений
	// на указанные области доступа (scopes)
	url := conf.AuthCodeURL("state", oauth2.AccessTypeOffline)  // "state" для защиты от CSRF
	fmt.Printf("Перейдите по ссылке для авторизации: %v", url)

	// Получаем код авторизации из redirect URL.
	// Exchange выполняет обмен кода на токен доступа.
	// HTTP клиент, возвращаемый conf.Client, будет автоматически обновлять токен.
	var code string
	if _, err := fmt.Scan(&code); err != nil {
		log.Fatal(err)
	}

	// Используем кастомный HTTP клиент с таймаутом 2 секунды для запроса токена
	httpClient := &http.Client{Timeout: 2 * time.Second}
	ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)

	// Получаем токен доступа
	tok, err := conf.Exchange(ctx, code)
	if err != nil {
		log.Fatal(err)
	}

	// Создаем HTTP клиент с автоматической авторизацией
	client := conf.Client(ctx, tok)
	_ = client  // Используйте client для авторизованных запросов
}

func (*Config) AuthCodeURL

func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string

AuthCodeURL возвращает URL страницы согласия OAuth 2.0 провайдера, которая явно запрашивает разрешения для требуемых областей доступа (scopes).

Параметры:

  1. state
    Случайное значение (опaque), используемое клиентом для поддержания состояния между запросом и callback-вызовом. Сервер авторизации включает это значение при перенаправлении пользователя обратно в клиентское приложение.

  2. opts (дополнительные опции)
    Может включать:

    • AccessTypeOnline или AccessTypeOffline - тип доступа
    • ApprovalForce - принудительное подтверждение разрешений

Защита от CSRF-атак:

  1. Рекомендуемый способ:
    Включите PKCE challenge через S256ChallengeOption.
    Примечание: Не все серверы поддерживают PKCE.

  2. Альтернативный способ:
    Генерация случайного параметра state с последующей проверкой после обмена токена.

Ссылки на стандарты:

func (*Config) Client

func (c *Config) Client(ctx context.Context, t *Token) *http.Client

Клиент возвращает HTTP-клиента, используя предоставленный токен. Токен будет автоматически обновляться по мере необходимости. Базовый HTTP-транспорт будет получен с использованием предоставленного контекста. Возвращенный клиент и его Transport не должны быть изменены.

func (*Config) DeviceAccessToken

func (c *Config) DeviceAccessToken(ctx context.Context, da *DeviceAuthResponse, opts ...AuthCodeOption) (*Token, error)

DeviceAccessToken опрашивает сервер для обмена device code на токен.

func (*Config) DeviceAuth

func (c *Config) DeviceAuth(ctx context.Context, opts ...AuthCodeOption) (*DeviceAuthResponse, error)

DeviceAuth возвращает структуру с device code для авторизации на другом устройстве.

Пример
var config Config
ctx := context.Background()
response, err := config.DeviceAuth(ctx)
if err != nil {
	panic(err)
}
fmt.Printf("please enter code %s at %s\n", response.UserCode, response.VerificationURI)
token, err := config.DeviceAccessToken(ctx, response)
if err != nil {
	panic(err)
}
fmt.Println(token)

func (*Config) Exchange

func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error)

Выполняет обмен authorization code на токен доступа.

Использование: Вызывается после перенаправления пользователя обратно на Redirect URI (URL, полученный из AuthCodeURL).

Параметры:

  • ctx - контекст, может содержать кастомный HTTP-клиент (см. переменную HTTPClient)
  • code - authorization code из параметра http.Request.FormValue("code")
  • opts - опции, при использовании PKCE должен включать VerifierOption

Безопасность:

  1. Обязательно проверяйте параметр state (из http.Request.FormValue("state")) перед вызовом для защиты от CSRF
  2. Для PKCE передавайте верификатор через VerifierOption

func (*Config) PasswordCredentialsToken

func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error)

Получает токен по связке username/password (Resource Owner Password Credentials flow).

Рекомендации RFC 6749: Следует использовать ТОЛЬКО при:

  • Высокой степени доверия между клиентом и владельцем ресурса
  • Когда клиент является частью ОС или привилегированного приложения
  • При отсутствии других доступных способов авторизации

Ссылка: RFC 6749 Section 4.3

Параметры:

  • ctx - может содержать кастомный HTTP-клиент
  • username, password - учетные данные владельца ресурса

Примечание: Этот grant type считается менее безопасным и должен применяться в исключительных случаях.

func (*Config) TokenSource

func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource

TokenSource возвращает источник токенов с автоматическим обновлением.


type DeviceAuthResponse

type DeviceAuthResponse struct {
    // DeviceCode - код устройства для OAuth-потока
    DeviceCode string `json:"device_code"`
    
    // UserCode - код, который пользователь должен ввести
    // на странице верификации
    UserCode string `json:"user_code"`
    
    // VerificationURI - URL страницы, куда пользователь
    // должен ввести user code
    VerificationURI string `json:"verification_uri"`
    
    // VerificationURIComplete (опционально) - полный URL верификации
    // с уже подставленным user code. Обычно отображается пользователю
    // в графической форме (например, QR-код)
    VerificationURIComplete string `json:"verification_uri_complete,omitempty"`
    
    // Expiry - время истечения срока действия 
    // device code и user code
    Expiry time.Time `json:"expires_in,omitempty"`
    
    // Interval - интервал в секундах между запросами
    // на проверку авторизации (polling)
    Interval int64 `json:"interval,omitempty"`
}

DeviceAuthResponse описывает успешный ответ Device Authorization по RFC 8628.

func (DeviceAuthResponse) MarshalJSON

func (d DeviceAuthResponse) MarshalJSON() ([]byte, error)

func (*DeviceAuthResponse) UnmarshalJSON

func (c *DeviceAuthResponse) UnmarshalJSON(data []byte) error

type Endpoint

type Endpoint struct {
    AuthURL       string    // URL endpoint'а авторизации (для получения authorization code)
    DeviceAuthURL string    // URL для Device Flow авторизации (RFC 8628)
    TokenURL      string    // URL endpoint'а получения токенов (для обмена code на token)
    AuthStyle     AuthStyle // Предпочтительный метод аутентификации клиента
}

Предназначение: Содержит все необходимые URL для OAuth 2.0 flow.

Использование: Конфигурация клиента для взаимодействия с OAuth провайдером.

type RetrieveError

type RetrieveError struct {
    Response         *http.Response // HTTP-ответ сервера
    Body             []byte         // Тело ответа (может быть усечено)
    ErrorCode        string         // Код ошибки OAuth (RFC 6749 Section 5.2)
    ErrorDescription string         // Человекочитаемое описание ошибки
    ErrorURI         string         // Ссылка на документацию по ошибке
}

RetrieveError - ошибка, возвращаемая при неверном статусе HTTP или ошибке OAuth2.

Предназначение: Ошибки, возвращаемые OAuth сервером.

Особенности:

  • Соответствует стандарту OAuth 2.0 (RFC 6749)
  • Включает как HTTP-детали, так и специфичные OAuth ошибки

type Token

type Token struct {
    AccessToken  string    // Основной токен доступа
    TokenType    string    // Тип токена (обычно "Bearer")
    RefreshToken string    // Токен для обновления (опционально)
    Expiry       time.Time // Время истечения срока действия
    ExpiresIn    int64     // Срок жизни токена в секундах
}

Token содержит учетные данные для авторизации запросов.

Предназначение: Хранит OAuth 2.0 токены и метаданные.

  • AccessToken всегда обязателен
  • RefreshToken может отсутствовать в некоторых flow
  • Expiry вычисляется из ExpiresIn при получении токена

type TokenSource

type TokenSource interface {
	Token() (*Token, error) // Возвращает текущий/новый токен
}

TokenSource - любой источник, который может возвращать токен.

Предназначение: Абстракция для источников токенов.

Реализации:

  • StaticTokenSource (фиксированный токен)
  • ReuseTokenSource (с автоматическим обновлением)
  • Config.TokenSource (получение токенов из Config)

type Transport

type Transport struct {
    Source TokenSource         // Источник токенов для авторизации
    Base   http.RoundTripper   // Базовый RoundTripper (по умолчанию http.DefaultTransport)
}

Transport - это http.RoundTripper для OAuth 2.0 запросов.

Предназначение: Добавляет OAuth-авторизацию к HTTP-запросам.

Принцип работы:

  • Получает токен из Source
  • Добавляет Authorization header
  • Делегирует запрос базовому RoundTripper

1 - Пакет jwt (JSON Web Token)

Пакет jwt реализует поток OAuth 2.0 с использованием JSON Web Token, известный как “двухногая OAuth 2.0” (two-legged OAuth 2.0).

Спецификация: https://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-12

Типы

type Config

type Config struct {
    // Email - идентификатор OAuth-клиента
    Email string

    // PrivateKey содержит содержимое RSA-ключа или PEM-файла
    PrivateKey []byte

    // PrivateKeyID - необязательный идентификатор ключа
    PrivateKeyID string

    // Subject - необязательный пользователь для имперсонации
    Subject string

    // Scopes - запрашиваемые области доступа
    Scopes []string

    // TokenURL - endpoint для JWT-потока
    TokenURL string

    // Expires - срок действия токена
    Expires time.Duration

    // Audience - целевая аудитория запроса
    Audience string

    // PrivateClaims - кастомные JWT-claims
    PrivateClaims map[string]any

    // UseIDToken - использовать ID-токен вместо access-токена
    UseIDToken bool
}

Config содержит конфигурацию для получения токенов через JWT (“двухногая OAuth 2.0”).

Пример
package main

import (
	"context"

	"golang.org/x/oauth2/jwt"
)

func main() {
	ctx := context.Background()
	conf := &jwt.Config{
		Email: "xxx@developer.com",
		// The contents of your RSA private key or your PEM file
		// that contains a private key.
		// If you have a p12 file instead, you
		// can use `openssl` to export the private key into a pem file.
		//
		//    $ openssl pkcs12 -in key.p12 -out key.pem -nodes
		//
		// It only supports PEM containers with no passphrase.
		PrivateKey: []byte("-----BEGIN RSA PRIVATE KEY-----..."),
		Subject:    "user@example.com",
		TokenURL:   "https://provider.com/o/oauth2/token",
	}
	// Initiate an http.Client, the following GET request will be
	// authorized and authenticated on the behalf of user@example.com.
	client := conf.Client(ctx)
	client.Get("...")
}

Методы Config

func (*Config) Client

func (c *Config) Client(ctx context.Context) *http.Client

Client возвращает HTTP-клиент, который автоматически добавляет Authorization-заголовки с токенами, полученными из конфигурации.

Возвращенный клиент и его Transport не должны изменяться.

func (*Config) TokenSource

func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource

TokenSource возвращает источник токенов JWT, используя конфигурацию и HTTP-клиент из переданного контекста.

Особенности реализации

  1. Формат ключей:

    • Поддерживаются RSA-ключи и PEM-файлы без пароля
    • Для конвертации PKCS#12 в PEM используйте:
      openssl pkcs12 -in key.p12 -out key.pem -nodes
      
  2. Кастомные claims:

  3. Аудитория:

    • Если Audience не указан, используется TokenURL
  4. Тип токена:

    • При UseIDToken=true будет использоваться ID-токен вместо access-токена

2 - Пакет jws (JSON Web Signature)

Пакет jws предоставляет частичную реализацию кодирования и декодирования JSON Web Signature. Существует для поддержки пакета golang.org/x/oauth2.

Устарело: этот пакет не предназначен для публичного использования и может быть удален в будущем. Существует только для внутреннего использования. Рекомендуется использовать другой JWS-пакет или скопировать этот пакет в свой исходный код.

Функции

func Encode

func Encode(header *Header, c *ClaimSet, key *rsa.PrivateKey) (string, error)

Encode кодирует подписанный JWS с предоставленными заголовком и набором claims. Использует crypto/rsa.SignPKCS1v15 с указанным RSA-приватным ключом.

func EncodeWithSigner

func EncodeWithSigner(header *Header, c *ClaimSet, sg Signer) (string, error)

EncodeWithSigner кодирует заголовок и набор claims с использованием предоставленного подписывающего устройства.

func Verify

func Verify(token string, key *rsa.PublicKey) error

Verify проверяет, была ли подпись JWT-токена создана приватным ключом, соответствующим предоставленному публичному ключу.

Типы

type ClaimSet

type ClaimSet struct {
    Iss   string `json:"iss"`             // email клиентского приложения
    Scope string `json:"scope,omitempty"` // запрашиваемые разрешения
    Aud   string `json:"aud"`             // целевая аудитория (опционально)
    Exp   int64  `json:"exp"`             // время истечения (Unix epoch)
    Iat   int64  `json:"iat"`             // время выдачи (Unix epoch)
    Typ   string `json:"typ,omitempty"`   // тип токена (опционально)
    Sub   string `json:"sub,omitempty"`   // email для делегированного доступа
    Prn   string `json:"prn,omitempty"`   // устаревший аналог Sub
    PrivateClaims map[string]any `json:"-"` // кастомные claims
}

ClaimSet содержит информацию о JWT-подписи, включая запрашиваемые разрешения, цель токена, издателя, время выдачи и срок действия.

func Decode

func Decode(payload string) (*ClaimSet, error)

Decode декодирует набор claims из JWS-полезной нагрузки.

type Header

type Header struct {
    Algorithm string `json:"alg"`  // алгоритм подписи
    Typ       string `json:"typ"`  // тип токена
    KeyID     string `json:"kid,omitempty"` // идентификатор ключа (опционально)
}

Header представляет заголовок для подписанных JWS-полезных нагрузок.

type Signer

type Signer func(data []byte) (sig []byte, err error)

Signer возвращает подпись для предоставленных данных.

Особенности реализации

  1. Поддержка алгоритмов:

    • Основная реализация использует RSA с PKCS1v15
    • Возможность подключения кастомных подписывающих устройств
  2. Устаревшие поля:

    • Поле Prn сохраняется для обратной совместимости
    • Рекомендуется использовать Sub вместо Prn
  3. Кастомные claims:

    • Поддерживаются через поле PrivateClaims
    • Не включаются в стандартную JSON-маршализацию
  4. Безопасность:

    • Пакет помечен как устаревший для публичного использования
    • Рекомендуется использовать более полные реализации JWS

3 - Пакет authhandler (Three-Legged OAuth 2.0)

Пакет authhandler реализует TokenSource для поддержки “трехногового OAuth 2.0” через кастомный AuthorizationHandler.

Функции

func TokenSource

func TokenSource(
    ctx context.Context, 
    config *oauth2.Config, 
    state string, 
    authHandler AuthorizationHandler,
) oauth2.TokenSource

TokenSource возвращает oauth2.TokenSource, который получает access-токены, используя трехноговый OAuth-поток.

Параметры:

  • ctx - контекст для операции Exchange
  • config - полная конфигурация OAuth (AuthURL, TokenURL, Scope)
  • state - уникальная строка состояния для защиты от CSRF
  • authHandler - обработчик авторизации для получения согласия пользователя

Особенности:

  • Проверяет соответствие параметра state в запросе и ответе
  • Обменивает auth-код на OAuth-токен после проверки

func TokenSourceWithPKCE

func TokenSourceWithPKCE(
    ctx context.Context,
    config *oauth2.Config,
    state string,
    authHandler AuthorizationHandler, 
    pkce *PKCEParams,
) oauth2.TokenSource

TokenSourceWithPKCE - расширенная версия с поддержкой PKCE (Proof Key for Code Exchange).

Дополнительный параметр:

  • pkce - параметры для защиты от CSRF через code challenge и code verifier

Рекомендации:

Типы

type AuthorizationHandler

type AuthorizationHandler func(authCodeURL string) (code string, state string, err error)

AuthorizationHandler - обработчик для трехногового OAuth, который:

  1. Перенаправляет пользователя по URL для получения согласия
  2. Возвращает auth-код и состояние после подтверждения

type PKCEParams

type PKCEParams struct {
    Challenge       string // Зашифрованный code verifier (base64-url)
    ChallengeMethod string // Метод шифрования (напр. S256)
    Verifier        string // Оригинальный секрет (незашифрованный)
}

PKCEParams содержит параметры для защиты потока PKCE.

Особенности реализации

  1. Безопасность:

    • Обязательная проверка параметра state
    • Поддержка современных методов защиты PKCE
  2. Гибкость:

    • Возможность кастомной обработки авторизации
    • Поддержка различных методов шифрования PKCE
  3. Рекомендации:

    • Всегда использовать уникальный state для каждого запроса
    • Для мобильных приложений предпочтительнее TokenSourceWithPKCE

4 - Пакет clientcredentials OAuth 2.0 Client Credentials Flow

Пакет реализует поток OAuth 2.0 учетные данные клиента client credentials, также известный как двухногая OAuth 2.0

Используется, когда:

  • Клиент действует от своего имени
  • Клиент является владельцем ресурса
  • Запрашивается доступ к защищенным ресурсам на основе предварительной авторизации

Спецификация: https://tools.ietf.org/html/rfc6749#section-4.4

Тип Config

type Config struct {
    // ClientID - идентификатор приложения
    ClientID string
    
    // ClientSecret - секрет приложения  
    ClientSecret string
    
    // TokenURL - endpoint сервера для получения токенов
    TokenURL string
    
    // Scopes - запрашиваемые разрешения (опционально)
    Scopes []string
    
    // EndpointParams - дополнительные параметры запроса
    EndpointParams url.Values
    
    // AuthStyle - способ аутентификации клиента
    AuthStyle oauth2.AuthStyle
}

Config описывает двухноговый OAuth2 поток, содержащий информацию о клиентском приложении и URL endpoint’ов сервера.

Методы Config

func (*Config) Client

func (c *Config) Client(ctx context.Context) *http.Client

Возвращает HTTP-клиент, который:

  • Автоматически добавляет токены авторизации
  • Обновляет токены по истечении срока
  • Использует HTTP-клиент из контекста (через oauth2.HTTPClient)

Важно: возвращенный клиент и его Transport не должны изменяться.

func (*Config) Token

func (c *Config) Token(ctx context.Context) (*oauth2.Token, error) 

Получает токен, используя учетные данные клиента (client credentials).

Может использовать кастомный HTTP-клиент из контекста.

func (*Config) TokenSource

func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource

Возвращает источник токенов, который:

  • Возвращает текущий токен, пока он действителен
  • Автоматически обновляет токен при истечении срока
  • Использует client ID и client secret для обновления

Рекомендация: большинству пользователей следует использовать Config.Client вместо прямого использования TokenSource.

Особенности реализации

  1. Сценарии использования:

    • Сервер-серверное взаимодействие
    • Микросервисная архитектура
    • Фоновые процессы без участия пользователя
  2. Безопасность:

    • ClientSecret должен храниться защищенно
    • Рекомендуется использовать HTTPS для всех запросов
  3. Гибкость:

    • Поддержка различных методов аутентификации (AuthStyle)
    • Возможность передачи дополнительных параметров (EndpointParams)