auth

package
v0.0.0-...-039c105 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 29, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Index

Constants

View Source
const (
	GitHubAuthorizeURL = "https://github.com/login/oauth/authorize"
	GitHubTokenURL     = "https://github.com/login/oauth/access_token"
	GitHubAPIURL       = "https://api.github.com"
)
View Source
const (
	ContextKeyUser        contextKey = "auth_user"
	ContextKeyAccessToken contextKey = "auth_access_token"
	ContextKeySession     contextKey = "auth_session"
)
View Source
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

View Source
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

View Source
const (
	AccessTokenLength  = 32 // 256 bits
	RefreshTokenLength = 32
	AuthCodeLength     = 32
	ClientIDLength     = 16
	ClientSecretLength = 32

	AccessTokenTTL  = 1 * time.Hour
	RefreshTokenTTL = 24 * time.Hour * 30 // 30 days
	AuthCodeTTL     = 10 * time.Minute
)

Variables

View Source
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

func ValidateCodeChallenge(codeChallenge, method string) error

ValidateCodeChallenge validates a code_challenge during authorization

func ValidatePKCE

func ValidatePKCE(codeVerifier, codeChallenge, method string) error

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) Close

func (s *BoltStorage) Close() error

Close closes the database

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) GetUser

func (s *BoltStorage) GetUser(ctx context.Context, userID string) (*User, error)

func (*BoltStorage) GetUserByGitHubLogin

func (s *BoltStorage) GetUserByGitHubLogin(ctx context.Context, login string) (*User, error)

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

func (s *BoltStorage) UpdateSessionLastUsed(ctx context.Context, sessionID string, lastUsed time.Time) error

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

func (gc *GitHubClient) ExchangeCode(ctx context.Context, code, callbackURL string) (string, error)

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

func (gc *GitHubClient) GetUserOrgs(ctx context.Context, token string) ([]GitHubOrg, error)

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 GitHubOrg

type GitHubOrg struct {
	ID    int64  `json:"id"`
	Login string `json:"login"`
}

GitHubOrg represents a GitHub organization

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

func GetUserFromContext(ctx context.Context) *User

GetUserFromContext retrieves the authenticated user from the request context

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL