Documentation
¶
Index ¶
- Constants
- Variables
- func AuthenticateHandler(sm *sessionManager, loginEndpoint string, next http.Handler) http.Handler
- func CallbackHandler(sm *sessionManager, postCallbackHandler PostCallbackHandler, ...) http.Handler
- func ContextWithSession(parent context.Context, s *SessionContext) context.Context
- func DebugHandler(sm *sessionManager, providers []*Provider) http.Handler
- func GetCookieValue(r *http.Request, name string) (string, error)
- func LoadSessionHandler(sm *sessionManager, next http.Handler) http.Handler
- func LoginHandler(sm *sessionManager, providerSelectionHandler http.Handler, ...) http.Handler
- func LogoutHandler(sm *sessionManager, postLogoutHandler http.Handler) http.Handler
- func NewDefaultSessionInfoHandler(sm *sessionManager, tm *templateManager, pathSet PathSet, ...) http.Handler
- func NewSessionManager(hashKey, encryptionKey []byte, providerSet *providerSet, ...) (*sessionManager, error)
- func NewTemplateManager(directory string, devMode bool) (*templateManager, error)
- func ProviderSelectionHandler(appName string, providers []*Provider, tm *templateManager) http.Handler
- func RefreshHandler(sm *sessionManager, postRefreshHandler http.Handler, errorHandler ErrorHandler) http.Handler
- func RemoveSessionHandler(sm *sessionManager) http.Handler
- func SessionInfoHandler(sm *sessionManager, ...) http.Handler
- func SetCookie(w http.ResponseWriter, r *http.Request, c *http.Cookie)
- type Authenticator
- func (a *Authenticator) AuthenticateHandler(next http.Handler) http.Handler
- func (a *Authenticator) CallbackHandler() http.Handler
- func (a *Authenticator) FullMiddleware(next http.Handler) *http.ServeMux
- func (a *Authenticator) LoginHandler() http.Handler
- func (a *Authenticator) LogoutHandler() http.Handler
- func (a *Authenticator) RefreshHandler() http.Handler
- func (a *Authenticator) SessionInfoHandler() http.Handler
- type ClaimCheckFunc
- type Config
- type CookieManager
- type CookieOptions
- type Endpoints
- type ErrorHandler
- type LoginState
- type PathSet
- type PostCallbackHandler
- type Provider
- func (p *Provider) AuthorizationEndpoint(_ context.Context, state string) (string, error)
- func (p *Provider) Config() ProviderConfig
- func (p *Provider) EndSessionEndpoint(_ context.Context, session *Session) (string, error)
- func (p *Provider) Exchange(ctx context.Context, code string) (*Session, error)
- func (p *Provider) ID() string
- func (p *Provider) Refresh(ctx context.Context, session *Session) (*Session, error)
- func (p *Provider) Revoke(ctx context.Context, token string) error
- func (p *Provider) String() string
- type ProviderConfig
- type ServerErr
- type Session
- type SessionContext
- type SessionInfoTemplateData
- type SessionSetupFunc
- type TokenResponse
- type Tokens
- type User
Constants ¶
const ( MAX_COOKIE_SIZE = 4096 // According to // https://stackoverflow.com/questions/3326210/can-http-headers-be-too-big-for-browsers // chrome does not handle more than 256k of total headers. Hence we do // not have to support more than 64 cookies (256k / 4k) MAX_COOKIE_COUNT = 64 )
Variables ¶
var ErrNotSupported = errors.New("not supported")
ErrNotSupported is returned if an action on a provider is called which is not supported. For example if you call Revoke but the provider does not have configured a revocation endpoint.
Functions ¶
func AuthenticateHandler ¶
AuthenticateHandler loads the session and sets it in the context. If there is no session available it initiates a login be redirecting the request to the login endpoint. If a session is available but it is no longer valid and if the session contains a refresh_token it tries to obtain a new session using the refresh token.
func CallbackHandler ¶
func CallbackHandler(sm *sessionManager, postCallbackHandler PostCallbackHandler, errorHandler ErrorHandler) http.Handler
func ContextWithSession ¶
func ContextWithSession(parent context.Context, s *SessionContext) context.Context
func DebugHandler ¶
DebugHandler returns information about the session including the tokens.
func LoadSessionHandler ¶
LoadSessionHandler loads the session and makes it available in the context for subsequent handler.
func LoginHandler ¶
func LoginHandler(sm *sessionManager, providerSelectionHandler http.Handler, errorHandler ErrorHandler) http.Handler
LoginHandler returns a handler which sets a state and then redirects the request to the authorization endpoint of the provider. If multiple providers are configured the provider is selected via the query paramter provider=<providerID>. If multiple providers are configured providerSelectionHandler can be used to render a provider selection dialog.
func LogoutHandler ¶
LogoutHandler deletes the session cookies, revokes the token (if supportd by the provider) and redirects to the end_session_uri of the provider (if supported by the provider). If no end_session_uri is available the postLogoutHandler is run.
func NewDefaultSessionInfoHandler ¶
func NewDefaultSessionInfoHandler(sm *sessionManager, tm *templateManager, pathSet PathSet, errorHandler ErrorHandler) http.Handler
func NewSessionManager ¶
func NewSessionManager(hashKey, encryptionKey []byte, providerSet *providerSet, cookieOptions *CookieOptions) (*sessionManager, error)
NewSessionManager creates a new sessionManager which is responsible to set and get encrypted session cookies.
func NewTemplateManager ¶
func ProviderSelectionHandler ¶
func ProviderSelectionHandler(appName string, providers []*Provider, tm *templateManager) http.Handler
ProviderSelectionHandler returns a handler which shows a provider selection dialog.
func RefreshHandler ¶
func RefreshHandler(sm *sessionManager, postRefreshHandler http.Handler, errorHandler ErrorHandler) http.Handler
func RemoveSessionHandler ¶
RemoveSessionHandler removes the session.
func SessionInfoHandler ¶
func SessionInfoHandler(sm *sessionManager, renderSessionHandler func(w http.ResponseWriter, r *http.Request, s *SessionContext), errorHandler ErrorHandler) http.Handler
SessionInfoHandler gets the session from the request using sessionManager and then renders the session info using the renderSessionInfo function. If the request accepts the MIME type application/json it returns a JSON representation of the session.
Types ¶
type Authenticator ¶
type Authenticator struct { Config *Config TemplateManager *templateManager SessionManager *sessionManager Providers []*Provider ErrorHandler ErrorHandler }
Authenticator combines privdes handlers and middlewares for the authentication using OIDC/OAuth2
func NewAuthenticator ¶
func NewAuthenticator(ctx context.Context, c *Config) (*Authenticator, error)
NewAuthenticator validates the configuration and creates a new authenticator.
func (*Authenticator) AuthenticateHandler ¶
func (a *Authenticator) AuthenticateHandler(next http.Handler) http.Handler
AuthenticateHandler checks if there is an existing valid session (not expired).
func (*Authenticator) CallbackHandler ¶
func (a *Authenticator) CallbackHandler() http.Handler
func (*Authenticator) FullMiddleware ¶
func (a *Authenticator) FullMiddleware(next http.Handler) *http.ServeMux
FullMiddleware authenticates each request using the authenticator. With the default configuration it shadows the following pathes:
- /auth/login
- /auth/callback
- /auth/info
- /auth/refresh
- /auth/logout
All other pathes are passed to the next handler.
func (*Authenticator) LoginHandler ¶
func (a *Authenticator) LoginHandler() http.Handler
func (*Authenticator) LogoutHandler ¶
func (a *Authenticator) LogoutHandler() http.Handler
func (*Authenticator) RefreshHandler ¶
func (a *Authenticator) RefreshHandler() http.Handler
func (*Authenticator) SessionInfoHandler ¶
func (a *Authenticator) SessionInfoHandler() http.Handler
type ClaimCheckFunc ¶
type Config ¶
type Config struct { // OAuth2 / OIDC Providers []ProviderConfig // CallbackURL is the url under which the callback path is reachable CallbackURL string // PostLogoutRedirectURI is the URL where you get redirected after an // RP initiated logut PostLogoutRediretURI string // BasePath is the path under which the other pathes get mapped BasePath string // LoginPath is the path under which the login flow gets initiated. LoginPath string // CallbackPath handle the oauth2 callback. It defaults to the path of // the CallbackURL if not specified. CallbackPath string // SessionInfoPath SessionInfoPath string // RefreshPath performs an explicit refresh RefreshPath string // LogoutPath deletes cookie, revokes token and redirect to IDPs logout // URL if available LogoutPath string // The external pathes are the paths under which the endpoint is // reachable from externally. If not set this defaults to the internal // path (same field without External prefix). These variables are only // required if between the client and this component the path gets // rewritten. // For example if you have an entry proxy (ingress) which routes // requests from entry.com/myapp/auth/info to myapp.com/auth/info you // have to configure a ExternalBasePath of /myapp. ExternalBasePath string ExternalLoginPath string ExternalSessionInfoPath string ExternalRefreshPath string ExternalLogoutPath string // secure cookie HashKey []byte EncryptionKey []byte CookieConfig *CookieOptions // AppName is used in templates. It is shown on the provider selection // to indicate where you are login into. AppName string TemplateDir string TemplateDevMode bool // GetRequestID is used in the default error handler if set. It returns // the request id along with the error message. GetRequestID func(r *http.Request) string }
func NewDefaultConfig ¶
func NewDefaultConfig() *Config
func (*Config) PrepareAndValidate ¶
Prepare sets derived defaults and validates configuration.
type CookieManager ¶
type CookieManager struct {
// contains filtered or unexported fields
}
func NewCookieHandler ¶
func NewCookieHandler(hashKey, encryptKey []byte) *CookieManager
func NewCookieHandlerWithOptions ¶
func NewCookieHandlerWithOptions(hashKey []byte, encryptKey []byte, options *CookieOptions) *CookieManager
func (*CookieManager) Delete ¶
func (c *CookieManager) Delete(w http.ResponseWriter, r *http.Request, name string)
type CookieOptions ¶
type CookieOptions struct { Path string Secure bool HttpOnly bool Domain string SameSite http.SameSite Duration time.Duration }
func NewDefaultCookieOptions ¶
func NewDefaultCookieOptions() *CookieOptions
type Endpoints ¶
type Endpoints struct { // AuthorizationEndpoint https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata AuthorizationEndpoint string `json:"authorization_endpoint"` // TokenEndpoint https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata TokenEndpoint string `json:"token_endpoint"` // UserinfoEndpoint https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata UserinfoEndpoint string `json:"userinfo_endpoint"` // EndSessionEndpoint https://openid.net/specs/openid-connect-rpinitiated-1_0.html#OPMetadata EndSessionEndpoint string `json:"end_session_endpoint"` // IntrospectionEndpoint (discovery has no specification) // See https://datatracker.ietf.org/doc/html/rfc7662 IntrospectionEndpoint string `json:"introspection_endpoint"` // RevocationEndpoint (discovery has no specification) // See https://datatracker.ietf.org/doc/html/rfc7009 RevocationEndpoint string `json:"revocation_endpoint"` }
type ErrorHandler ¶
type ErrorHandler func(w http.ResponseWriter, r *http.Request, err error)
func DefaultErrorHandler ¶
type LoginState ¶
type LoginState struct { // ProviderID to identify the provider we want to login with. ProviderID string // State for the OAuth2 code flow State string // URI to return to during the callback. URI string }
LoginState gets set during the login before we redirect a request to the IDPs authorization endpoint.
type PathSet ¶
type PathSet struct { // Login is the path to the login handler Login string // Logout is the path to the logout handler Logout string // Refresh is the path to the refresh handler Refresh string }
PathSet contains all pathes for the session info template.
type PostCallbackHandler ¶
type PostCallbackHandler func(w http.ResponseWriter, r *http.Request, s *SessionContext)
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
func NewProvider ¶
func NewProvider(ctx context.Context, config ProviderConfig) (*Provider, error)
func NewProviderSet ¶
func NewProviderSet(ctx context.Context, providerConfigs []ProviderConfig, modifier func(pc *ProviderConfig)) ([]*Provider, error)
func (*Provider) AuthorizationEndpoint ¶
AuthorizationEndpoint returns the authorization endpoint where redirect clients to initiate a login.
func (*Provider) Config ¶
func (p *Provider) Config() ProviderConfig
func (*Provider) EndSessionEndpoint ¶
EndSessionEndpoint returns the logout URL for the RP initiated logout if the end_session_endpoint is configured or an empty string otherwise. https://openid.net/specs/openid-connect-rpinitiated-1_0.html
func (*Provider) Exchange ¶
Exchange performs the Access Token Request using code. See https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3. Based on the returned Access Token Response it returns a session (see SessionSetupFunc).
func (*Provider) ID ¶
ID returns an identifier of the provider. If not set in ProviderConfig it gets calculated based on:
- IssuerURL
- ClientID
- AuthorizationEndpoint
- TokenEndpoint
func (*Provider) Refresh ¶
Refresh uses the refresh token of an existing session to obtain a new session. See https://datatracker.ietf.org/doc/html/rfc6749#section-6. If the session has no refresh token it returns an error.
func (*Provider) Revoke ¶
Revoke revokes a token using the revocation endpoint. See https://www.rfc-editor.org/rfc/rfc7009.html#section-2.1 for details. Usually you want to revoke the refresh_token because the RFC states that `If the particular token is a refresh token and the authorization server supports the revocation of access tokens, then the authorization server SHOULD also invalidate all access tokens based on the same authorization grant`. Revoke does return ErrNotSupported if no revocation endpoint is configured.
type ProviderConfig ¶
type ProviderConfig struct { // ID (optional) for the provider. This is espacially used in multi provider // scenarios where the provider ID is stored in the session to figure // out for each session to which provider it belongs. // If no ID is provided it is generated based on the configuration. ID string `json:"id,omitempty"` // Name (optional) is a descriptive name for the provider. It is used in multi // provider scenarios during the login process on the provider // selection screen. Name string `json:"name"` // IssuerURL is the URL for the OpenID discovery. For providers which // do not support OpenID discovery you can configure // AuthorizationEndpoint and TokenEndpoint instead. IssuerURL string `json:"issuer_url"` // ClientID ClientID string `json:"client_id"` // ClientSecret (optional) if not set the provider acts as a public // client. ClientSecret string `json:"client_secret"` // Scopes (optional) to use for the authorization. Scopes []string `json:"scopes"` // AuthorizationParameter (optional) are additional query parameters // for the authorization endpoint (e.g. resource). AuthorizationParameter url.Values `json:"authorization_parameters"` // TokenParameters (optional) are additional query parameters for the // token endpoint. TokenParameters url.Values `json:"token_parameters"` // CallbackURL used as redirect_uri CallbackURL string `json:"callback_url"` // PostLogoutRedirectURI (optional) is used during logout for the call // to the EndSessionEndpoint. PostLogoutRedirectURI string `json:"post_logout_redirect_uri"` // SetupSessionFunc allows to customize the Session based on the tokens // returned in the TokenResponse. For example exctract values from the // id_tokens of fetch additional information from a third-party servie // using the access_token. If SetupSessionFunc is nil only the defaultSessionSetupFunc is used SetupSessionFunc SessionSetupFunc `json:"-"` // Endpoints are usually discovered using OpenID discovery. If set // manual you can configure endpoints which can't be discovered or // overwrite endpoints from the discovery. Endpoints }
type ServerErr ¶
type ServerErr struct { HTTPStatusCode int // HTTP status code ResponseText string // Response text to the user Err error // wrapped error }
ServerErr is a error which can be passed to error handler. It allows to control what message is shown to the user.
func ErrMessage ¶
ErrMessage creates a ServerErr which uses message as response text for the user
type Session ¶
type Session struct { ProviderID string `json:"provider_id"` // Expiry specifies the time when the session expires. This is set // during the session setup and is usually obtained from the field // expires_in from the Access Token Response (see // https://datatracker.ietf.org/doc/html/rfc6749#section-5.1). Expiry time.Time `json:"expiry"` // Tokens usually stores the issued tokens from which the session got // created. If you don't need the tokens you can remove them during the // session setup which helps to keep the cookie small. Tokens *Tokens `json:"tokens,omitempty"` // User represents the authenticated user. The user can be initialized // during the session setup. Usually for this values from the claims in // the id_token are used. User *User `json:"user,omitempty"` }
Session represents a session which usually gets stored encrypted in a cookie. A session is initialized based on a set of tokens from a provider (TokenResponse) in a SetupSessionFunc.
func (*Session) AccessToken ¶
func (*Session) HasAccessToken ¶
func (*Session) HasIDToken ¶
func (*Session) HasRefreshToken ¶
func (*Session) RefreshToken ¶
type SessionContext ¶
SessionContext represents a Session and a reference to the Provider which issued the session.
func SessionFromContext ¶
func SessionFromContext(ctx context.Context) *SessionContext
func (*SessionContext) Valid ¶
func (s *SessionContext) Valid() bool
type SessionInfoTemplateData ¶
SessionInfoTemplateData are the parameters for the session info template.
type SessionSetupFunc ¶
SessionSetupFunc is used to setup a new session. This happens always after a IDP issues a new set of tokens. This is either on the initial login where we get a set of tokens using an authorization code or if we obtain a new set of tokens using a refresh_token. It turns the returend tokens into a session. This allows to customize the session setup based on the tokens. For example obtaining additional information like groups from other sources (e.g. userinfo endpoint) or setting a custom expiration time. Be aware that on a refresh not every provider does return a new id_token. If you return an error no new session will be established. Consider returning ServerErr to control what HTTP status code is retuned and what error is shown to the user.
func ChainSessionSetupFunc ¶
func ChainSessionSetupFunc(sessionSetupFuncs ...SessionSetupFunc) SessionSetupFunc
ChainSessionSetupFunc chains multiple sessionSetupFuncs. If one function returns an error subsequent functions are not called.
func NewSessionClaimCheckFunc ¶
func NewSessionClaimCheckFunc(claimCheckFunc ClaimCheckFunc) SessionSetupFunc
func RequireIDTokenGroup ¶
func RequireIDTokenGroup(groups ...string) SessionSetupFunc
RequireIDTokenGroup verifies that at least one of the given groups is available in the id_token.
func SaveGroups ¶
func SaveGroups() SessionSetupFunc
SaveGroups adds groups from id_token claims to session. It ignores errors.
type TokenResponse ¶
type TokenResponse struct { // Token contains the standard OAuth2 tokens like the access_token. oauth2.Token // RawIDToken contains the id_token if it was available in the // response. RawIDToken string // IDToken contains the parsed and validated id_token if it was // available in the response. IDToken *oidc.IDToken }