Architecture β
AuthKit has three layers that compose upward: managers (your storage), flows (one per grant or endpoint), and the server (the dispatcher your HTTP handlers call into).
βββββββββββββββββββββββββββββββββββββββββββββββ
β Server β
β RegisterGrant Β· RegisterEndpoint β
β CreateAuthorizationResponse / TokenResponseβ
βββββββββββββββββ¬ββββββββββββββββββββ¬ββββββββββ
β β
βββββββββΌβββββββ βββββββββΌβββββββββ
β Grant Flow β β Endpoint β
β (e.g. auth β β (e.g. token β
β code, ropc) β β introspection) β
βββββββββ¬βββββββ βββββββββ¬βββββββββ
β β
βββββββββΌββββββββββββββββββββΌβββββββββ
β Extensions β
β PKCE Β· OIDC ID Token Β· (yours) β
βββββββββ¬ββββββββββββββββββββββββββββββ
β
βββββββββΌβββββββββββββββββββββββββββββββ
β Manager interfaces β
β ClientManager Β· TokenManager Β· ... β
β (implemented by you) β
ββββββββββββββββββββββββββββββββββββββββββServer β
Server is the central dispatcher. Register grant flows and endpoints before use, then call its handler methods from your HTTP routes.
srv := authkit.NewServer()
srv.RegisterGrant(authCodeFlow)
srv.RegisterGrant(ropcFlow)
srv.RegisterEndpoint(introspectionFlow)
// In your HTTP handlers:
srv.CreateAuthorizationResponse(r, w, user) // GET /authorize
srv.CreateConsentResponse(r, w, user) // POST /authorize (consent step)
srv.CreateTokenResponse(r, w) // POST /token
srv.EndpointResponse(r, w, "introspection") // POST /introspectFor finer control, use the split validate/respond methods to inspect a request before committing a response:
grant, req, err := srv.ValidateAuthorizationRequest(r, user)
grant, req, err := srv.ValidateConsentRequest(r, user)
grant, req, err := srv.ValidateTokenRequest(r)Grant Flow pattern β
Every flow follows the same Config + Flow pattern:
// 1. Build config
cfg := authorizationcode.NewConfig().
SetClientManager(myClientManager).
SetAuthCodeManager(myAuthCodeManager).
SetTokenManager(myTokenManager)
// 2. Register optional extensions (PKCE, OIDC, etc.)
cfg.RegisterExtension(pkceFlow)
cfg.RegisterExtension(oidcFlow)
// 3. Instantiate β validates config, fails fast on missing dependencies
flow, err := authorizationcode.Must(cfg)
// 4. Register with server
srv.RegisterGrant(flow)This same shape applies to ropc, client_credentials, rfc7662 (introspection), and every other flow β learn it once. See Config + Flow Pattern for the reasoning behind it.
Extension system β
A single object can implement multiple extension interfaces and be registered once via RegisterExtension. Extensions are called in registration order.
| Interface | Called when |
|---|---|
AuthorizationRequestValidator | Validating /authorize request |
ConsentRequestValidator | Validating the consent step |
AuthCodeProcessor | Before saving the authorization code |
TokenRequestValidator | Validating /token request |
TokenProcessor | Before writing the token response |
PKCE (rfc7636) and OIDC (oidc/core/authorization_code) are implemented as extensions and plug into the Authorization Code flow via RegisterExtension β a useful pattern to follow if you need to add custom claims, audience restriction, or rate limiting at the same integration points. See Extension System.
Models β
Implement the interfaces in the models package with your own data layer. See Models for the full interface reference and integrations/sql/ for example SQL-backed implementations.