Documentation
¶
Overview ¶
Package extauth provides external authentication provider integration. This package implements OIDC/OAuth2 client functionality to authenticate users via external identity providers like Google, GitHub, Microsoft, etc.
Index ¶
- Variables
- type AccountStore
- type AuthState
- type AuthenticatedUser
- type AuthorizeRequest
- type AuthorizeResponse
- type CallbackRequest
- type CallbackResponse
- type ClaimMapping
- type DefaultService
- func (s *DefaultService) AddProvider(cfg *ProviderConfig) error
- func (s *DefaultService) Authorize(ctx context.Context, req *AuthorizeRequest) (*AuthorizeResponse, error)
- func (s *DefaultService) Callback(ctx context.Context, req *CallbackRequest) (*CallbackResponse, error)
- func (s *DefaultService) GetLinkedAccounts(ctx context.Context, userID string) ([]*LinkedAccount, error)
- func (s *DefaultService) GetProvider(ctx context.Context, id string) (*ProviderConfig, error)
- func (s *DefaultService) GetUserInfo(ctx context.Context, providerID, accessToken string) (*UserInfo, error)
- func (s *DefaultService) LinkAccount(ctx context.Context, userID string, req *AuthorizeRequest) (*AuthorizeResponse, error)
- func (s *DefaultService) ListProviders(ctx context.Context) ([]*ProviderInfo, error)
- func (s *DefaultService) RefreshToken(ctx context.Context, providerID, refreshToken string) (*TokenResponse, error)
- func (s *DefaultService) RemoveProvider(id string)
- func (s *DefaultService) UnlinkAccount(ctx context.Context, userID, providerID string) error
- type DiscoveryDocument
- type Handler
- func (h *Handler) Authorize(c echo.Context) error
- func (h *Handler) Callback(c echo.Context) error
- func (h *Handler) ExchangeToken(c echo.Context) error
- func (h *Handler) GetLinkedAccounts(c echo.Context) error
- func (h *Handler) GetUserInfo(c echo.Context) error
- func (h *Handler) LinkAccount(c echo.Context) error
- func (h *Handler) ListProviders(c echo.Context) error
- func (h *Handler) RefreshToken(c echo.Context) error
- func (h *Handler) RegisterProtectedRoutes(g *echo.Group)
- func (h *Handler) RegisterRoutes(g *echo.Group)
- func (h *Handler) UnlinkAccount(c echo.Context) error
- type LinkedAccount
- type MemoryAccountStore
- func (s *MemoryAccountStore) Delete(ctx context.Context, userID, providerID string) error
- func (s *MemoryAccountStore) GetByProviderUser(ctx context.Context, providerID, providerUserID string) (*LinkedAccount, error)
- func (s *MemoryAccountStore) GetByUser(ctx context.Context, userID string) ([]*LinkedAccount, error)
- func (s *MemoryAccountStore) Save(ctx context.Context, account *LinkedAccount) error
- type MemoryStateStore
- type ProviderClient
- func (c *ProviderClient) AuthorizationURL(state, nonce, codeChallenge string) (string, error)
- func (c *ProviderClient) Config() *ProviderConfig
- func (c *ProviderClient) Discover(ctx context.Context) (*DiscoveryDocument, error)
- func (c *ProviderClient) ExchangeCode(ctx context.Context, code, codeVerifier string) (*TokenResponse, error)
- func (c *ProviderClient) GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)
- func (c *ProviderClient) RefreshToken(ctx context.Context, refreshToken string) (*TokenResponse, error)
- type ProviderConfig
- type ProviderInfo
- type ProviderType
- type RoleMapping
- type Service
- type ServiceConfig
- type StateStore
- type TokenGenerator
- type TokenResponse
- type UserInfo
- type UserStore
Constants ¶
This section is empty.
Variables ¶
var ( // ErrProviderNotFound is returned when a provider is not found. ErrProviderNotFound = errors.New("provider not found") // ErrProviderDisabled is returned when a provider is disabled. ErrProviderDisabled = errors.New("provider disabled") // ErrInvalidState is returned when the state parameter is invalid. ErrInvalidState = errors.New("invalid state parameter") // ErrStateExpired is returned when the state has expired. ErrStateExpired = errors.New("state expired") // ErrInvalidCode is returned when the authorization code is invalid. ErrInvalidCode = errors.New("invalid authorization code") // ErrTokenExpired is returned when the token has expired. ErrTokenExpired = errors.New("token expired") // ErrInvalidToken is returned when the token is invalid. ErrInvalidToken = errors.New("invalid token") // ErrInvalidNonce is returned when the nonce is invalid. ErrInvalidNonce = errors.New("invalid nonce") // ErrUserNotFound is returned when the user is not found. ErrUserNotFound = errors.New("user not found") // ErrAccountAlreadyLinked is returned when the account is already linked. ErrAccountAlreadyLinked = errors.New("account already linked to another user") // ErrEmailNotAllowed is returned when the email domain is not allowed. ErrEmailNotAllowed = errors.New("email domain not allowed") // ErrDiscoveryFailed is returned when OIDC discovery fails. ErrDiscoveryFailed = errors.New("OIDC discovery failed") )
Functions ¶
This section is empty.
Types ¶
type AccountStore ¶
type AccountStore interface {
Save(ctx context.Context, account *LinkedAccount) error
GetByProviderUser(ctx context.Context, providerID, providerUserID string) (*LinkedAccount, error)
GetByUser(ctx context.Context, userID string) ([]*LinkedAccount, error)
Delete(ctx context.Context, userID, providerID string) error
}
AccountStore defines the interface for storing linked accounts.
type AuthState ¶
type AuthState struct {
State string `json:"state"`
Nonce string `json:"nonce"`
ProviderID string `json:"provider_id"`
RedirectURI string `json:"redirect_uri"`
CodeVerifier string `json:"code_verifier,omitempty"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
UserID string `json:"user_id,omitempty"` // For account linking
}
AuthState represents the state stored during the auth flow.
type AuthenticatedUser ¶
type AuthenticatedUser struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
Picture string `json:"picture,omitempty"`
Roles []string `json:"roles"`
ProviderID string `json:"provider_id"`
}
AuthenticatedUser represents an authenticated user.
type AuthorizeRequest ¶
type AuthorizeRequest struct {
ProviderID string `json:"provider_id"`
RedirectURI string `json:"redirect_uri,omitempty"`
State string `json:"state,omitempty"`
UserID string `json:"user_id,omitempty"` // For account linking
}
AuthorizeRequest represents a request to start the auth flow.
type AuthorizeResponse ¶
AuthorizeResponse represents the response to start the auth flow.
type CallbackRequest ¶
type CallbackRequest struct {
ProviderID string `json:"provider_id"`
Code string `json:"code"`
State string `json:"state"`
Error string `json:"error,omitempty"`
ErrorDescription string `json:"error_description,omitempty"`
}
CallbackRequest represents the callback from the provider.
type CallbackResponse ¶
type CallbackResponse struct {
User *AuthenticatedUser `json:"user"`
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token,omitempty"`
ExpiresIn int `json:"expires_in"`
IsNewUser bool `json:"is_new_user"`
}
CallbackResponse represents the response after processing the callback.
type ClaimMapping ¶
type ClaimMapping struct {
Subject string `json:"subject" yaml:"subject"`
Email string `json:"email" yaml:"email"`
Name string `json:"name" yaml:"name"`
Picture string `json:"picture,omitempty" yaml:"picture,omitempty"`
Groups string `json:"groups,omitempty" yaml:"groups,omitempty"`
Roles string `json:"roles,omitempty" yaml:"roles,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
}
ClaimMapping maps OIDC claims to user attributes.
func DefaultClaimMapping ¶
func DefaultClaimMapping() *ClaimMapping
DefaultClaimMapping returns the default claim mapping.
type DefaultService ¶
type DefaultService struct {
// contains filtered or unexported fields
}
DefaultService implements the Service interface.
func NewService ¶
func NewService(cfg *ServiceConfig) (*DefaultService, error)
NewService creates a new external auth service.
func (*DefaultService) AddProvider ¶
func (s *DefaultService) AddProvider(cfg *ProviderConfig) error
AddProvider adds a new provider at runtime.
func (*DefaultService) Authorize ¶
func (s *DefaultService) Authorize(ctx context.Context, req *AuthorizeRequest) (*AuthorizeResponse, error)
Authorize starts the authorization flow.
func (*DefaultService) Callback ¶
func (s *DefaultService) Callback(ctx context.Context, req *CallbackRequest) (*CallbackResponse, error)
Callback handles the authorization callback.
func (*DefaultService) GetLinkedAccounts ¶
func (s *DefaultService) GetLinkedAccounts(ctx context.Context, userID string) ([]*LinkedAccount, error)
GetLinkedAccounts returns all linked accounts for a user.
func (*DefaultService) GetProvider ¶
func (s *DefaultService) GetProvider(ctx context.Context, id string) (*ProviderConfig, error)
GetProvider returns a provider by ID.
func (*DefaultService) GetUserInfo ¶
func (s *DefaultService) GetUserInfo(ctx context.Context, providerID, accessToken string) (*UserInfo, error)
GetUserInfo gets user info from the provider.
func (*DefaultService) LinkAccount ¶
func (s *DefaultService) LinkAccount(ctx context.Context, userID string, req *AuthorizeRequest) (*AuthorizeResponse, error)
LinkAccount links an external account to an existing user.
func (*DefaultService) ListProviders ¶
func (s *DefaultService) ListProviders(ctx context.Context) ([]*ProviderInfo, error)
ListProviders returns all enabled providers.
func (*DefaultService) RefreshToken ¶
func (s *DefaultService) RefreshToken(ctx context.Context, providerID, refreshToken string) (*TokenResponse, error)
RefreshToken refreshes an access token.
func (*DefaultService) RemoveProvider ¶
func (s *DefaultService) RemoveProvider(id string)
RemoveProvider removes a provider at runtime.
func (*DefaultService) UnlinkAccount ¶
func (s *DefaultService) UnlinkAccount(ctx context.Context, userID, providerID string) error
UnlinkAccount unlinks an external account from a user.
type DiscoveryDocument ¶
type DiscoveryDocument struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserInfoEndpoint string `json:"userinfo_endpoint,omitempty"`
JWKSURI string `json:"jwks_uri,omitempty"`
ScopesSupported []string `json:"scopes_supported,omitempty"`
ResponseTypesSupported []string `json:"response_types_supported,omitempty"`
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported,omitempty"`
ClaimsSupported []string `json:"claims_supported,omitempty"`
}
DiscoveryDocument represents the OIDC discovery document.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler handles external auth HTTP requests.
func NewHandler ¶
NewHandler creates a new external auth handler.
func (*Handler) ExchangeToken ¶
ExchangeToken exchanges an authorization code for tokens.
func (*Handler) GetLinkedAccounts ¶
GetLinkedAccounts returns all linked accounts for the current user.
func (*Handler) GetUserInfo ¶
GetUserInfo gets user info from the provider.
func (*Handler) LinkAccount ¶
LinkAccount links an external account to the current user.
func (*Handler) ListProviders ¶
ListProviders returns all enabled providers.
func (*Handler) RefreshToken ¶
RefreshToken refreshes an access token.
func (*Handler) RegisterProtectedRoutes ¶
RegisterProtectedRoutes registers routes that require authentication.
func (*Handler) RegisterRoutes ¶
RegisterRoutes registers the external auth routes. Note: Some routes require authentication - use RegisterProtectedRoutes for those.
type LinkedAccount ¶
type LinkedAccount struct {
ID string `json:"id"`
UserID string `json:"user_id"`
ProviderID string `json:"provider_id"`
ProviderUserID string `json:"provider_user_id"`
Email string `json:"email,omitempty"`
Name string `json:"name,omitempty"`
Picture string `json:"picture,omitempty"`
AccessToken string `json:"-"`
RefreshToken string `json:"-"`
TokenExpiry time.Time `json:"token_expiry,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
LinkedAccount represents an external account linked to a user.
type MemoryAccountStore ¶
type MemoryAccountStore struct {
// contains filtered or unexported fields
}
MemoryAccountStore is an in-memory implementation of AccountStore.
func NewMemoryAccountStore ¶
func NewMemoryAccountStore() *MemoryAccountStore
NewMemoryAccountStore creates a new in-memory account store.
func (*MemoryAccountStore) Delete ¶
func (s *MemoryAccountStore) Delete(ctx context.Context, userID, providerID string) error
Delete deletes a linked account.
func (*MemoryAccountStore) GetByProviderUser ¶
func (s *MemoryAccountStore) GetByProviderUser(ctx context.Context, providerID, providerUserID string) (*LinkedAccount, error)
GetByProviderUser gets a linked account by provider and provider user ID.
func (*MemoryAccountStore) GetByUser ¶
func (s *MemoryAccountStore) GetByUser(ctx context.Context, userID string) ([]*LinkedAccount, error)
GetByUser gets all linked accounts for a user.
func (*MemoryAccountStore) Save ¶
func (s *MemoryAccountStore) Save(ctx context.Context, account *LinkedAccount) error
Save saves a linked account.
type MemoryStateStore ¶
type MemoryStateStore struct {
// contains filtered or unexported fields
}
MemoryStateStore is an in-memory implementation of StateStore.
func NewMemoryStateStore ¶
func NewMemoryStateStore() *MemoryStateStore
NewMemoryStateStore creates a new in-memory state store.
func (*MemoryStateStore) Cleanup ¶
func (s *MemoryStateStore) Cleanup(ctx context.Context) error
Cleanup removes expired states.
func (*MemoryStateStore) Delete ¶
func (s *MemoryStateStore) Delete(ctx context.Context, state string) error
Delete deletes an auth state.
type ProviderClient ¶
type ProviderClient struct {
// contains filtered or unexported fields
}
ProviderClient is a client for an external auth provider.
func NewProviderClient ¶
func NewProviderClient(config *ProviderConfig) (*ProviderClient, error)
NewProviderClient creates a new provider client.
func (*ProviderClient) AuthorizationURL ¶
func (c *ProviderClient) AuthorizationURL(state, nonce, codeChallenge string) (string, error)
AuthorizationURL returns the authorization URL for the auth flow.
func (*ProviderClient) Config ¶
func (c *ProviderClient) Config() *ProviderConfig
Config returns the provider configuration.
func (*ProviderClient) Discover ¶
func (c *ProviderClient) Discover(ctx context.Context) (*DiscoveryDocument, error)
Discover fetches the OIDC discovery document.
func (*ProviderClient) ExchangeCode ¶
func (c *ProviderClient) ExchangeCode(ctx context.Context, code, codeVerifier string) (*TokenResponse, error)
ExchangeCode exchanges an authorization code for tokens.
func (*ProviderClient) GetUserInfo ¶
GetUserInfo fetches user info from the userinfo endpoint.
func (*ProviderClient) RefreshToken ¶
func (c *ProviderClient) RefreshToken(ctx context.Context, refreshToken string) (*TokenResponse, error)
RefreshToken refreshes an access token using a refresh token.
type ProviderConfig ¶
type ProviderConfig struct {
// ID is the unique identifier for this provider.
ID string `json:"id" yaml:"id"`
// Name is the display name for this provider.
Name string `json:"name" yaml:"name"`
// Type is the provider type.
Type ProviderType `json:"type" yaml:"type"`
// Enabled indicates if this provider is enabled.
Enabled bool `json:"enabled" yaml:"enabled"`
// ClientID is the OAuth client ID.
ClientID string `json:"client_id" yaml:"client_id"`
// ClientSecret is the OAuth client secret.
ClientSecret string `json:"client_secret" yaml:"client_secret"`
// IssuerURL is the OIDC issuer URL (for discovery).
IssuerURL string `json:"issuer_url,omitempty" yaml:"issuer_url,omitempty"`
// AuthURL is the authorization endpoint URL.
AuthURL string `json:"auth_url,omitempty" yaml:"auth_url,omitempty"`
// TokenURL is the token endpoint URL.
TokenURL string `json:"token_url,omitempty" yaml:"token_url,omitempty"`
// UserInfoURL is the userinfo endpoint URL.
UserInfoURL string `json:"userinfo_url,omitempty" yaml:"userinfo_url,omitempty"`
// JWKSURL is the JWKS endpoint URL.
JWKSURL string `json:"jwks_url,omitempty" yaml:"jwks_url,omitempty"`
// Scopes is the list of scopes to request.
Scopes []string `json:"scopes,omitempty" yaml:"scopes,omitempty"`
// RedirectURL is the callback URL.
RedirectURL string `json:"redirect_url" yaml:"redirect_url"`
// ClaimMapping maps provider claims to user attributes.
ClaimMapping *ClaimMapping `json:"claim_mapping,omitempty" yaml:"claim_mapping,omitempty"`
// RoleMappings maps provider claims to user roles.
RoleMappings []RoleMapping `json:"role_mappings,omitempty" yaml:"role_mappings,omitempty"`
// AutoCreateUser indicates if users should be auto-created.
AutoCreateUser bool `json:"auto_create_user" yaml:"auto_create_user"`
// DefaultRole is the default role for auto-created users.
DefaultRole string `json:"default_role" yaml:"default_role"`
// AllowedDomains restricts login to specific email domains.
AllowedDomains []string `json:"allowed_domains,omitempty" yaml:"allowed_domains,omitempty"`
// IconURL is the URL for the provider's icon.
IconURL string `json:"icon_url,omitempty" yaml:"icon_url,omitempty"`
// Order is the display order for this provider.
Order int `json:"order" yaml:"order"`
}
ProviderConfig holds the configuration for an external auth provider.
type ProviderInfo ¶
type ProviderInfo struct {
ID string `json:"id"`
Name string `json:"name"`
Type ProviderType `json:"type"`
IconURL string `json:"icon_url,omitempty"`
Order int `json:"order"`
}
ProviderInfo represents public information about a provider.
type ProviderType ¶
type ProviderType string
ProviderType represents the type of external auth provider.
const ( // ProviderGeneric is a generic OIDC provider. ProviderGeneric ProviderType = "generic" // ProviderGoogle is Google's OIDC provider. ProviderGoogle ProviderType = "google" // ProviderGitHub is GitHub's OAuth provider. ProviderGitHub ProviderType = "github" // ProviderMicrosoft is Microsoft/Azure AD's OIDC provider. ProviderMicrosoft ProviderType = "microsoft" // ProviderKeycloak is Keycloak's OIDC provider. ProviderKeycloak ProviderType = "keycloak" // ProviderAuthentik is Authentik's OIDC provider. ProviderAuthentik ProviderType = "authentik" // ProviderAuth0 is Auth0's OIDC provider. ProviderAuth0 ProviderType = "auth0" )
type RoleMapping ¶
type RoleMapping struct {
Claim string `json:"claim" yaml:"claim"`
Value string `json:"value" yaml:"value"`
Role string `json:"role" yaml:"role"`
}
RoleMapping maps a claim value to a role.
type Service ¶
type Service interface {
// ListProviders returns all enabled providers.
ListProviders(ctx context.Context) ([]*ProviderInfo, error)
// GetProvider returns a provider by ID.
GetProvider(ctx context.Context, id string) (*ProviderConfig, error)
// Authorize starts the authorization flow.
Authorize(ctx context.Context, req *AuthorizeRequest) (*AuthorizeResponse, error)
// Callback handles the authorization callback.
Callback(ctx context.Context, req *CallbackRequest) (*CallbackResponse, error)
// RefreshToken refreshes an access token.
RefreshToken(ctx context.Context, providerID, refreshToken string) (*TokenResponse, error)
// GetUserInfo gets user info from the provider.
GetUserInfo(ctx context.Context, providerID, accessToken string) (*UserInfo, error)
// LinkAccount links an external account to an existing user.
LinkAccount(ctx context.Context, userID string, req *AuthorizeRequest) (*AuthorizeResponse, error)
// UnlinkAccount unlinks an external account from a user.
UnlinkAccount(ctx context.Context, userID, providerID string) error
// GetLinkedAccounts returns all linked accounts for a user.
GetLinkedAccounts(ctx context.Context, userID string) ([]*LinkedAccount, error)
}
Service defines the external auth service interface.
type ServiceConfig ¶
type ServiceConfig struct {
Providers []*ProviderConfig
StateStore StateStore
AccountStore AccountStore
UserStore UserStore
TokenGenerator TokenGenerator
StateTTL time.Duration
}
ServiceConfig holds the service configuration.
type StateStore ¶
type StateStore interface {
Save(ctx context.Context, state *AuthState) error
Get(ctx context.Context, state string) (*AuthState, error)
Delete(ctx context.Context, state string) error
Cleanup(ctx context.Context) error
}
StateStore defines the interface for storing auth state.
type TokenGenerator ¶
type TokenGenerator interface {
GenerateAccessToken(userID, username, role string) (string, error)
}
TokenGenerator generates access tokens for authenticated users.
type TokenResponse ¶
type TokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
IDToken string `json:"id_token,omitempty"`
Scope string `json:"scope,omitempty"`
}
TokenResponse represents the token endpoint response.
type UserInfo ¶
type UserInfo struct {
Subject string `json:"sub"`
Email string `json:"email,omitempty"`
EmailVerified bool `json:"email_verified,omitempty"`
Name string `json:"name,omitempty"`
GivenName string `json:"given_name,omitempty"`
FamilyName string `json:"family_name,omitempty"`
Picture string `json:"picture,omitempty"`
Locale string `json:"locale,omitempty"`
Username string `json:"preferred_username,omitempty"`
Groups []string `json:"groups,omitempty"`
Roles []string `json:"roles,omitempty"`
}
UserInfo represents user information from the provider.
type UserStore ¶
type UserStore interface {
GetByID(ctx context.Context, id string) (*AuthenticatedUser, error)
GetByEmail(ctx context.Context, email string) (*AuthenticatedUser, error)
Create(ctx context.Context, user *AuthenticatedUser) error
Update(ctx context.Context, user *AuthenticatedUser) error
}
UserStore defines the interface for user operations.