Documentation
¶
Overview ¶
Package oauth2as is an library implementation of helpers for implementing the core OIDC specification (https://openid.net/specs/openid-connect-core-1_0.html). It aims to provide the tools needed to build a compliant implementation of the specification. Note: It does not _enforce_ all behaviours required by the spec, implementations that consume this should be sure to not introduce non-compliant behaviours.
Index ¶
- Constants
- type AlgorithmSigner
- type AuthGrant
- type AuthRequest
- type ClientOpt
- type ClientSource
- type Config
- type MemStorage
- func (m *MemStorage) CreateGrant(ctx context.Context, grant *StoredGrant) error
- func (m *MemStorage) ExpireGrant(ctx context.Context, id uuid.UUID) error
- func (m *MemStorage) GetGrant(ctx context.Context, id uuid.UUID) (*StoredGrant, error)
- func (m *MemStorage) GetGrantByAuthCode(ctx context.Context, authCode []byte) (*StoredGrant, error)
- func (m *MemStorage) GetGrantByRefreshToken(ctx context.Context, refreshToken []byte) (*StoredGrant, error)
- func (m *MemStorage) UpdateGrant(ctx context.Context, grant *StoredGrant) error
- type Server
- func (s *Server) GrantAuth(ctx context.Context, grant *AuthGrant) (redirectURI string, _ error)
- func (s *Server) ParseAuthRequest(req *http.Request) (*AuthRequest, error)
- func (s *Server) TokenHandler(w http.ResponseWriter, req *http.Request)
- func (s *Server) UserinfoHandler(w http.ResponseWriter, req *http.Request)
- type Storage
- type StoredGrant
- type TokenHandler
- type TokenRequest
- type TokenResponse
- type UserinfoHandler
- type UserinfoRequest
- type UserinfoResponse
Constants ¶
const ( // DefaultAuthValidityTime is used if the AuthValidityTime is not // configured. DefaultAuthValidityTime = 10 * time.Minute // DefaultCodeValidityTime is used if the CodeValidityTime is not // configured. DefaultCodeValidityTime = 60 * time.Second // DefaultIDTokenValidity is the default IDTokenValidity time. DefaultIDTokenValidity = 1 * time.Hour // DefaultsAccessTokenValidity is the default AccessTokenValdity time. DefaultsAccessTokenValidity = 1 * time.Hour // DefaultMaxRefreshTime is the default value sessions are refreshable for. DefaultMaxRefreshTime = 30 * 24 * time.Hour )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AlgorithmSigner ¶
type AlgorithmSigner interface { // PublicKeyset is used to verify issued tokens, i.e in the Userinfo // endpoint. jwt.PublicKeyset // SignWithAlgorithm should sign the payload with the given algorithm and // type header, and return the compact representation of the signed token. SignWithAlgorithm(ctx context.Context, alg, typHdr string, payload []byte) (string, error) // SupportedAlgorithms returns the list of JWT algorithms supported by this // signer. SupportedAlgorithms() []string }
type AuthGrant ¶
type AuthGrant struct { // Request is the corresponding authorization request that we are granting // access for. Request *AuthRequest // GrantedScopes are the scopes that were actually granted. GrantedScopes []string // UserID is the user ID that was granted access. This is used to form the subject // claim, and is provided on subsequent actions. UserID string // Metadata is arbitraty metadata that can be stored with the grant. Can be // used for auditing or tracking other information that is associated with // the grant. This is not sensitive, and can be accessed at any time. Metadata map[string]string // EncryptedMetadata is the encrypted metadata that can be stored with the // grant. This is only available to token callbacks. Can be used to store // sensitive, grant-specific information like upstream auth tokens. EncryptedMetadata map[string]string }
type AuthRequest ¶
type AuthRequest struct { // ClientID is the client ID that is requesting authentication. ClientID string // RedirectURI the client specified. This is an OPTIONAL field, if not // passed will be set to the zero value. If provided, it will have been // validated. RedirectURI string // State is the state value that was passed in the request. State string // Scopes is the list of scopes that the client is requesting. Scopes []string // CodeChallenge is the PKCE code challenge. If it is provided, it will be // S256 format. If not provided, it will be an empty string. CodeChallenge string // ACRValues is the list of ACR values that the client is requesting. ACRValues []string // Raw is the raw URL values that were passed in the request. Raw url.Values }
type ClientOpt ¶
type ClientOpt func(opts *clientOpts)
ClientOpt is a flag that can be set on a given client, to adjust various behaviours.
func ClientOptSigningAlg ¶
func ClientOptSigningAlg(alg jwt.SigningAlg) ClientOpt
func ClientOptSkipPKCE ¶
func ClientOptSkipPKCE() ClientOpt
ClientOptSkipPKCE indicates that the client is not required to use PKCE
type ClientSource ¶
type ClientSource interface { // IsValidClientID should return true if the passed client ID is valid IsValidClientID(_ context.Context, clientID string) (ok bool, err error) // ValidateClientSecret should confirm if the passed secret is valid for the // given client. If no secret is provided, clientSecret will be empty but // this will still be called. ValidateClientSecret(_ context.Context, clientID, clientSecret string) (ok bool, err error) // ValidateRedirectURI should return the list of valid redirect URIs. They // will be compared for an exact match, with the exception of loopback // addresses, which can have a variable port // (https://www.rfc-editor.org/rfc/rfc8252#section-7.3). RedirectURIs(_ context.Context, clientID string) ([]string, error) // ClientOpts returns the list of options for this client. See ClientOpt. ClientOpts(_ context.Context, clientID string) ([]ClientOpt, error) }
ClientSource is used for validating client informantion for the general flow
type Config ¶
type Config struct { // Issuer is the issuer we are serving for. Issuer string // Storage is the storage backend to use for the server. Storage Storage Clients ClientSource Signer AlgorithmSigner Logger *slog.Logger TokenHandler TokenHandler UserinfoHandler UserinfoHandler // AuthValidityTime is the maximum time an authorization flow/AuthID is // valid. This is the time from Starting to Finishing the authorization. The // optimal time here will be application specific, and should encompass how // long the app expects a user to complete the "upstream" authorization // process. Defaults to DefaultAuthValidityTime AuthValidityTime time.Duration // CodeValidityTime is the maximum time the authorization code is valid, // before it is exchanged for a token (code flow). This should be a short // value, as the exhange should generally not take long. Defaults to DefaultCodeValidityTime. CodeValidityTime time.Duration // IDTokenValidity sets the default validity for issued ID tokens. This can // be overridden on a per-request basis. IDTokenValidity time.Duration // AccessTokenValidity sets the default validity for issued access tokens. // This can be overridden on a per-request basis. Must be equal or less to // the IDTokenValitity time. AccessTokenValidity time.Duration // MaxRefreshTime sets the longest time a session can be refreshed for, from // the time it was created. This can be overridden on a per-request basis. // Defaults to DefaultMaxRefreshTime. Any refesh token may be considered // valid up until this time. MaxRefreshTime time.Duration }
Config is used to set the configuration for creating a server instance.
type MemStorage ¶
type MemStorage struct {
// contains filtered or unexported fields
}
MemStorage implements the Storage interface with an in-memory dataset. All items return nil when not found.
func NewMemStorage ¶
func NewMemStorage() *MemStorage
NewMemStorage creates a new in-memory storage instance.
func (*MemStorage) CreateGrant ¶
func (m *MemStorage) CreateGrant(ctx context.Context, grant *StoredGrant) error
CreateGrant stores a new grant in memory.
func (*MemStorage) ExpireGrant ¶
ExpireGrant removes a grant from memory.
func (*MemStorage) GetGrant ¶
func (m *MemStorage) GetGrant(ctx context.Context, id uuid.UUID) (*StoredGrant, error)
GetGrant retrieves a grant by its ID. Returns nil if not found.
func (*MemStorage) GetGrantByAuthCode ¶
func (m *MemStorage) GetGrantByAuthCode(ctx context.Context, authCode []byte) (*StoredGrant, error)
GetGrantByAuthCode retrieves a grant by its authorization code. Returns nil if not found.
func (*MemStorage) GetGrantByRefreshToken ¶
func (m *MemStorage) GetGrantByRefreshToken(ctx context.Context, refreshToken []byte) (*StoredGrant, error)
GetGrantByRefreshToken retrieves a grant by its refresh token. Returns nil if not found.
func (*MemStorage) UpdateGrant ¶
func (m *MemStorage) UpdateGrant(ctx context.Context, grant *StoredGrant) error
UpdateGrant updates an existing grant in memory.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
func (*Server) ParseAuthRequest ¶
func (s *Server) ParseAuthRequest(req *http.Request) (*AuthRequest, error)
func (*Server) TokenHandler ¶
func (s *Server) TokenHandler(w http.ResponseWriter, req *http.Request)
TokenHandler is used to handle the access token endpoint for code flow requests. This can handle both the initial access token request, as well as subsequent calls for refreshes.
If a handler returns an error, it will be checked and the endpoint will respond to the user appropriately. The session will not be invalidated automatically, it it the responsibility of the handler to delete if it requires this. * If the error implements an `Unauthorized() bool` method and the result of calling this is true, the caller will be notified of an `invalid_grant`. The error text will be returned as the `error_description` * All other errors will result an an InternalServerError
This will always return a response to the user, regardless of success or failure. As such, once returned the called can assume the HTTP request has been dealt with appropriately
https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens
func (*Server) UserinfoHandler ¶
func (s *Server) UserinfoHandler(w http.ResponseWriter, req *http.Request)
UserinfoHandler can handle a request to the userinfo endpoint. If the request is not valid, an error will be returned. Otherwise handler will be invoked with information about the requestor passed in. This handler should write the appropriate response data in JSON format to the passed writer.
https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
type Storage ¶
type Storage interface { // CreateGrant creates a new grant. CreateGrant(ctx context.Context, grant *StoredGrant) error // UpdateGrant updates an existing grant. UpdateGrant(ctx context.Context, grant *StoredGrant) error // ExpireGrant expires a grant. ExpireGrant(ctx context.Context, id uuid.UUID) error // GetGrant retrieves a grant by ID. If no grant is found, it should return // a nil grant. GetGrant(ctx context.Context, id uuid.UUID) (*StoredGrant, error) // GetGrantByAuthCode retrieves a grant by authorization code. If no grant // is found, it should return a nil grant. The code is a raw byte slice. GetGrantByAuthCode(ctx context.Context, authCode []byte) (*StoredGrant, error) // GetGrantByRefreshToken retrieves a grant by refresh token. If no grant // is found, it should return a nil grant. The token is a raw byte slice. GetGrantByRefreshToken(ctx context.Context, refreshToken []byte) (*StoredGrant, error) }
Storage is the interface for storing and retrieving grants.
type StoredGrant ¶
type StoredGrant struct { // ID is the unique identifier for this grant. ID uuid.UUID // AuthCode is the authorization code for the initial token exchange. AuthCode []byte // UserID is the user ID that was granted access. UserID string // ClientID is the client ID that was granted access. ClientID string // GrantedScopes are the scopes that were actually granted. GrantedScopes []string // Request captures the request that was used to grant access. Used for // finalizing the code flow. Request *AuthRequest // RefreshToken is the refresh token for the grant. RefreshToken []byte // GrantedAt is the time at which the grant was granted. GrantedAt time.Time // ExpiresAt is the time at which the grant will expire. ExpiresAt time.Time // Metadata is arbitrary metadata that can be stored with the grant. Metadata map[string]string // EncryptedMetadata stores the encrypted metadata associated with this // grant. EncryptedMetadata []byte }
type TokenHandler ¶
type TokenHandler func(_ context.Context, req *TokenRequest) (*TokenResponse, error)
type TokenRequest ¶
type TokenRequest struct { // GrantID is the ID of the grant that was used to obtain the token. GrantID uuid.UUID // UserID is the user ID that was granted access. UserID string // ClientID is the client ID that was used to obtain the token. ClientID string // GrantedScopes are the scopes that were granted. GrantedScopes []string // Metadata is the metadata that was associated with the grant. Metadata map[string]string // EncryptedMetadata is the decrypted metadata that was associated with the // grant. EncryptedMetadata map[string]string // IsRefresh indicates if this is a refresh token request. IsRefresh bool }
TokenRequest encapsulates the information from the initial request to the token endpoint. This is passed to the handler, to generate an appropriate response.
type TokenResponse ¶
type TokenResponse struct { // may be zero, if so defaulted IDTokenExpiry time.Time AccessTokenExpiry time.Time // IDClaims are the claims that will be included in the ID token. These will // be serialized to JSON, and then returned in the token. This is optional. // The following claims will always be overridden: // - iss // - iat // - auth_time // - nonce // The following claims will be defaulted if not set: // - sub // - exp // - aud IDClaims any // AccessTokenClaims is the claims that will be included in the access token. // The claims will be serialized to JSON, and then returned in the token. // The following claims will always be overridden: // - iss // - client_id // - iat // - jti // The following claims will be defaulted if not set: // - sub // - exp // - aud AccessTokenClaims any // RefreshTokenValidUntil indicates how long the returned refresh token should // be valid for, if one is issued. If zero, the default will be used. RefreshTokenValidUntil time.Time // Metadata is the metadata that was associated with the grant. If nil, the // existing metadata will be re-used. Metadata map[string]string // EncryptedMetadata is the encrypted metadata that was associated with the // grant. If nil, the existing encrypted metadata will be re-used. EncryptedMetadata map[string]string }
TokenResponse is returned by the token endpoint handler, indicating what it should actually return to the user.
type UserinfoHandler ¶
type UserinfoHandler func(ctx context.Context, uireq *UserinfoRequest) (*UserinfoResponse, error)
type UserinfoRequest ¶
type UserinfoRequest struct { // Subject is the sub of the user this request is for. Subject string }
UserinfoRequest contains information about this request to the UserInfo endpoint
type UserinfoResponse ¶
type UserinfoResponse struct { // Subject is the sub of the user this request is for. Identity *jwt.IDClaims }
UserinfoResponse contains information to response to the userinfo response.