Documentation
¶
Overview ¶
Package server provides the OAuth 2.0 authorization server implementation for ToolHive.
This package implements a standards-compliant OAuth 2.0 authorization server that acts as an intermediary between MCP clients and upstream identity providers (IdPs). It issues its own JWTs while federating authentication to external IdPs.
Architecture ¶
The server package is organized into focused sub-packages:
- server/registration: OAuth client types including RFC 8252 compliant LoopbackClient for native applications with dynamic port matching
- server/crypto: Cryptographic utilities for key loading, PKCE, and signing
- server/session: Session management linking issued tokens to upstream IdP tokens
Protocol Compliance ¶
This implementation follows these OAuth 2.0 and OIDC specifications:
- RFC 6749: OAuth 2.0 Authorization Framework
- RFC 6750: Bearer Token Usage
- RFC 7636: Proof Key for Code Exchange (PKCE)
- RFC 7591: OAuth 2.0 Dynamic Client Registration
- RFC 8252: OAuth 2.0 for Native Apps (loopback redirect URI handling)
- OpenID Connect Core 1.0: Discovery and JWT claims
Main Entry Points ¶
For creating an authorization server configuration:
params := &server.AuthorizationServerParams{
Issuer: "https://auth.example.com",
AccessTokenLifespan: time.Hour,
SigningKeyID: "key-1",
SigningKeyAlgorithm: "RS256",
SigningKey: privateKey,
HMACSecrets: &crypto.HMACSecrets{
Current: currentSecret, // Active secret for signing
Rotated: [][]byte{oldSecret}, // Previous secrets for verification (optional)
},
}
authServerConfig, err := server.NewAuthorizationServerConfig(params)
For creating OAuth clients:
client, err := registration.New(registration.Config{
ID: "my-client",
RedirectURIs: []string{"http://127.0.0.1:8080/callback"},
Public: true,
})
Token Flow ¶
The authorization server implements the authorization code flow with PKCE:
- Client initiates auth at /oauth/authorize with PKCE challenge
- Server redirects to upstream IdP for authentication
- IdP calls back to /oauth/callback with auth code
- Server exchanges code with IdP and stores IdP tokens
- Server issues its own auth code and redirects to client
- Client exchanges code at /oauth/token for JWT access token
- JWT contains "tsid" claim linking to stored IdP tokens
Sub-package Details ¶
Use the sub-packages directly for more granular control:
import "github.com/stacklok/toolhive/pkg/authserver/server/registration" // Client types import "github.com/stacklok/toolhive/pkg/authserver/server/crypto" // Key loading, PKCE import "github.com/stacklok/toolhive/pkg/authserver/server/session" // Session types
Index ¶
- Constants
- func NewAuthorizationServer(config *AuthorizationServerConfig, storage fosite.Storage, strategy any, ...) fosite.OAuth2Provider
- type AuthorizationServerConfig
- func (c *AuthorizationServerConfig) GetAccessTokenIssuer() string
- func (c *AuthorizationServerConfig) GetAccessTokenLifespan() time.Duration
- func (c *AuthorizationServerConfig) GetAuthorizeCodeLifespan() time.Duration
- func (c *AuthorizationServerConfig) GetPrivateSigningJWKS(_ context.Context) *jose.JSONWebKeySet
- func (c *AuthorizationServerConfig) GetRefreshTokenLifespan() time.Duration
- func (c *AuthorizationServerConfig) GetSigningKey(_ context.Context) *jose.JSONWebKey
- func (c *AuthorizationServerConfig) PublicJWKS() *jose.JSONWebKeySet
- type AuthorizationServerParams
- type Factory
Constants ¶
const ( // MinAccessTokenLifespan is the minimum allowed access token lifetime. MinAccessTokenLifespan = 1 * time.Minute // MaxAccessTokenLifespan is the maximum allowed access token lifetime. MaxAccessTokenLifespan = 24 * time.Hour // MinRefreshTokenLifespan is the minimum allowed refresh token lifetime. MinRefreshTokenLifespan = 1 * time.Hour // MaxRefreshTokenLifespan is the maximum allowed refresh token lifetime (30 days). MaxRefreshTokenLifespan = 30 * 24 * time.Hour // MinAuthCodeLifespan is the minimum allowed authorization code lifetime. MinAuthCodeLifespan = 30 * time.Second // MaxAuthCodeLifespan is the maximum allowed authorization code lifetime (RFC 6749 recommends 10 min max). MaxAuthCodeLifespan = 10 * time.Minute )
Token lifespan bounds for validation.
Variables ¶
This section is empty.
Functions ¶
func NewAuthorizationServer ¶
func NewAuthorizationServer( config *AuthorizationServerConfig, storage fosite.Storage, strategy any, factories ...Factory, ) fosite.OAuth2Provider
NewAuthorizationServer creates a new fosite OAuth2Provider with the given configuration, storage, strategy, and endpoint handler factories.
Types ¶
type AuthorizationServerConfig ¶
type AuthorizationServerConfig struct {
*fosite.Config
SigningKey *jose.JSONWebKey
SigningJWKS *jose.JSONWebKeySet
}
AuthorizationServerConfig wraps fosite.Config with additional configuration for JWT signing and other extensions.
func NewAuthorizationServerConfig ¶
func NewAuthorizationServerConfig(cfg *AuthorizationServerParams) (*AuthorizationServerConfig, error)
NewAuthorizationServerConfig creates an AuthorizationServerConfig from the provided configuration.
func (*AuthorizationServerConfig) GetAccessTokenIssuer ¶
func (c *AuthorizationServerConfig) GetAccessTokenIssuer() string
GetAccessTokenIssuer returns the issuer URL for access tokens. This is an adapter method that wraps the embedded fosite.Config method.
func (*AuthorizationServerConfig) GetAccessTokenLifespan ¶
func (c *AuthorizationServerConfig) GetAccessTokenLifespan() time.Duration
GetAccessTokenLifespan returns the lifetime for access tokens. This is an adapter method that wraps the embedded fosite.Config method.
func (*AuthorizationServerConfig) GetAuthorizeCodeLifespan ¶
func (c *AuthorizationServerConfig) GetAuthorizeCodeLifespan() time.Duration
GetAuthorizeCodeLifespan returns the lifetime for authorization codes. This is an adapter method that wraps the embedded fosite.Config method.
func (*AuthorizationServerConfig) GetPrivateSigningJWKS ¶
func (c *AuthorizationServerConfig) GetPrivateSigningJWKS(_ context.Context) *jose.JSONWebKeySet
GetPrivateSigningJWKS returns the config's signing JWKS containing private keys.
WARNING: This JWKS contains PRIVATE key material and MUST NOT be exposed publicly. Use PublicJWKS() for the /.well-known/jwks.json endpoint.
func (*AuthorizationServerConfig) GetRefreshTokenLifespan ¶
func (c *AuthorizationServerConfig) GetRefreshTokenLifespan() time.Duration
GetRefreshTokenLifespan returns the lifetime for refresh tokens. This is an adapter method that wraps the embedded fosite.Config method.
func (*AuthorizationServerConfig) GetSigningKey ¶
func (c *AuthorizationServerConfig) GetSigningKey(_ context.Context) *jose.JSONWebKey
GetSigningKey returns the config's signing key.
func (*AuthorizationServerConfig) PublicJWKS ¶
func (c *AuthorizationServerConfig) PublicJWKS() *jose.JSONWebKeySet
PublicJWKS returns a copy of the JWKS containing only public keys.
type AuthorizationServerParams ¶
type AuthorizationServerParams struct {
Issuer string
AccessTokenLifespan time.Duration
RefreshTokenLifespan time.Duration
AuthCodeLifespan time.Duration
HMACSecrets *servercrypto.HMACSecrets
SigningKeyID string
SigningKeyAlgorithm string
SigningKey crypto.Signer
}
AuthorizationServerParams contains the configuration needed to create an AuthorizationServerConfig. This is a minimal subset of the authserver.Config fields needed for OAuth2.
type Factory ¶
type Factory func(config *AuthorizationServerConfig, storage fosite.Storage, strategy any) any
Factory is a constructor which is used to create an OAuth2 endpoint handler. NewAuthorizationServer handles consuming the new struct and attaching it to the parts of the config that it implements.
The strategy parameter is typed as any because fosite uses different strategy interfaces for different flows (e.g., oauth2.CoreStrategy, openid.OpenIDConnectTokenStrategy) that do not share a common base interface.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package crypto provides cryptographic utilities for the OAuth authorization server.
|
Package crypto provides cryptographic utilities for the OAuth authorization server. |
|
Package registration provides OAuth client types and utilities, including RFC 8252 compliant loopback redirect URI support for native OAuth clients.
|
Package registration provides OAuth client types and utilities, including RFC 8252 compliant loopback redirect URI support for native OAuth clients. |
|
Package session provides OAuth session management for the authorization server.
|
Package session provides OAuth session management for the authorization server. |