oidcop

package module
v1.0.0-alpha.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 25, 2024 License: BSD-3-Clause Imports: 25 Imported by: 0

README

oidcop

Go Reference

Go library for implementing OIDC OPs (Servers)

Example OP

An example server is provided. Can be run:

go run ./cmd/oidc-example-op

And interacted with via

go run github.com/lstoll/oidc/cmd/oidccli -issuer=http://localhost:8085 -client-id=cli -scopes=openid,offline_access -skip-cache info

Documentation

Overview

Package oidcop 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

View Source
const (
	SigningAlgRS256 = "RS256"
	SigningAlgES256 = "ES256"
)
View Source
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
)
View Source
const (
	DefaultAuthorizationEndpoint = "/authorization"
	DefaultTokenEndpoint         = "/token"
	DefaultUserinfoEndpoint      = "/userinfo"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthHandlers

type AuthHandlers interface {
	// SetAuthorizer sets the authorizer these handlers should use to finalize
	// login flows. This will be called before any other methods are called.
	SetAuthorizer(Authorizer)
	StartAuthorization(w http.ResponseWriter, req *http.Request, authReq *AuthorizationRequest)
	Token(req *TokenRequest) (*TokenResponse, error)
	RefreshToken(req *RefreshTokenRequest) (*TokenResponse, error)
	Userinfo(w io.Writer, uireq *UserinfoRequest) (*UserinfoResponse, error)
}

type Authorization

type Authorization struct {
	// Subject that was authenticated
	Subject string `json:"sub"`
	// Scopes are the list of scopes this session was granted
	Scopes []string `json:"scopes"`
	// ACR is the Authentication Context Class Reference the session was
	// authenticated with
	ACR string `json:"acr"`
	// AMR are the Authentication Methods Reference the session was
	// authenticated with
	AMR []string `json:"amr"`
	// Metadata can optionally contain serialized data, that will be made
	// accessible across calls. This library will not maipulate the data.
	Metadata json.RawMessage `json:"metadata"`
}

type AuthorizationRequest

type AuthorizationRequest struct {
	// ID for this auth request
	ID uuid.UUID
	// ACRValues are the authentication context class reference values the
	// caller requested
	//
	// https://openid.net/specs/openid-connect-core-1_0.html#acrSemantics
	ACRValues []string
	// Scopes that have been requested
	Scopes []string
	// ClientID that started this request
	ClientID string
}

AuthorizationRequest details the information the user starting the authorization flow requested

type Authorizer

type Authorizer interface {
	// Authorize should be called once the consumer has validated the identity
	// of the user. This will return the appropriate response directly to the
	// passed http context, which should be considered finalized when this is
	// called. Note: This does not have to be the same http request in which
	// Authorization was started, but the session ID field will need to be
	// tracked and consistent.
	//
	// The scopes this request has been granted with should be included.
	//
	// https://openid.net/specs/openid-connect-core-1_0.html#IDToken
	Authorize(w http.ResponseWriter, r *http.Request, authReqID uuid.UUID, auth *Authorization) error
}

type ClientSource

type ClientSource interface {
	// IsValidClientID should return true if the passed client ID is valid
	IsValidClientID(clientID string) (ok bool, err error)
	// RequiresPKCE indicates if this client is required to use PKCE for token
	// exchange.
	RequiresPKCE(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(clientID, clientSecret string) (ok bool, err error)
	// ValidateRedirectURI should confirm if the given redirect is valid for the client. It should
	// compare as per https://tools.ietf.org/html/rfc3986#section-6
	ValidateClientRedirectURI(clientID, redirectURI string) (ok bool, err error)
}

ClientSource is used for validating client informantion for the general flow

type HandleFn

type HandleFn func(context.Context) (*keyset.Handle, error)

HandleFn is used to get a tink handle for a keyset, when it is needed.

func StaticHandleFn

func StaticHandleFn(h *keyset.Handle) HandleFn

StaticHandleFn is a convenience method to create a HandleFn from a fixed keyset handle.

type Identity

type Identity struct {
	EMail    string
	FullName string
	// Extra claims to include in the ID Token.
	ExtraClaims map[string]any
}

Identity of a user, used to construct ID token claims and UserInfo responses. Depending on the requested scopes, only a subset of this information might be used

type OIDC

type OIDC struct {
	// contains filtered or unexported fields
}

OIDC can be used to handle the various parts of the OIDC auth flow.

func New

func New(issuer string, storage storage.Storage, clientSource ClientSource, keyset map[SigningAlg]HandleFn, handlers AuthHandlers, opts *Options) (*OIDC, error)

func (*OIDC) AttachHandlers

func (o *OIDC) AttachHandlers(mux *http.ServeMux, metadata *oidc.ProviderMetadata) error

AttachHandlers will bind handlers for the following endpoints to the given mux. If the provided metadata specifies a URL for them already it will be used, if not defaults will be set. If metadata is nil, BuildDiscovery will be used.

func (*OIDC) BuildDiscovery

func (o *OIDC) BuildDiscovery() *oidc.ProviderMetadata

func (*OIDC) StartAuthorization

func (o *OIDC) StartAuthorization(w http.ResponseWriter, req *http.Request)

StartAuthorization can be used to handle a request to the auth endpoint. It will parse and validate the incoming request, returning a unique identifier. If an error was returned, it should be assumed that this has been returned to the called appropriately. Otherwise, no response will be written. The caller can then use this request to implement the appropriate auth flow. The authID should be kept and treated as sensitive - it will be used to mark the request as Authorized.

https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth

func (*OIDC) Token

func (o *OIDC) Token(w http.ResponseWriter, req *http.Request)

Token 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 (*OIDC) Userinfo

func (o *OIDC) Userinfo(w http.ResponseWriter, req *http.Request)

Userinfo 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 Options

type Options struct {
	// Issuer is the issuer we are serving for.
	Issuer string
	// 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

	// Logger can be used to configure a logger that will have errors and
	// warning logged. Defaults to discarding this information.
	Logger *slog.Logger
}

Options sets configuration values for the OIDC flow implementation

type RefreshTokenRequest

type RefreshTokenRequest struct {
	// Authorization information this session was authorized with
	Authorization storage.Authorization
}

RefreshTokenRequest encapsulates the information for a request to refresh a token.

type SigningAlg

type SigningAlg string

SigningAlg represents supported JWT signing algorithms

func (SigningAlg) Template

func (s SigningAlg) Template() *tinkpb.KeyTemplate

type TokenRequest

type TokenRequest struct {
	// Authorization information this session was authorized with
	Authorization storage.Authorization
}

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 {
	// OverrideRefreshTokenIssuance can be used to override issuing a refresh
	// token if the client requested it, if true.
	OverrideRefreshTokenIssuance bool

	// OverrideRefreshTokenExpiry can be used to override the expiration of the
	// refresh token. If not set, the default will be used.
	OverrideRefreshTokenExpiry time.Time

	// may be zero, if so defaulted
	IDTokenExpiry     time.Time
	AccessTokenExpiry time.Time

	// Identity sets the user information, that can be included in the returned
	// ID token.
	Identity *Identity

	// AccessTokenExtraClaims sets additional claims to be included in the
	// access token.
	AccessTokenExtraClaims map[string]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
}

TokenResponse is returned by the token endpoint handler, indicating what it should actually return to the user.

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 *Identity
}

UserinfoResponse contains information to response to the userinfo response.

Directories

Path Synopsis
cmd
Package e2e contains high-level smoke tests for this module
Package e2e contains high-level smoke tests for this module
internal
jsonfile
Package jsonfile persists a Go value to a JSON file.
Package jsonfile persists a Go value to a JSON file.
oauth2
Package oauth2 implements base primitives for parsing a subset of oauth2 messages and errors
Package oauth2 implements base primitives for parsing a subset of oauth2 messages and errors
proto

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL