Documentation
¶
Overview ¶
Package jawsauth provides OIDC-verified authentication for JaWS HTTP sessions.
It uses OIDC discovery from a configured issuer to run the OAuth2 authorization-code flow with PKCE and nonce verification, verifies the returned id_token, and stores the identity claims in the JaWS session. It also refreshes the id_token in the background before it expires and supports gating handlers to administrator emails.
Create a Server with New (or NewDebug) and protect handlers with Server.Wrap, Server.WrapAdmin, Server.Handler or Server.HandlerAdmin.
Index ¶
- Variables
- func DefaultSetHeaders(hw http.ResponseWriter, ishttps bool)
- type Config
- type EventFunc
- type FailedFunc
- type HandleFunc
- type JawsAuth
- type OAuth2CallbackError
- type Server
- func (srv *Server) GetAdmins() (emails []string)
- func (srv *Server) HandleAuthResponse(hw http.ResponseWriter, hr *http.Request)
- func (srv *Server) HandleLogin(hw http.ResponseWriter, hr *http.Request)
- func (srv *Server) HandleLogout(hw http.ResponseWriter, hr *http.Request)
- func (srv *Server) Handler(name string, dot any) http.Handler
- func (srv *Server) HandlerAdmin(name string, dot any) http.Handler
- func (srv *Server) IsAdmin(email string) (yes bool)
- func (srv *Server) Logout(sess *jaws.Session, hr *http.Request) (cleared bool)
- func (srv *Server) Set403Handler(h http.Handler)
- func (srv *Server) SetAdmins(emails []string)
- func (srv *Server) Valid() bool
- func (srv *Server) Wrap(h http.Handler) (rh http.Handler)
- func (srv *Server) WrapAdmin(h http.Handler) (rh http.Handler)
Constants ¶
This section is empty.
Variables ¶
var ErrConfig errConfig
ErrConfig matches all configuration validation errors.
var ErrConfigIssuerMustBeHTTPS = errors.New("issuer url must use https")
ErrConfigIssuerMustBeHTTPS means Issuer must use the https scheme unless AllowInsecureIssuer is enabled.
var ErrConfigMissingValue = errors.New("config value is missing")
ErrConfigMissingValue means a required configuration value is missing.
var ErrConfigURLMissingHost = errors.New("url host is missing")
ErrConfigURLMissingHost means a configured URL does not include a host.
var ErrConfigURLNotAbsolute = errors.New("url is not absolute")
ErrConfigURLNotAbsolute means a configured URL is not absolute.
var ErrOAuth2Callback = errors.New("oauth2 callback error")
ErrOAuth2Callback matches OAuth2 callback errors returned by the identity provider.
var ErrOAuth2MissingPKCEVerifier = errors.New("oauth2 missing pkce verifier")
ErrOAuth2MissingPKCEVerifier means the callback session did not contain the required PKCE verifier.
var ErrOAuth2MissingSession = errors.New("oauth2 missing session")
ErrOAuth2MissingSession means no jaws session was available to carry the OAuth2 flow state.
var ErrOAuth2MissingState = errors.New("oauth2 missing state")
ErrOAuth2MissingState means the callback session did not contain the expected state value.
var ErrOAuth2NotConfigured = errors.New("oauth2 not configured")
ErrOAuth2NotConfigured means OAuth2/OIDC is not configured on the Server.
var ErrOAuth2WrongState = errors.New("oauth2 wrong state")
ErrOAuth2WrongState means the callback state value did not match the stored session state.
var ErrOIDCDiscovery = errors.New("oidc discovery failed")
ErrOIDCDiscovery means OIDC provider discovery failed.
var ErrOIDCInvalidIDToken = errors.New("oidc invalid id_token")
ErrOIDCInvalidIDToken means id_token verification failed.
var ErrOIDCMissingIDToken = errors.New("oidc missing id_token")
ErrOIDCMissingIDToken means the token response did not include an id_token.
var ErrOIDCMissingNonce = errors.New("oidc missing nonce")
ErrOIDCMissingNonce means the login request did not include a nonce.
var ErrOIDCNonceMismatch = errors.New("oidc nonce mismatch")
ErrOIDCNonceMismatch means the id_token nonce did not match the stored session nonce.
var ErrOIDCProviderMetadata = errors.New("oidc provider metadata invalid")
ErrOIDCProviderMetadata means discovered OIDC metadata was invalid.
var ErrServerNilJaws = errors.New("jawsauth: nil *jaws.Jaws")
ErrServerNilJaws is returned by New and NewDebug when the *jaws.Jaws argument is nil. Server methods dereference Server.Jaws and require it to be non-nil for the lifetime of the Server.
var ErrUserInfoStatus = errors.New("userinfo status")
ErrUserInfoStatus means the UserInfo endpoint returned a non-200 HTTP status.
var SetHeaders = DefaultSetHeaders
SetHeaders writes the HTTP response headers for all OAuth endpoint responses.
It defaults to DefaultSetHeaders and may be reassigned at startup to customize headers; it must not be reassigned concurrently with serving requests.
Functions ¶
func DefaultSetHeaders ¶ added in v1.0.7
func DefaultSetHeaders(hw http.ResponseWriter, ishttps bool)
DefaultSetHeaders writes response headers for OAuth endpoint responses.
Types ¶
type Config ¶
type Config struct {
RedirectURL string // required. e.g. "https://application.example.com/oauth2/callback"
Issuer string // required. e.g. "https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/v2.0"
AuthURL string // optional override for discovered authorization_endpoint
TokenURL string // optional override for discovered token_endpoint
UserInfoURL string // optional override for discovered userinfo_endpoint
// AllowInsecureIssuer permits "http://" Issuer URLs and should only be used for tests/dev.
AllowInsecureIssuer bool
// HTTPClient is used for OIDC discovery at startup and, unless a per-request
// oauth2.HTTPClient is supplied via the request context, as the default client
// for token exchange/refresh and UserInfo requests.
HTTPClient *http.Client
Scopes []string // optional additional scopes, "openid" and "email" are always ensured
ClientID string
//gosec:disable G117
ClientSecret string
}
Config holds the OIDC/OAuth2 settings used by New and NewDebug to construct a Server.
RedirectURL, Issuer and ClientID are required; AuthURL, TokenURL and UserInfoURL override values otherwise obtained via OIDC discovery, and the remaining fields are optional.
type EventFunc ¶ added in v0.3.0
EventFunc is called for login and logout lifecycle events.
For a LogoutEvent triggered by an auth-refresh timer rather than an HTTP request, hr may be nil.
type FailedFunc ¶ added in v0.9.0
type FailedFunc func(hw http.ResponseWriter, hr *http.Request, httpCode int, err error, email string) (wroteresponse bool)
FailedFunc is called when a login attempt fails.
It returns true if it wrote the HTTP response itself, in which case jawsauth writes nothing further.
type HandleFunc ¶
HandleFunc registers handler to serve requests for the given URI path.
It matches the shape of http.ServeMux.Handle and is supplied to New and NewDebug so the login, logout and callback endpoints can be wired into the caller's router.
type JawsAuth ¶ added in v0.6.0
type JawsAuth struct {
// contains filtered or unexported fields
}
JawsAuth exposes authenticated session data to JaWS templates. Its zero value is safe to use and reports no user data.
func (*JawsAuth) Data ¶ added in v0.6.0
Data returns the verified OIDC claims stored in the session, or nil. It is safe to call on a nil or zero-value JawsAuth.
func (*JawsAuth) Email ¶ added in v0.6.0
Email returns the authenticated email stored in the session, or an empty string. It is safe to call on a nil or zero-value JawsAuth.
func (*JawsAuth) EmailVerified ¶ added in v1.0.9
EmailVerified returns whether the authenticated email was marked verified. It is safe to call on a nil or zero-value JawsAuth.
type OAuth2CallbackError ¶ added in v1.0.0
type OAuth2CallbackError struct {
Code string // OAuth2 error code from the callback.
Description string // Optional error description from the callback.
URI string // Optional URI with details about the callback error.
}
OAuth2CallbackError describes an OAuth2 callback error response.
func (*OAuth2CallbackError) Error ¶ added in v1.0.0
func (err *OAuth2CallbackError) Error() string
func (*OAuth2CallbackError) Is ¶ added in v1.0.0
func (err *OAuth2CallbackError) Is(target error) bool
type Server ¶
type Server struct {
Jaws *jaws.Jaws
//gosec:disable G117
SessionKey string // default is "oidc_claims", value will be of type map[string]any // #nosec G117
SessionTokenKey string // default is "oauth2_tokensource", value will be of type oauth2.TokenSource
SessionEmailKey string // default is "email", value will be of type string
SessionEmailVerifiedKey string // default is "email_verified", value will be of type bool
HandledPaths map[string]struct{} // URI paths we have registered handlers for
LoginEvent EventFunc // if not nil, called after a successful login
LogoutEvent EventFunc // if not nil, called before logout; hr may be nil for timer-driven logout
LoginFailed FailedFunc // if not nil, called on failed login
Options []oauth2.AuthCodeOption // options to use, see https://pkg.go.dev/golang.org/x/oauth2#AuthCodeOption
// contains filtered or unexported fields
}
Server provides OIDC-verified authentication for JaWS sessions.
Create one with New or NewDebug. Its methods are safe for concurrent use; the exported configuration fields and callbacks should be set before serving requests.
func New ¶
New creates a Server providing OIDC-verified authentication for JaWS sessions.
It configures the Server from cfg and registers the login, logout and OAuth2 callback endpoints via handleFn. A nil jw returns ErrServerNilJaws. Use Valid to test whether OIDC authentication was successfully configured.
func NewDebug ¶ added in v0.2.0
func NewDebug(jw *jaws.Jaws, cfg *Config, handleFn HandleFunc, overrideUrl string) (srv *Server, err error)
NewDebug behaves like New but can override the scheme and host of cfg.RedirectURL.
overrideUrl supplies the replacement scheme and host (an empty overrideUrl disables the override), which is useful when serving behind a different public address during development.
A nil jw returns ErrServerNilJaws and a nil Server. Otherwise a non-nil Server is always returned. OIDC is configured, and the login, logout and callback handlers registered via handleFn, only when cfg, handleFn and cfg.RedirectURL are all provided; any error from OIDC discovery is returned alongside the not-yet-Valid Server.
func (*Server) GetAdmins ¶ added in v0.6.0
GetAdmins returns a sorted list of the administrator emails. If empty, everyone is considered an administrator.
func (*Server) HandleAuthResponse ¶
func (srv *Server) HandleAuthResponse(hw http.ResponseWriter, hr *http.Request)
HandleAuthResponse handles the OIDC redirect/callback endpoint.
For GET requests it validates the state, exchanges the authorization code using the stored PKCE verifier, verifies the id_token and its nonce, stores the verified claims in the session, and invokes LoginEvent on success or LoginFailed on failure. Non-GET requests receive 405.
func (*Server) HandleLogin ¶
func (srv *Server) HandleLogin(hw http.ResponseWriter, hr *http.Request)
HandleLogin begins the OIDC login flow.
For GET requests it generates and stores the state, nonce and PKCE verifier in the session, then responds with a 302 redirect to the provider's authorization URL. Non-GET requests receive 405.
func (*Server) HandleLogout ¶
func (srv *Server) HandleLogout(hw http.ResponseWriter, hr *http.Request)
HandleLogout clears the session's stored authentication and redirects.
For GET requests it clears the auth (firing LogoutEvent if set) and responds with a 302 redirect back to the sanitized referrer (or "/"). Non-GET requests receive 405.
func (*Server) Handler ¶
Handler returns a http.Handler that renders the named jaws.Template with dot and requires an authenticated user.
Unauthenticated requests are redirected into the OIDC login flow (HandleLogin), which verifies the id_token and stores the claims in srv.SessionKey (with optional UserInfo fallback) before the user returns. If the Server is not Valid, the template handler is returned without the authentication requirement.
func (*Server) HandlerAdmin ¶ added in v0.6.0
HandlerAdmin returns a http.Handler that renders the named jaws.Template with dot and requires an authenticated administrator.
Unauthenticated requests are redirected into the OIDC login flow (HandleLogin); authenticated non-admins (see SetAdmins and IsAdmin) are served the 403 handler. If the Server is not Valid, the template handler is returned without the authentication requirement.
func (*Server) IsAdmin ¶ added in v0.6.0
IsAdmin returns true if email belongs to an admin, if the list of admins is empty, or if srv is nil.
func (*Server) Logout ¶ added in v1.2.0
Logout clears all authentication state for the session and returns true if anything was cleared.
It stops the auth-refresh timer, clears the OIDC claims, token source, email, expiry and any in-flight OAuth flow keys, calls LogoutEvent (if set), and marks the session dirty. It performs no HTTP redirect, so the caller can build its own post-logout response (for example an RP-initiated end-session redirect). It is safe to call with a nil receiver or nil session.
func (*Server) Set403Handler ¶ added in v0.6.0
Set403Handler sets the handler used to serve 403 Forbidden responses to authenticated non-admin users.
A nil h restores the default handler. It is safe for concurrent use.
func (*Server) SetAdmins ¶ added in v0.6.0
SetAdmins sets the emails of administrators. If empty, everyone is considered an administrator.
func (*Server) Wrap ¶
Wrap returns a http.Handler that requires an authenticated user before invoking h.
Unauthenticated requests are redirected into the OIDC login flow (HandleLogin), which verifies the id_token and stores the claims in srv.SessionKey (with optional UserInfo fallback) before the user returns. If the Server is not Valid, returns h.
func (*Server) WrapAdmin ¶ added in v0.6.0
WrapAdmin returns a http.Handler that requires an authenticated administrator before invoking h.
Unauthenticated requests are redirected into the OIDC login flow (HandleLogin); authenticated users whose email is not an admin (see SetAdmins and IsAdmin) are served the 403 handler instead of h. If the Server is not Valid, returns h.