Documentation
¶
Index ¶
- Constants
- Variables
- func GenerateClientCredentials() (clientID, clientSecret string)
- func ValidateCodeChallenge(codeChallenge, method string) error
- func ValidatePKCE(codeVerifier, codeChallenge, method string) error
- type AccessToken
- type AuthService
- type AuthSession
- type AuthorizationCode
- type AuthorizationServerMetadata
- type BoltStorage
- func (s *BoltStorage) Close() error
- func (s *BoltStorage) DeleteAccessToken(ctx context.Context, token string) error
- func (s *BoltStorage) DeleteAuthCode(ctx context.Context, code string) error
- func (s *BoltStorage) DeleteAuthRequest(ctx context.Context, id string) error
- func (s *BoltStorage) DeleteClient(ctx context.Context, clientID string) error
- func (s *BoltStorage) DeleteRefreshToken(ctx context.Context, token string) error
- func (s *BoltStorage) DeleteSession(ctx context.Context, sessionID string) error
- func (s *BoltStorage) GetAccessToken(ctx context.Context, token string) (*AccessToken, error)
- func (s *BoltStorage) GetAuthCode(ctx context.Context, code string) (*AuthorizationCode, error)
- func (s *BoltStorage) GetAuthRequest(ctx context.Context, id string) (*PendingAuthRequest, error)
- func (s *BoltStorage) GetClient(ctx context.Context, clientID string) (*RegisteredClient, error)
- func (s *BoltStorage) GetRefreshToken(ctx context.Context, token string) (*RefreshToken, error)
- func (s *BoltStorage) GetSession(ctx context.Context, sessionID string) (*AuthSession, error)
- func (s *BoltStorage) GetSessionByAccessToken(ctx context.Context, token string) (*AuthSession, error)
- func (s *BoltStorage) GetUser(ctx context.Context, userID string) (*User, error)
- func (s *BoltStorage) GetUserByGitHubLogin(ctx context.Context, login string) (*User, error)
- func (s *BoltStorage) ListClients(ctx context.Context) ([]*RegisteredClient, error)
- func (s *BoltStorage) StoreAccessToken(ctx context.Context, token *AccessToken) error
- func (s *BoltStorage) StoreAuthCode(ctx context.Context, code *AuthorizationCode) error
- func (s *BoltStorage) StoreAuthRequest(ctx context.Context, req *PendingAuthRequest) error
- func (s *BoltStorage) StoreClient(ctx context.Context, client *RegisteredClient) error
- func (s *BoltStorage) StoreRefreshToken(ctx context.Context, token *RefreshToken) error
- func (s *BoltStorage) StoreSession(ctx context.Context, session *AuthSession) error
- func (s *BoltStorage) StoreUser(ctx context.Context, user *User) error
- func (s *BoltStorage) UpdateSessionLastUsed(ctx context.Context, sessionID string, lastUsed time.Time) error
- type ClientRegistrationRequest
- type ClientRegistrationResponse
- type CreateStaticClientRequest
- type GitHubClient
- func (gc *GitHubClient) ExchangeCode(ctx context.Context, code, callbackURL string) (string, error)
- func (gc *GitHubClient) GetAuthorizationURL(callbackURL, state string) string
- func (gc *GitHubClient) GetUser(ctx context.Context, token string) (*GitHubUser, error)
- func (gc *GitHubClient) GetUserOrgs(ctx context.Context, token string) ([]GitHubOrg, error)
- func (gc *GitHubClient) GetUserTeams(ctx context.Context, token string) ([]GitHubTeam, error)
- type GitHubOrg
- type GitHubTeam
- type GitHubTokenResponse
- type GitHubUser
- type OAuthError
- type PendingAuthRequest
- type ProtectedResourceMetadata
- type RefreshToken
- type RegisteredClient
- type StaticClientResponse
- type Storage
- type TokenResponse
- type TokenService
- func (ts *TokenService) GenerateAccessToken(userID, clientID, scope, resource string) (*AccessToken, error)
- func (ts *TokenService) GenerateAuthorizationCode(...) (*AuthorizationCode, error)
- func (ts *TokenService) GenerateRefreshToken(userID, clientID, scope, resource string) (*RefreshToken, error)
- func (ts *TokenService) ValidateAccessToken(token string) (*AccessToken, error)
- type User
Constants ¶
const ( GitHubAuthorizeURL = "https://github.com/login/oauth/authorize" GitHubTokenURL = "https://github.com/login/oauth/access_token" GitHubAPIURL = "https://api.github.com" )
const ( ContextKeyUser contextKey = "auth_user" ContextKeyAccessToken contextKey = "auth_access_token" ContextKeySession contextKey = "auth_session" )
const ( PKCEMethodS256 = "S256" PKCEMethodPlain = "plain" // NOT recommended but allowed per spec // code_verifier must be 43-128 characters, unreserved chars only PKCEVerifierMinLength = 43 PKCEVerifierMaxLength = 128 )
PKCE validation constants
const ( BucketAuthCodes = "auth_codes" BucketAccessTokens = "access_tokens" BucketRefreshTokens = "refresh_tokens" BucketClients = "clients" BucketUsers = "users" BucketUsersByGitHub = "users_by_github" BucketSessions = "sessions" BucketSessionsByToken = "sessions_by_token" BucketAuthRequests = "auth_requests" )
Bucket names
Variables ¶
var ( ErrTokenNotFound = errors.New("token not found") ErrTokenExpired = errors.New("token expired") ErrClientNotFound = errors.New("client not found") ErrInvalidCredentials = errors.New("invalid credentials") ErrUserNotFound = errors.New("user not found") ErrSessionNotFound = errors.New("session not found") )
Sentinel errors
Functions ¶
func GenerateClientCredentials ¶
func GenerateClientCredentials() (clientID, clientSecret string)
GenerateClientCredentials generates client_id and client_secret
func ValidateCodeChallenge ¶
ValidateCodeChallenge validates a code_challenge during authorization
func ValidatePKCE ¶
ValidatePKCE validates the code_verifier against the stored code_challenge
Types ¶
type AccessToken ¶
type AccessToken struct {
Token string `json:"token"`
TokenType string `json:"token_type"` // "Bearer"
ClientID string `json:"client_id"`
UserID string `json:"user_id"`
Scope string `json:"scope"`
Resource string `json:"resource,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
}
AccessToken represents an issued access token
func GetAccessTokenFromContext ¶
func GetAccessTokenFromContext(ctx context.Context) *AccessToken
GetAccessTokenFromContext retrieves the access token from the request context
type AuthService ¶
type AuthService struct {
// contains filtered or unexported fields
}
AuthService is the main entry point for all auth operations
func NewAuthService ¶
func NewAuthService(cfg *config.AuthConfig) (*AuthService, error)
NewAuthService creates a new authentication service
func (*AuthService) Close ¶
func (svc *AuthService) Close() error
Close closes the auth service and releases resources
func (*AuthService) Middleware ¶
func (svc *AuthService) Middleware(next http.Handler) http.Handler
Middleware creates an HTTP middleware for token validation
func (*AuthService) RegisterAdminRoutes ¶
func (svc *AuthService) RegisterAdminRoutes(mux *http.ServeMux)
RegisterAdminRoutes adds admin endpoints to the mux (protected by auth middleware)
func (*AuthService) RegisterRoutes ¶
func (svc *AuthService) RegisterRoutes(mux *http.ServeMux)
RegisterRoutes adds all OAuth endpoints to the mux
type AuthSession ¶
type AuthSession struct {
SessionID string `json:"session_id"`
UserID string `json:"user_id"`
ClientID string `json:"client_id"`
AccessToken string `json:"access_token"`
CreatedAt time.Time `json:"created_at"`
LastUsedAt time.Time `json:"last_used_at"`
}
AuthSession ties MCP sessions to authenticated users
type AuthorizationCode ¶
type AuthorizationCode struct {
Code string `json:"code"`
ClientID string `json:"client_id"`
RedirectURI string `json:"redirect_uri"`
Scope string `json:"scope"`
CodeChallenge string `json:"code_challenge"`
CodeChallengeMethod string `json:"code_challenge_method"`
Resource string `json:"resource,omitempty"` // RFC 8707
UserID string `json:"user_id"`
ExpiresAt time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
}
AuthorizationCode represents a pending authorization code
type AuthorizationServerMetadata ¶
type AuthorizationServerMetadata struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
ScopesSupported []string `json:"scopes_supported,omitempty"`
ResponseTypesSupported []string `json:"response_types_supported"`
GrantTypesSupported []string `json:"grant_types_supported"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
RequirePKCE bool `json:"require_pkce,omitempty"` // OAuth 2.1
}
AuthorizationServerMetadata per RFC 8414
type BoltStorage ¶
type BoltStorage struct {
// contains filtered or unexported fields
}
BoltStorage implements Storage using BoltDB
func NewBoltStorage ¶
func NewBoltStorage(path string) (*BoltStorage, error)
NewBoltStorage creates a new BoltDB storage
func (*BoltStorage) DeleteAccessToken ¶
func (s *BoltStorage) DeleteAccessToken(ctx context.Context, token string) error
func (*BoltStorage) DeleteAuthCode ¶
func (s *BoltStorage) DeleteAuthCode(ctx context.Context, code string) error
func (*BoltStorage) DeleteAuthRequest ¶
func (s *BoltStorage) DeleteAuthRequest(ctx context.Context, id string) error
func (*BoltStorage) DeleteClient ¶
func (s *BoltStorage) DeleteClient(ctx context.Context, clientID string) error
func (*BoltStorage) DeleteRefreshToken ¶
func (s *BoltStorage) DeleteRefreshToken(ctx context.Context, token string) error
func (*BoltStorage) DeleteSession ¶
func (s *BoltStorage) DeleteSession(ctx context.Context, sessionID string) error
func (*BoltStorage) GetAccessToken ¶
func (s *BoltStorage) GetAccessToken(ctx context.Context, token string) (*AccessToken, error)
func (*BoltStorage) GetAuthCode ¶
func (s *BoltStorage) GetAuthCode(ctx context.Context, code string) (*AuthorizationCode, error)
func (*BoltStorage) GetAuthRequest ¶
func (s *BoltStorage) GetAuthRequest(ctx context.Context, id string) (*PendingAuthRequest, error)
func (*BoltStorage) GetClient ¶
func (s *BoltStorage) GetClient(ctx context.Context, clientID string) (*RegisteredClient, error)
func (*BoltStorage) GetRefreshToken ¶
func (s *BoltStorage) GetRefreshToken(ctx context.Context, token string) (*RefreshToken, error)
func (*BoltStorage) GetSession ¶
func (s *BoltStorage) GetSession(ctx context.Context, sessionID string) (*AuthSession, error)
func (*BoltStorage) GetSessionByAccessToken ¶
func (s *BoltStorage) GetSessionByAccessToken(ctx context.Context, token string) (*AuthSession, error)
func (*BoltStorage) GetUserByGitHubLogin ¶
func (*BoltStorage) ListClients ¶
func (s *BoltStorage) ListClients(ctx context.Context) ([]*RegisteredClient, error)
func (*BoltStorage) StoreAccessToken ¶
func (s *BoltStorage) StoreAccessToken(ctx context.Context, token *AccessToken) error
Access Tokens
func (*BoltStorage) StoreAuthCode ¶
func (s *BoltStorage) StoreAuthCode(ctx context.Context, code *AuthorizationCode) error
Authorization Codes
func (*BoltStorage) StoreAuthRequest ¶
func (s *BoltStorage) StoreAuthRequest(ctx context.Context, req *PendingAuthRequest) error
Pending Auth Requests
func (*BoltStorage) StoreClient ¶
func (s *BoltStorage) StoreClient(ctx context.Context, client *RegisteredClient) error
Clients
func (*BoltStorage) StoreRefreshToken ¶
func (s *BoltStorage) StoreRefreshToken(ctx context.Context, token *RefreshToken) error
Refresh Tokens
func (*BoltStorage) StoreSession ¶
func (s *BoltStorage) StoreSession(ctx context.Context, session *AuthSession) error
Sessions
func (*BoltStorage) StoreUser ¶
func (s *BoltStorage) StoreUser(ctx context.Context, user *User) error
Users
func (*BoltStorage) UpdateSessionLastUsed ¶
type ClientRegistrationRequest ¶
type ClientRegistrationRequest struct {
RedirectURIs []string `json:"redirect_uris"`
ClientName string `json:"client_name,omitempty"`
ClientURI string `json:"client_uri,omitempty"`
LogoURI string `json:"logo_uri,omitempty"`
Scope []string `json:"scope,omitempty"`
GrantTypes []string `json:"grant_types,omitempty"`
ResponseTypes []string `json:"response_types,omitempty"`
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`
}
ClientRegistrationRequest per RFC 7591
type ClientRegistrationResponse ¶
type ClientRegistrationResponse struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret,omitempty"`
ClientName string `json:"client_name,omitempty"`
ClientURI string `json:"client_uri,omitempty"`
LogoURI string `json:"logo_uri,omitempty"`
RedirectURIs []string `json:"redirect_uris"`
GrantTypes []string `json:"grant_types,omitempty"`
ResponseTypes []string `json:"response_types,omitempty"`
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`
ClientIDIssuedAt int64 `json:"client_id_issued_at,omitempty"`
}
ClientRegistrationResponse per RFC 7591
type CreateStaticClientRequest ¶
type CreateStaticClientRequest struct {
ClientName string `json:"client_name"`
RedirectURIs []string `json:"redirect_uris"`
Scopes []string `json:"scopes,omitempty"`
}
CreateStaticClientRequest is the request body for creating a static client
type GitHubClient ¶
type GitHubClient struct {
// contains filtered or unexported fields
}
GitHubClient handles GitHub OAuth and API interactions
func NewGitHubClient ¶
func NewGitHubClient(cfg config.GitHubConfig) *GitHubClient
NewGitHubClient creates a new GitHub client
func (*GitHubClient) ExchangeCode ¶
ExchangeCode exchanges an authorization code for a GitHub access token
func (*GitHubClient) GetAuthorizationURL ¶
func (gc *GitHubClient) GetAuthorizationURL(callbackURL, state string) string
GetAuthorizationURL returns the GitHub OAuth authorization URL
func (*GitHubClient) GetUser ¶
func (gc *GitHubClient) GetUser(ctx context.Context, token string) (*GitHubUser, error)
GetUser fetches the authenticated user's info from GitHub
func (*GitHubClient) GetUserOrgs ¶
GetUserOrgs fetches the user's organization memberships
func (*GitHubClient) GetUserTeams ¶
func (gc *GitHubClient) GetUserTeams(ctx context.Context, token string) ([]GitHubTeam, error)
GetUserTeams fetches the user's team memberships
type GitHubTeam ¶
type GitHubTeam struct {
ID int64 `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
Organization GitHubOrg `json:"organization"`
}
GitHubTeam represents a GitHub team
type GitHubTokenResponse ¶
type GitHubTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
Scope string `json:"scope"`
Error string `json:"error,omitempty"`
ErrorDesc string `json:"error_description,omitempty"`
}
GitHubTokenResponse represents GitHub's token response
type GitHubUser ¶
type GitHubUser struct {
ID int64 `json:"id"`
Login string `json:"login"`
Name string `json:"name"`
Email string `json:"email"`
AvatarURL string `json:"avatar_url"`
}
GitHubUser represents a GitHub user
type OAuthError ¶
type OAuthError struct {
Error string `json:"error"`
ErrorDescription string `json:"error_description,omitempty"`
ErrorURI string `json:"error_uri,omitempty"`
}
OAuthError represents an OAuth error response per RFC 6749
type PendingAuthRequest ¶
type PendingAuthRequest struct {
ID string `json:"id"`
ClientID string `json:"client_id"`
RedirectURI string `json:"redirect_uri"`
Scope string `json:"scope"`
State string `json:"state"`
CodeChallenge string `json:"code_challenge"`
CodeChallengeMethod string `json:"code_challenge_method"`
Resource string `json:"resource,omitempty"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
}
PendingAuthRequest represents a pending OAuth authorization request
type ProtectedResourceMetadata ¶
type ProtectedResourceMetadata struct {
Resource string `json:"resource"`
AuthorizationServers []string `json:"authorization_servers"`
ScopesSupported []string `json:"scopes_supported,omitempty"`
BearerMethodsSupported []string `json:"bearer_methods_supported,omitempty"`
}
ProtectedResourceMetadata per RFC 9728
type RefreshToken ¶
type RefreshToken struct {
Token string `json:"token"`
ClientID string `json:"client_id"`
UserID string `json:"user_id"`
Scope string `json:"scope"`
Resource string `json:"resource,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
}
RefreshToken represents a refresh token
type RegisteredClient ¶
type RegisteredClient struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret,omitempty"` // Hashed
ClientName string `json:"client_name"`
ClientURI string `json:"client_uri,omitempty"`
LogoURI string `json:"logo_uri,omitempty"`
RedirectURIs []string `json:"redirect_uris"`
Scopes []string `json:"scope,omitempty"`
GrantTypes []string `json:"grant_types,omitempty"`
ResponseTypes []string `json:"response_types,omitempty"`
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`
IsStatic bool `json:"is_static"` // True if from config or admin endpoint
CreatedAt time.Time `json:"created_at"`
}
RegisteredClient represents an OAuth client (dynamic or static)
type StaticClientResponse ¶
type StaticClientResponse struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret,omitempty"` // Only included on creation
ClientName string `json:"client_name"`
RedirectURIs []string `json:"redirect_uris"`
Scopes []string `json:"scopes,omitempty"`
CreatedAt string `json:"created_at"`
}
StaticClientResponse is the response for static client operations
type Storage ¶
type Storage interface {
// Authorization codes
StoreAuthCode(ctx context.Context, code *AuthorizationCode) error
GetAuthCode(ctx context.Context, code string) (*AuthorizationCode, error)
DeleteAuthCode(ctx context.Context, code string) error
// Access tokens
StoreAccessToken(ctx context.Context, token *AccessToken) error
GetAccessToken(ctx context.Context, token string) (*AccessToken, error)
DeleteAccessToken(ctx context.Context, token string) error
// Refresh tokens
StoreRefreshToken(ctx context.Context, token *RefreshToken) error
GetRefreshToken(ctx context.Context, token string) (*RefreshToken, error)
DeleteRefreshToken(ctx context.Context, token string) error
// Registered clients
StoreClient(ctx context.Context, client *RegisteredClient) error
GetClient(ctx context.Context, clientID string) (*RegisteredClient, error)
DeleteClient(ctx context.Context, clientID string) error
ListClients(ctx context.Context) ([]*RegisteredClient, error)
// Users
StoreUser(ctx context.Context, user *User) error
GetUser(ctx context.Context, userID string) (*User, error)
GetUserByGitHubLogin(ctx context.Context, login string) (*User, error)
// Sessions
StoreSession(ctx context.Context, session *AuthSession) error
GetSession(ctx context.Context, sessionID string) (*AuthSession, error)
GetSessionByAccessToken(ctx context.Context, token string) (*AuthSession, error)
UpdateSessionLastUsed(ctx context.Context, sessionID string, lastUsed time.Time) error
DeleteSession(ctx context.Context, sessionID string) error
// Pending auth requests
StoreAuthRequest(ctx context.Context, req *PendingAuthRequest) error
GetAuthRequest(ctx context.Context, id string) (*PendingAuthRequest, error)
DeleteAuthRequest(ctx context.Context, id string) error
// Close
Close() error
}
Storage defines the interface for persisting auth data
type TokenResponse ¶
type TokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
}
TokenResponse is the OAuth token endpoint response
type TokenService ¶
type TokenService struct {
// contains filtered or unexported fields
}
TokenService handles token generation and validation
func NewTokenService ¶
func NewTokenService(issuer string, storage Storage) *TokenService
NewTokenService creates a new token service
func (*TokenService) GenerateAccessToken ¶
func (ts *TokenService) GenerateAccessToken(userID, clientID, scope, resource string) (*AccessToken, error)
GenerateAccessToken creates a new access token
func (*TokenService) GenerateAuthorizationCode ¶
func (ts *TokenService) GenerateAuthorizationCode( clientID, redirectURI, scope, codeChallenge, codeChallengeMethod, resource, userID string, ) (*AuthorizationCode, error)
GenerateAuthorizationCode creates a new authorization code
func (*TokenService) GenerateRefreshToken ¶
func (ts *TokenService) GenerateRefreshToken(userID, clientID, scope, resource string) (*RefreshToken, error)
GenerateRefreshToken creates a new refresh token
func (*TokenService) ValidateAccessToken ¶
func (ts *TokenService) ValidateAccessToken(token string) (*AccessToken, error)
ValidateAccessToken checks if an access token is valid
type User ¶
type User struct {
ID string `json:"id"`
GitHubLogin string `json:"github_login"`
GitHubID int64 `json:"github_id"`
Email string `json:"email,omitempty"`
Name string `json:"name,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
Organizations []string `json:"organizations,omitempty"`
Teams []string `json:"teams,omitempty"` // Format: "org/team"
}
User represents an authenticated user
func GetUserFromContext ¶
GetUserFromContext retrieves the authenticated user from the request context