Documentation
¶
Overview ¶
Package oauth2 is a pure-Go (CGO-free) reimplementation of the deterministic protocol pieces of Ruby's `oauth2` gem (the OAuth2 client): building authorization URLs and token-request specifications, and parsing token and error responses. It is the interpreter-independent core the gem shares across grant strategies, without any Ruby runtime.
What it is — and isn't ¶
The URL/param construction (authorize-URL query encoding, per-grant token request bodies, basic-auth vs request-body client authentication, PKCE) and response parsing (JSON / form-encoded token bodies, error extraction) are fully deterministic and need no interpreter, so they live here as pure Go. The HTTP round-trip itself is a host seam: the library builds a Request and a host (wiring to go-ruby-net-http / faraday) turns it into a Response via a RoundTripper. This mirrors the gem, where Faraday performs the transport.
Flow ¶
client := oauth2.NewClient("id", "secret", oauth2.Options{
Site: "https://provider.example.com",
AuthorizeURL: "/oauth/authorize",
TokenURL: "/oauth/token",
})
// 1. Build the authorization URL to redirect the user to.
url := client.AuthCode().AuthorizeURL(oauth2.Params{
{"redirect_uri", "https://app/cb"}, {"scope", "read"}, {"state", "xyz"},
})
// 2. Build the token request for the returned code, run it through the host
// transport, and parse the response into an AccessToken.
req := client.AuthCode().GetTokenRequest("thecode", oauth2.Params{
{"redirect_uri", "https://app/cb"},
})
resp, _ := transport.RoundTrip(req) // host seam
tok, _ := client.ParseToken(resp)
Value model ¶
Parameters and parsed bodies are carried as an ordered string→string Map; residual token fields live in AccessToken.Params. A host (go-embedded-ruby / rbgo) maps its Ruby Hash/AccessToken objects to and from these shapes.
Index ¶
- func CodeChallenge(verifier string, method PKCEMethod) string
- type AccessToken
- func (t *AccessToken) ApplyTo(headers, params, body *Map) (h, p, b *Map)
- func (t *AccessToken) AuthorizationHeader() string
- func (t *AccessToken) Expired() bool
- func (t *AccessToken) Expires() bool
- func (t *AccessToken) Get(key string) (string, bool)
- func (t *AccessToken) RefreshRequest(extra ...Param) (*Request, error)
- func (t *AccessToken) Scope() string
- func (t *AccessToken) ToHash() *Map
- func (t *AccessToken) TokenType() string
- type Assertion
- type AuthCode
- type AuthScheme
- type Client
- func (c *Client) Assertion() Assertion
- func (c *Client) AuthCode() AuthCode
- func (c *Client) AuthorizeURL() string
- func (c *Client) ClientCredentials() ClientCredentials
- func (c *Client) ID() string
- func (c *Client) ParseRefreshToken(resp *Response, prevRefresh string) (*AccessToken, error)
- func (c *Client) ParseToken(resp *Response) (*AccessToken, error)
- func (c *Client) Password() Password
- func (c *Client) Refresh() Refresh
- func (c *Client) TokenURL() string
- type ClientCredentials
- type Error
- type Map
- type Mode
- type Options
- type PKCEMethod
- type Pair
- type Param
- type Params
- type Password
- type Refresh
- type Request
- type Response
- type RoundTripFunc
- type RoundTripper
- type TokenMethod
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CodeChallenge ¶
func CodeChallenge(verifier string, method PKCEMethod) string
CodeChallenge derives the PKCE code_challenge for a code_verifier under the given method (RFC 7636 §4.2). For PKCES256 it returns the base64url (no padding) of SHA-256(verifier); for PKCEPlain it returns the verifier unchanged. An unknown method is treated as plain.
The verifier and challenge are added to the authorize URL and token request as the code_challenge / code_challenge_method / code_verifier params by the caller; this helper only performs the deterministic transformation.
Types ¶
type AccessToken ¶
type AccessToken struct {
// Token is the bearer/opaque access-token string.
Token string
// RefreshToken is the refresh token, or "" if none was issued.
RefreshToken string
// ExpiresAt is the absolute expiry as a Unix timestamp, or 0 when the token
// does not expire (Expires reports whether it is set).
ExpiresAt int64
// Params holds the residual response members not promoted to a named field
// (token_type, scope, and any provider extras), in response order.
Params *Map
// Mode / HeaderFormat / ParamName control resource-request injection.
Mode Mode
HeaderFormat string
ParamName string
// contains filtered or unexported fields
}
AccessToken is a parsed OAuth2 access token, mirroring OAuth2::AccessToken. It binds the token to its issuing Client so [AccessToken.Refresh] can build the refresh request. The value model rbgo maps: Token/RefreshToken/ExpiresAt/ TokenType plus the residual Params.
func AccessTokenFromHash ¶
func AccessTokenFromHash(client *Client, h map[string]any, order []string) *AccessToken
AccessTokenFromHash builds an AccessToken from a parsed token-response map, mirroring OAuth2::AccessToken.from_hash. It promotes access_token, refresh_token, token_type, expires_at, expires_in, mode, header_format and param_name; every other member is retained in Params (in the given order). When expires_in is present and expires_at is not, ExpiresAt is derived as now + expires_in (the gem's behaviour).
order lists the response keys in their original order so Params preserves it; pass nil to fall back to unspecified iteration for the residuals.
func NewAccessToken ¶
func NewAccessToken(client *Client, token string) *AccessToken
NewAccessToken builds a token bound to client with default injection options (header mode, "Bearer %s", "access_token"), like OAuth2::AccessToken.new.
func (*AccessToken) ApplyTo ¶
func (t *AccessToken) ApplyTo(headers, params, body *Map) (h, p, b *Map)
ApplyTo injects the token into a resource request per the token's Mode. It mutates and returns the given headers, params and body maps (any may be nil and will be created on demand for its mode). This mirrors OAuth2::AccessToken#headers / the request-mode handling.
- ModeHeader: sets Authorization to HeaderFormat with the token substituted.
- ModeQuery: sets params[ParamName] = token.
- ModeBody: sets body[ParamName] = token.
func (*AccessToken) AuthorizationHeader ¶
func (t *AccessToken) AuthorizationHeader() string
AuthorizationHeader returns the Authorization header value for the header mode (HeaderFormat with the token substituted), a convenience over AccessToken.ApplyTo.
func (*AccessToken) Expired ¶
func (t *AccessToken) Expired() bool
Expired reports whether the token has expired: it must have an expiry and that expiry must be at or before now (OAuth2::AccessToken#expired?).
func (*AccessToken) Expires ¶
func (t *AccessToken) Expires() bool
Expires reports whether the token carries an expiry (OAuth2::AccessToken#expires?).
func (*AccessToken) Get ¶
func (t *AccessToken) Get(key string) (string, bool)
Get returns a residual param by name (OAuth2::AccessToken#[]).
func (*AccessToken) RefreshRequest ¶
func (t *AccessToken) RefreshRequest(extra ...Param) (*Request, error)
RefreshRequest builds the token-endpoint Request that exchanges this token's refresh token for a new access token, mirroring OAuth2::AccessToken#refresh's request. extra merges additional body params. It returns an error when the token has no refresh token (as the gem raises).
func (*AccessToken) Scope ¶
func (t *AccessToken) Scope() string
Scope returns the scope residual param, or "".
func (*AccessToken) ToHash ¶
func (t *AccessToken) ToHash() *Map
ToHash renders the token as an ordered map matching OAuth2::AccessToken#to_hash: the residual params first (in order), then access_token, refresh_token, expires_at, mode, header_format, param_name. refresh_token and expires_at are omitted when unset.
func (*AccessToken) TokenType ¶
func (t *AccessToken) TokenType() string
TokenType returns the token_type residual param (e.g. "bearer"), or "".
type Assertion ¶
type Assertion struct {
// contains filtered or unexported fields
}
Assertion is the assertion (JWT-bearer) grant strategy (OAuth2::Strategy::Assertion). The signed assertion is supplied by the caller (or a host binding to go-ruby-jwt) as the `assertion` param.
func (Assertion) GetTokenRequest ¶
GetTokenRequest builds the assertion-grant token request. grantType is the grant_type URI (e.g. "urn:ietf:params:oauth:grant-type:jwt-bearer"); assertion is the signed JWT bearer assertion; extra carries any additional params.
type AuthCode ¶
type AuthCode struct {
// contains filtered or unexported fields
}
AuthCode is the authorization-code grant strategy (OAuth2::Strategy::AuthCode).
func (AuthCode) AuthorizeURL ¶
AuthorizeURL builds the authorization URL to redirect the user-agent to, mirroring OAuth2::Strategy::AuthCode#authorize_url. The client_id and response_type=code defaults are merged in unless params overrides them; every param (redirect_uri, scope, state, PKCE code_challenge, provider extras) is query-encoded with keys sorted, byte-faithful to the gem.
func (AuthCode) GetTokenRequest ¶
GetTokenRequest builds the token request that exchanges an authorization code for a token, mirroring OAuth2::Strategy::AuthCode#get_token. The body carries grant_type=authorization_code and the code, plus any extra params (typically redirect_uri and a PKCE code_verifier); client authentication is applied per the client's auth scheme.
type AuthScheme ¶
type AuthScheme string
AuthScheme selects how client credentials authenticate the token request, mirroring OAuth2::Client's :auth_scheme.
const ( // AuthBasic sends the credentials as an HTTP Basic Authorization header // (base64("id:secret")); the default. AuthBasic AuthScheme = "basic_auth" // AuthRequestBody sends client_id and client_secret as form-body params. AuthRequestBody AuthScheme = "request_body" // AuthTLSClientAuth sends only client_id in the body (the secret is carried // by the mutual-TLS certificate, out of band), per RFC 8705. AuthTLSClientAuth AuthScheme = "tls_client_auth" )
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is an OAuth2 client bound to a set of credentials and endpoints, mirroring OAuth2::Client. It builds authorization URLs and token requests and parses responses; the HTTP transport is a host seam (see RoundTripper).
func NewClient ¶
NewClient returns a Client for the given client id and secret. opts fills in the site and endpoints; unset endpoint paths default to the gem's "oauth/authorize" and "oauth/token".
func (*Client) AuthorizeURL ¶
AuthorizeURL returns the fully-qualified authorization endpoint (AuthorizeURL resolved against Site), matching OAuth2::Client#authorize_url with no params.
func (*Client) ClientCredentials ¶
func (c *Client) ClientCredentials() ClientCredentials
ClientCredentials returns the client-credentials strategy for this client.
func (*Client) ParseRefreshToken ¶
func (c *Client) ParseRefreshToken(resp *Response, prevRefresh string) (*AccessToken, error)
ParseRefreshToken is like Client.ParseToken but preserves prevRefresh when the response omits a new refresh_token, matching OAuth2::AccessToken#refresh.
func (*Client) ParseToken ¶
func (c *Client) ParseToken(resp *Response) (*AccessToken, error)
ParseToken turns a token-endpoint Response into an AccessToken, mirroring OAuth2::Client#get_token's success path: a >= 400 status becomes an Error; otherwise the parsed body is promoted into an AccessToken bound to this client. prevRefresh, when non-empty, is retained as the refresh token if the response omits one (the gem's refresh behaviour, which keeps the old refresh token).
type ClientCredentials ¶
type ClientCredentials struct {
// contains filtered or unexported fields
}
ClientCredentials is the client-credentials grant strategy (OAuth2::Strategy::ClientCredentials).
func (ClientCredentials) GetTokenRequest ¶
func (s ClientCredentials) GetTokenRequest(extra Params) *Request
GetTokenRequest builds the client-credentials token request (grant_type=client_credentials plus any extra params such as scope).
type Error ¶
type Error struct {
Response *Response
Code string
Description string
// contains filtered or unexported fields
}
Error is raised for an unsuccessful token response, mirroring OAuth2::Error. It carries the originating Response and the extracted OAuth error fields. Code is the `error` member of the parsed body (or "" if absent); Description is `error_description`. Message reproduces the gem's assembled message.
type Map ¶
type Map struct {
// contains filtered or unexported fields
}
Map is an insertion-ordered string→string map used for request parameters and parsed form bodies. Ruby's `oauth2` gem threads plain Hashes through the flow; this ordered map mirrors that while giving deterministic iteration for the (unsorted) request-body specs and stable, sorted output for URLs.
func (*Map) Set ¶
Set inserts or replaces the entry for key, preserving the position of an existing key when it is overwritten (last write wins on value, first write wins on order — the gem's Hash semantics).
func (*Map) SetDefault ¶
SetDefault inserts key→val only if key is absent, mirroring the gem's habit of filling in a default (client_id, grant_type, response_type) without clobbering a caller-supplied override.
type Mode ¶
type Mode string
Mode selects how AccessToken.ApplyTo carries the token to a resource request, mirroring OAuth2::AccessToken's :mode.
const ( // ModeHeader carries the token in the Authorization header (the default). ModeHeader Mode = "header" // ModeQuery carries the token as a query parameter named by ParamName. ModeQuery Mode = "query" // ModeBody carries the token as a form-body parameter named by ParamName. ModeBody Mode = "body" )
type Options ¶
type Options struct {
// Site is the base URL against which relative AuthorizeURL/TokenURL resolve.
Site string
// AuthorizeURL is the authorization endpoint: an absolute URL, or a path
// resolved against Site. Defaults to "oauth/authorize".
AuthorizeURL string
// TokenURL is the token endpoint: an absolute URL, or a path resolved against
// Site. Defaults to "oauth/token".
TokenURL string
// AuthScheme selects client authentication (default AuthBasic).
AuthScheme AuthScheme
// TokenMethod is the token-request HTTP method (default TokenPost).
TokenMethod TokenMethod
}
Options configures a Client, mirroring the OAuth2::Client keyword options that affect URL/request construction. Empty fields take the gem's defaults.
type PKCEMethod ¶
type PKCEMethod string
PKCEMethod is a PKCE code-challenge transformation (RFC 7636).
const ( // PKCES256 is the SHA-256 transformation: challenge = BASE64URL(SHA256(verifier)). PKCES256 PKCEMethod = "S256" // PKCEPlain is the identity transformation: challenge = verifier. PKCEPlain PKCEMethod = "plain" )
type Param ¶
Param is one ordered key/value request parameter; a []Param (Params) lets callers supply parameters with a deterministic order (the gem accepts a Ruby Hash — here order is explicit for reproducibility).
type Password ¶
type Password struct {
// contains filtered or unexported fields
}
Password is the resource-owner password-credentials grant strategy (OAuth2::Strategy::Password).
type Refresh ¶
type Refresh struct {
// contains filtered or unexported fields
}
Refresh is the refresh-token grant strategy. It builds the request that exchanges a refresh token for a new access token (the request half of OAuth2::AccessToken#refresh, usable independently of an AccessToken).
type Request ¶
Request is the deterministic specification of a single HTTP round-trip the library builds for a token operation. The HTTP transport itself is a host seam: a host (wiring to go-ruby-net-http / faraday) turns a Request into a Response via a RoundTripper. All fields are byte-faithful to what the `oauth2` gem hands to Faraday.
- Method is "POST" or "GET" (from the client's token_method).
- URL is the fully-qualified token endpoint.
- Params carries the form fields when Method is GET (they go in the query string); it is empty for POST.
- Body carries the form fields when Method is POST (encoded application/x-www-form-urlencoded); it is empty for GET.
- Headers carries the request headers (Content-Type, and Authorization for the basic-auth scheme).
func (*Request) EncodedBody ¶
EncodedBody returns the request body form-encoded (sorted keys, %-escaped), suitable for an application/x-www-form-urlencoded POST. It is empty for a GET request.
type Response ¶
type Response struct {
Status int
Headers *Map
Body string
// contains filtered or unexported fields
}
Response is the raw HTTP response from the token endpoint, as returned by a RoundTripper. It mirrors OAuth2::Response: Status, Headers and the raw Body, with Response.Parsed lazily decoding the body by content type.
func NewResponse ¶
NewResponse builds a Response from its parts.
func (*Response) ContentType ¶
ContentType returns the response's Content-Type header value with any parameters (e.g. "; charset=utf-8") stripped and lower-cased, matching OAuth2::Response#content_type's effective media type.
func (*Response) Parsed ¶
Parsed decodes the body into a map keyed by string, dispatching on the content type exactly as OAuth2::Response does: a JSON media type (application/json, or any "+json") is JSON-decoded; a form media type (application/x-www-form-urlencoded) is form-decoded; anything else (or an undecodable body) yields an empty map. The result is memoised.
type RoundTripFunc ¶
RoundTripFunc adapts a function to the RoundTripper interface.
type RoundTripper ¶
RoundTripper is the host transport seam: it performs the HTTP round-trip for a built Request and returns the raw Response. Implementations live in the host (go-ruby-net-http / faraday); this package never opens a socket.
type TokenMethod ¶
type TokenMethod string
TokenMethod is the HTTP method used for the token request.
const ( // TokenPost issues the token request as a POST with a form body (default). TokenPost TokenMethod = "post" // TokenGet issues the token request as a GET with query params. TokenGet TokenMethod = "get" )
