Documentation
¶
Index ¶
- Constants
- Variables
- func OAuthCallbackURL(publicURL string) string
- type AuthService
- func (s *AuthService) AuthenticateWithMFA(ctx context.Context, challengeToken, code string, trustDevice bool) (*SessionTokens, error)
- func (s *AuthService) AuthenticateWithOIDC(ctx context.Context, state, code string) (*SessionTokens, error)
- func (s *AuthService) AuthenticateWithPassword(ctx context.Context, email, password, deviceToken string) (*SessionTokens, error)
- func (s *AuthService) ChangePassword(ctx context.Context, userID uuid.UUID, oldPassword, newPassword string) error
- func (s *AuthService) CompleteRegistration(ctx context.Context, token, password string) (*SessionTokens, error)
- func (s *AuthService) EnableRequiredMFA(ctx context.Context, setupToken, code string) (*SessionTokens, error)
- func (s *AuthService) HandleTokenReuse(ctx context.Context, userID uuid.UUID)
- func (s *AuthService) Logout(ctx context.Context, refreshToken string) error
- func (s *AuthService) RefreshSession(ctx context.Context, refreshToken string) (*SessionTokens, error)
- func (s *AuthService) SetupRequiredMFA(ctx context.Context, setupToken string) (*MFAEnrollment, error)
- func (s *AuthService) SignOutEverywhere(ctx context.Context, userID uuid.UUID) error
- type DirectPermission
- type EffectivePermission
- type JWTClaims
- type LoginAttemptsService
- func (s *LoginAttemptsService) IsAccountLocked(ctx context.Context, email string) (bool, time.Time, error)
- func (s *LoginAttemptsService) RecordFailedLogin(ctx context.Context, email string, userID *uuid.UUID, lastLoginAt *time.Time) error
- func (s *LoginAttemptsService) RecordSuccessfulLogin(ctx context.Context, userID uuid.UUID) error
- type MFABackupCode
- type MFAEnrollment
- type MFAService
- func (s *MFAService) DisableMFA(ctx context.Context, userID uuid.UUID, password, code string) error
- func (s *MFAService) EnableMFA(ctx context.Context, userID uuid.UUID, code string) error
- func (s *MFAService) GetStatus(ctx context.Context, userID uuid.UUID) (*MFAStatus, error)
- func (s *MFAService) IsMFAEnabled(ctx context.Context, userID uuid.UUID) (bool, error)
- func (s *MFAService) RegenerateBackupCodes(ctx context.Context, userID uuid.UUID, password string) ([]string, error)
- func (s *MFAService) SetupMFA(ctx context.Context, userID uuid.UUID) (*MFAEnrollment, error)
- func (s *MFAService) VerifyCode(ctx context.Context, userID uuid.UUID, code string) error
- type MFASettings
- type MFAStatus
- type OIDCAuthService
- func (s *OIDCAuthService) ProcessCallback(ctx context.Context, state, code string) (*User, error)
- func (s *OIDCAuthService) StartOIDCLogin(ctx context.Context, providerType sdk.OIDCProviderType) (string, error)
- func (s *OIDCAuthService) StartSSOLogin(ctx context.Context, email string) (string, error)
- type OIDCClaims
- type OIDCDiscoveryMetadata
- type OIDCLink
- type OIDCProvider
- type OIDCProviderConfig
- type OIDCProviderService
- func (s *OIDCProviderService) CreateOIDCProvider(ctx context.Context, provider *OIDCProviderConfig, accessToken string) (*OIDCProviderConfig, error)
- func (s *OIDCProviderService) DeleteOIDCProvider(ctx context.Context, providerID uuid.UUID) error
- func (s *OIDCProviderService) GetOIDCProvider(ctx context.Context, providerID uuid.UUID) (*OIDCProviderConfig, error)
- func (s *OIDCProviderService) GetOIDCProvidersByDomain(ctx context.Context, domain string) ([]*OIDCProviderConfig, error)
- func (s *OIDCProviderService) IsSSORequired(ctx context.Context, email string) (bool, error)
- func (s *OIDCProviderService) ListOIDCProviders(ctx context.Context) ([]*OIDCProviderConfig, error)
- func (s *OIDCProviderService) UpdateOIDCProvider(ctx context.Context, params *UpdateOIDCProviderParams) (*OIDCProviderConfig, error)
- type OIDCRegistration
- type OIDCSession
- type OIDCTokenResponse
- type OIDCUserInfo
- type PasswordService
- func (s *PasswordService) ChangePassword(ctx context.Context, userID uuid.UUID, oldPassword, newPassword string) error
- func (s *PasswordService) InitiatePasswordReset(ctx context.Context, email string) error
- func (s *PasswordService) ResetPassword(ctx context.Context, tokenStr, newPassword string) error
- func (s *PasswordService) VerifyCredentials(ctx context.Context, email, password string) (*User, error)
- type Permission
- type RBACService
- func (s *RBACService) CreateRole(ctx context.Context, role *Role) (*Role, error)
- func (s *RBACService) DeleteRole(ctx context.Context, roleID uuid.UUID) error
- func (s *RBACService) GetDirectPermissions(ctx context.Context, userID uuid.UUID) ([]*EffectivePermission, error)
- func (s *RBACService) GetRole(ctx context.Context, roleID uuid.UUID) (*Role, error)
- func (s *RBACService) GetRolePermissions(ctx context.Context, roleID uuid.UUID) ([]*Permission, error)
- func (s *RBACService) GetUserRoles(ctx context.Context, userID uuid.UUID) ([]*Role, error)
- func (s *RBACService) GetUserScopes(ctx context.Context, userID uuid.UUID) ([]Scope, error)
- func (s *RBACService) ListPermissions(ctx context.Context) ([]*Permission, error)
- func (s *RBACService) ListRoles(ctx context.Context) ([]*Role, error)
- func (s *RBACService) SetDirectPermissions(ctx context.Context, userID uuid.UUID, permissions []DirectPermission) error
- func (s *RBACService) SetRolePermissions(ctx context.Context, roleID uuid.UUID, permissionIDs []uuid.UUID) error
- func (s *RBACService) SetUserRoles(ctx context.Context, userID uuid.UUID, roleIDs []uuid.UUID) error
- func (s *RBACService) UpdateRole(ctx context.Context, params UpdateRoleParams) (*Role, error)
- func (s *RBACService) UserRolesRequireMFA(ctx context.Context, userID uuid.UUID) (bool, error)
- type RefreshToken
- type Role
- type Scope
- type SessionService
- func (s *SessionService) DeleteExpiredSessions(ctx context.Context) error
- func (s *SessionService) ListSessions(ctx context.Context, userID uuid.UUID) ([]*RefreshToken, error)
- func (s *SessionService) RevokeAllSessions(ctx context.Context, userID uuid.UUID) error
- func (s *SessionService) RevokeSession(ctx context.Context, sessionID uuid.UUID) error
- func (s *SessionService) RevokeSessionByToken(ctx context.Context, refreshToken string) error
- func (s *SessionService) RotateSession(ctx context.Context, refreshToken string) (*RefreshToken, error)
- func (s *SessionService) StoreSession(ctx context.Context, rt *RefreshToken) error
- func (s *SessionService) ValidateSession(ctx context.Context, refreshToken string) (*RefreshToken, error)
- type SessionTokens
- type Tenant
- type TrustedDevice
- type TrustedDeviceService
- func (s *TrustedDeviceService) CreateTrustedDevice(ctx context.Context, device *TrustedDevice) (string, error)
- func (s *TrustedDeviceService) DeleteExpiredDevices(ctx context.Context) error
- func (s *TrustedDeviceService) RevokeAllTrustedDevices(ctx context.Context, userID uuid.UUID) error
- func (s *TrustedDeviceService) ValidateTrustedDevice(ctx context.Context, deviceToken string, userID uuid.UUID, ipAddress string) (bool, error)
- type UpdateOIDCProviderParams
- type UpdateRoleParams
- type UpdateUserParams
- type User
- type UserService
- func (s *UserService) CreateUser(ctx context.Context, user *User, roleIDs []uuid.UUID) (*User, string, error)
- func (s *UserService) GetUser(ctx context.Context, userID uuid.UUID) (*User, error)
- func (s *UserService) Register(ctx context.Context, email, firstName, lastName string) (*User, error)
- func (s *UserService) VerifyEmailAndSetPassword(ctx context.Context, tokenStr string, password string) (*User, error)
- type UserStatus
- type UserToken
Constants ¶
const ( // DeviceTokenBytes is the number of random bytes for device tokens (256 bits) DeviceTokenBytes = 32 // DeviceTokenPrefix identifies device trust tokens for secret scanning DeviceTokenPrefix = "hmdl_device_" // DeviceTrustDays is the default trust duration DeviceTrustDays = 30 )
Variables ¶
var AllScopes = []Scope{ ScopeUserCreate, ScopeUserRead, ScopeUserUpdate, ScopeUserDelete, ScopeUserAssign, ScopeRoleCreate, ScopeRoleRead, ScopeRoleUpdate, ScopeRoleDelete, ScopeOIDCCreate, ScopeOIDCRead, ScopeOIDCUpdate, ScopeOIDCDelete, }
AllScopes is the canonical list of every scope Heimdall defines. The seed migration must insert exactly these names; a test asserts the two agree.
var ErrAccountAlreadyVerified = errors.New("account has already been verified")
var ErrAccountIsInactive = errors.New("user account is not active")
var ErrAccountLocked = errors.New("account is temporarily locked due to too many failed login attempts")
var ErrAutoProvisioningDisabled = errors.New("automatic user provisioning is not enabled for this domain")
var ErrBackupCodeAlreadyUsed = errors.New("backup code has already been used")
var ErrDuplicateEmail = errors.New("email address is already registered")
var ErrEmailConflict = errors.New("email address conflicts with existing account")
var ErrEmailNotVerified = errors.New("email address not verified")
var ErrInvalidBackupCode = errors.New("invalid backup code")
var ErrInvalidChallengeToken = errors.New("invalid or expired challenge token")
var ErrInvalidCredentials = errors.New("invalid credentials")
Authentication errors
var ErrInvalidMFACode = errors.New("invalid MFA code")
var ErrInvalidOIDCState = errors.New("invalid oidc state parameter")
var ErrInvalidSetupToken = errors.New("invalid or expired setup token")
var ErrMFAAlreadyEnabled = errors.New("MFA is already enabled for this user")
var ErrMFACodeAlreadyUsed = errors.New("MFA code has already been used")
var ErrMFANotEnabled = errors.New("MFA is not enabled for this user")
MFA errors
var ErrMismatchedHash = argon2.ErrMismatchedHash
var ErrOIDCDiscoveryFailed = errors.New("failed to discover OIDC provider")
OIDC discovery and registration errors
var ErrOIDCIssuerMismatch = errors.New("OIDC issuer mismatch")
var ErrOIDCLinkAlreadyExists = errors.New("user already has this provider linked")
var ErrOIDCLinkNotFound = errors.New("oidc link not found")
OIDC flow errors
var ErrOIDCProviderAccountAlreadyLinked = errors.New("this provider account is already linked to another user")
var ErrOIDCProviderNotConfigured = errors.New("OAuth provider is not configured")
var ErrOIDCProviderNotFound = errors.New("oidc provider not found")
var ErrOIDCRegistrationFailed = errors.New("dynamic client registration failed")
var ErrOIDCSessionNotFound = errors.New("oidc session not found or expired")
var ErrPasswordResetTokenNotFound = errors.New("password reset token not found or expired")
var ErrPermissionNotFound = errors.New("permission not found")
var ErrProviderEmailNotVerified = errors.New("email not verified by OAuth provider")
var ErrRoleNotFound = errors.New("role not found")
RBAC errors
var ErrSSONotConfigured = errors.New("SSO is not configured for this domain")
Corporate SSO errors
var ErrSSORequired = errors.New("this email domain requires SSO login")
var ErrSessionNotFound = errors.New("session not found or expired")
Session management errors
var ErrSessionRevoked = errors.New("session has been revoked")
var ErrTokenReused = errors.New("refresh token reuse detected")
var ErrTrustedDeviceNotFound = errors.New("trusted device not found or expired")
Trusted device errors
var ErrUserNotFound = errors.New("user not found")
var ErrVerificationTokenNotFound = errors.New("verification token not found or expired")
var ErrWeakPassword = errors.New("password is too weak")
Functions ¶
func OAuthCallbackURL ¶
OAuthCallbackURL constructs the OAuth callback URL from frontend base URL
Types ¶
type AuthService ¶
type AuthService struct {
PasswordService passwordService
PasswordChangeService passwordChangeService
OIDCService oidcAuthService
UserService userService
MFAService mfaVerificationService
RBACService rbacService
JWTService jwtService
SessionService sessionStorageService
TrustedDeviceService trustedDeviceService
Logger *slog.Logger
}
AuthService orchestrates authentication flows
func (*AuthService) AuthenticateWithMFA ¶
func (s *AuthService) AuthenticateWithMFA(ctx context.Context, challengeToken, code string, trustDevice bool) (*SessionTokens, error)
AuthenticateWithMFA completes MFA challenge and issues final tokens
func (*AuthService) AuthenticateWithOIDC ¶
func (s *AuthService) AuthenticateWithOIDC(ctx context.Context, state, code string) (*SessionTokens, error)
AuthenticateWithOIDC handles OAuth/OIDC callback
func (*AuthService) AuthenticateWithPassword ¶
func (s *AuthService) AuthenticateWithPassword(ctx context.Context, email, password, deviceToken string) (*SessionTokens, error)
AuthenticateWithPassword handles password-based authentication
func (*AuthService) ChangePassword ¶
func (s *AuthService) ChangePassword(ctx context.Context, userID uuid.UUID, oldPassword, newPassword string) error
ChangePassword orchestrates password change with security side effects. Revokes all trusted devices after password change.
func (*AuthService) CompleteRegistration ¶
func (s *AuthService) CompleteRegistration(ctx context.Context, token, password string) (*SessionTokens, error)
CompleteRegistration handles email verification and auto-login
func (*AuthService) EnableRequiredMFA ¶
func (s *AuthService) EnableRequiredMFA(ctx context.Context, setupToken, code string) (*SessionTokens, error)
EnableRequiredMFA validates the setup token, enables MFA, and returns a challenge token
func (*AuthService) HandleTokenReuse ¶
func (s *AuthService) HandleTokenReuse(ctx context.Context, userID uuid.UUID)
HandleTokenReuse handles a detected token reuse attempt (potential theft). Revokes all trusted devices for the user as a security measure.
func (*AuthService) Logout ¶
func (s *AuthService) Logout(ctx context.Context, refreshToken string) error
Logout revokes the session associated with the given refresh token
func (*AuthService) RefreshSession ¶
func (s *AuthService) RefreshSession(ctx context.Context, refreshToken string) (*SessionTokens, error)
RefreshSession validates a refresh token, rotates it, and generates new session tokens. Token rotation: old token is revoked, new token is issued with same family_id. If a revoked token is reused, it's detected as theft and entire family is revoked.
func (*AuthService) SetupRequiredMFA ¶
func (s *AuthService) SetupRequiredMFA(ctx context.Context, setupToken string) (*MFAEnrollment, error)
SetupRequiredMFA validates the setup token and initiates MFA enrollment
func (*AuthService) SignOutEverywhere ¶
SignOutEverywhere revokes all sessions and trusted devices for a user
type DirectPermission ¶
type DirectPermission struct {
PermissionID uuid.UUID
Effect sdk.PermissionEffect
}
DirectPermission represents input for setting direct user permissions
type EffectivePermission ¶
type EffectivePermission struct {
Permission *Permission
Effect sdk.PermissionEffect
}
EffectivePermission represents a user permission assignment
type LoginAttemptsService ¶
LoginAttemptsService handles login attempt tracking and account lockout logic
func (*LoginAttemptsService) IsAccountLocked ¶
func (s *LoginAttemptsService) IsAccountLocked(ctx context.Context, email string) (bool, time.Time, error)
IsAccountLocked checks if an email is currently locked out and when the lock expires
func (*LoginAttemptsService) RecordFailedLogin ¶
func (s *LoginAttemptsService) RecordFailedLogin(ctx context.Context, email string, userID *uuid.UUID, lastLoginAt *time.Time) error
RecordFailedLogin records a failed login attempt and calculates the appropriate lockout expiry
func (*LoginAttemptsService) RecordSuccessfulLogin ¶
RecordSuccessfulLogin clears failed login attempts for the user
type MFABackupCode ¶
type MFABackupCode struct {
ID uuid.UUID
UserID uuid.UUID
CodeHash string
Used bool
UsedAt *time.Time
}
MFABackupCode represents a one-time recovery code
type MFAEnrollment ¶
type MFAEnrollment struct {
Secret string // Base32 encoded secret
QRCode string // data:image/png;base64,...
BackupCodes []string // Plain text (shown once)
}
MFAEnrollment contains TOTP enrollment data
type MFAService ¶
type MFAService struct {
MFASettingsDB mfaSettingsDB
BackupCodesDB mfaBackupCodesDB
UsersDB userDB
Verifier mfaVerifier
Hasher hasher
Logger *slog.Logger
}
MFAService manages multi-factor authentication
func (*MFAService) DisableMFA ¶
DisableMFA disables MFA for a user (requires password and TOTP/backup code)
func (*MFAService) IsMFAEnabled ¶
IsMFAEnabled returns whether MFA is enabled for a user
func (*MFAService) RegenerateBackupCodes ¶
func (s *MFAService) RegenerateBackupCodes(ctx context.Context, userID uuid.UUID, password string) ([]string, error)
RegenerateBackupCodes generates new backup codes (requires password)
func (*MFAService) SetupMFA ¶
func (s *MFAService) SetupMFA(ctx context.Context, userID uuid.UUID) (*MFAEnrollment, error)
SetupMFA initiates MFA setup by generating secret, QR code, and backup codes
func (*MFAService) VerifyCode ¶
VerifyCode verifies an MFA code (TOTP or backup code) for a user
type MFASettings ¶
type MFASettings struct {
UserID uuid.UUID
TOTPSecret string
LastUsedWindow *int64
VerifiedAt *time.Time
LastUsedAt *time.Time
}
MFASettings represents user's MFA configuration
type OIDCAuthService ¶
type OIDCAuthService struct {
OIDCProviderService oidcProviderLookup
OIDCLinkDB oidcLinkDB
OIDCSessionDB oidcSessionDB
UserDB userDB
TenantsDB tenantsDB
SystemProviders map[sdk.OIDCProviderType]OIDCProvider
ProviderFactory oidcProviderFactory
PublicURL string
Logger *slog.Logger
}
OIDCAuthService handles OAuth/SSO authentication flows
func (*OIDCAuthService) ProcessCallback ¶
ProcessCallback processes the OAuth callback and authenticates the user
func (*OIDCAuthService) StartOIDCLogin ¶
func (s *OIDCAuthService) StartOIDCLogin(ctx context.Context, providerType sdk.OIDCProviderType) (string, error)
StartOIDCLogin initiates an OIDC login flow for individual OAuth registration
func (*OIDCAuthService) StartSSOLogin ¶
StartSSOLogin initiates an OIDC login flow for corporate SSO (domain-based discovery)
type OIDCClaims ¶
type OIDCClaims struct {
Sub string
Email string
EmailVerified bool
Name string
Picture string
Issuer string
Audience string
ExpiresAt time.Time
IssuedAt time.Time
}
OIDCClaims represents the claims from an ID token
type OIDCDiscoveryMetadata ¶
type OIDCDiscoveryMetadata struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserInfoEndpoint string `json:"userinfo_endpoint"`
JWKSUri string `json:"jwks_uri"`
RegistrationEndpoint string `json:"registration_endpoint"` // RFC 7591 dynamic registration
ScopesSupported []string `json:"scopes_supported,omitempty"`
}
OIDCDiscoveryMetadata from provider's .well-known/openid-configuration endpoint
type OIDCLink ¶
type OIDCLink struct {
ID uuid.UUID
UserID uuid.UUID
OIDCProviderID uuid.UUID
ProviderUserID string // Provider's immutable 'sub' claim (allows email reassignment)
ProviderEmail string // Email at time of link (may change at provider)
ProviderMetadata map[string]any // Additional claims (name, picture, etc.)
LinkedAt time.Time
LastUsedAt *time.Time
}
OIDCLink tracks SSO users by provider's immutable sub claim (not email)
type OIDCProvider ¶
type OIDCProvider interface {
// GetAuthorizationURL generates the OAuth authorization URL with PKCE
GetAuthorizationURL(state, codeVerifier, redirectURI string) (string, error)
// ExchangeCode exchanges an authorization code for tokens
ExchangeCode(ctx context.Context, code, codeVerifier, redirectURI string) (*OIDCTokenResponse, error)
// GetUserInfo retrieves user information from the provider
GetUserInfo(ctx context.Context, accessToken string) (*OIDCUserInfo, error)
// ValidateIDToken validates and parses an ID token
ValidateIDToken(ctx context.Context, idToken string) (*OIDCClaims, error)
}
OIDCProvider defines the interface for OIDC provider implementations
type OIDCProviderConfig ¶
type OIDCProviderConfig struct {
ID uuid.UUID
TenantID uuid.UUID
ProviderName string // User-defined display name (e.g., "Azure AD - Production")
IssuerURL string // OIDC discovery URL (e.g., https://login.microsoftonline.com/tenant-id)
ClientID string
ClientSecret string
Scopes []string
Enabled bool
// Domain-based SSO routing
AllowedDomains []string // Email domains that trigger this provider (e.g., ['acmecorp.com'])
AutoCreateUsers bool // Auto-provision users on first SSO login
RequireEmailVerification bool // Require provider to verify email
// RFC 7591 dynamic registration metadata (empty for manual registration)
RegistrationAccessToken string
RegistrationClientURI string
ClientIDIssuedAt *time.Time
ClientSecretExpiresAt *time.Time
RegistrationMethod sdk.OIDCRegistrationMethod
}
OIDCProviderConfig represents tenant-specific OIDC provider for corporate SSO
type OIDCProviderService ¶
type OIDCProviderService struct {
OIDCProviderDB oidcProviderDB
RegistrationClient oidcRegistrationClient
ProviderFactory oidcProviderFactory
PublicURL string
Logger *slog.Logger
}
OIDCProviderService handles OIDC provider CRUD operations and domain checks
func (*OIDCProviderService) CreateOIDCProvider ¶
func (s *OIDCProviderService) CreateOIDCProvider(ctx context.Context, provider *OIDCProviderConfig, accessToken string) (*OIDCProviderConfig, error)
CreateOIDCProvider creates a new OIDC provider configuration manually or dynamically
func (*OIDCProviderService) DeleteOIDCProvider ¶
DeleteOIDCProvider deletes an OIDC provider (admin operation) For dynamically registered providers, also attempts to unregister the OAuth client
func (*OIDCProviderService) GetOIDCProvider ¶
func (s *OIDCProviderService) GetOIDCProvider(ctx context.Context, providerID uuid.UUID) (*OIDCProviderConfig, error)
GetOIDCProvider retrieves an OIDC provider by ID
func (*OIDCProviderService) GetOIDCProvidersByDomain ¶
func (s *OIDCProviderService) GetOIDCProvidersByDomain(ctx context.Context, domain string) ([]*OIDCProviderConfig, error)
GetOIDCProvidersByDomain retrieves OIDC providers by domain
func (*OIDCProviderService) IsSSORequired ¶
IsSSORequired verifies if SSO login is required for the email domain
func (*OIDCProviderService) ListOIDCProviders ¶
func (s *OIDCProviderService) ListOIDCProviders(ctx context.Context) ([]*OIDCProviderConfig, error)
ListOIDCProviders lists all OIDC providers for a tenant
func (*OIDCProviderService) UpdateOIDCProvider ¶
func (s *OIDCProviderService) UpdateOIDCProvider(ctx context.Context, params *UpdateOIDCProviderParams) (*OIDCProviderConfig, error)
UpdateOIDCProvider updates an OIDC provider configuration
type OIDCRegistration ¶
type OIDCRegistration struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret,omitempty"`
ClientIDIssuedAt *int64 `json:"client_id_issued_at,omitempty"`
ClientSecretExpiresAt *int64 `json:"client_secret_expires_at,omitempty"` // 0 = never expires
RegistrationAccessToken string `json:"registration_access_token,omitempty"` // For RFC 7592 management
RegistrationClientURI string `json:"registration_client_uri,omitempty"` // Update/delete endpoint
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`
GrantTypes []string `json:"grant_types,omitempty"`
ResponseTypes []string `json:"response_types,omitempty"`
RedirectURIs []string `json:"redirect_uris,omitempty"`
}
OIDCRegistration represents RFC 7591 dynamic client registration response
type OIDCSession ¶
type OIDCSession struct {
ID uuid.UUID
State string // Random state for CSRF protection
CodeVerifier string // PKCE code verifier (hashed in authorization URL)
OIDCProviderID *uuid.UUID // Tenant-specific provider for SSO
ProviderType *sdk.OIDCProviderType // System-wide provider for individual OAuth
RedirectURI string
TenantID *uuid.UUID
ExpiresAt time.Time
}
OIDCSession tracks OAuth flow state for CSRF protection and PKCE
type OIDCTokenResponse ¶
type OIDCTokenResponse struct {
AccessToken string
IDToken string
RefreshToken string
ExpiresIn int
}
OIDCTokenResponse represents tokens from an OAuth token exchange
type OIDCUserInfo ¶
type OIDCUserInfo struct {
Sub string // Provider's unique user ID (immutable)
Email string
EmailVerified bool
Name string
Picture string
Metadata map[string]any // Provider-specific claims
}
OIDCUserInfo from provider's userinfo endpoint (standard + custom claims)
func (*OIDCUserInfo) Validate ¶
func (u *OIDCUserInfo) Validate() error
Validate checks that required claims are present
type PasswordService ¶
type PasswordService struct {
UserDB userDB
PasswordValidator passwordValidator
Hasher hasher
PasswordResetTokenDB tokenDB
EmailClient emailClient
LoginAttemptsService loginAttemptsService
SessionRevoker sessionRevoker
Logger *slog.Logger
}
func (*PasswordService) ChangePassword ¶
func (s *PasswordService) ChangePassword(ctx context.Context, userID uuid.UUID, oldPassword, newPassword string) error
ChangePassword updates a user's password after validating their current password
func (*PasswordService) InitiatePasswordReset ¶
func (s *PasswordService) InitiatePasswordReset(ctx context.Context, email string) error
InitiatePasswordReset generates a password reset token and sends a reset email
func (*PasswordService) ResetPassword ¶
func (s *PasswordService) ResetPassword(ctx context.Context, tokenStr, newPassword string) error
ResetPassword validates the reset token and updates the user's password
func (*PasswordService) VerifyCredentials ¶
func (s *PasswordService) VerifyCredentials(ctx context.Context, email, password string) (*User, error)
VerifyCredentials verifies user credentials and returns the active user account
type Permission ¶
Permission represents a system-wide permission
type RBACService ¶
type RBACService struct {
RolesDB roleDB
PermissionsDB permissionDB
RolePermissionsDB rolePermissionDB
UserRolesDB userRoleDB
UserPermissionsDB userPermissionDB
Logger *slog.Logger
}
func (*RBACService) CreateRole ¶
CreateRole creates a new role
func (*RBACService) DeleteRole ¶
DeleteRole deletes a role
func (*RBACService) GetDirectPermissions ¶
func (s *RBACService) GetDirectPermissions(ctx context.Context, userID uuid.UUID) ([]*EffectivePermission, error)
GetDirectPermissions retrieves direct permissions assigned to a user
func (*RBACService) GetRolePermissions ¶
func (s *RBACService) GetRolePermissions(ctx context.Context, roleID uuid.UUID) ([]*Permission, error)
GetRolePermissions retrieves all permissions for a role
func (*RBACService) GetUserRoles ¶
GetUserRoles retrieves all roles for a user
func (*RBACService) GetUserScopes ¶
GetUserScopes returns all effective permission scopes for a user
func (*RBACService) ListPermissions ¶
func (s *RBACService) ListPermissions(ctx context.Context) ([]*Permission, error)
ListPermissions lists all available permissions (system-wide)
func (*RBACService) ListRoles ¶
func (s *RBACService) ListRoles(ctx context.Context) ([]*Role, error)
ListRoles lists all roles for the current tenant
func (*RBACService) SetDirectPermissions ¶
func (s *RBACService) SetDirectPermissions(ctx context.Context, userID uuid.UUID, permissions []DirectPermission) error
SetDirectPermissions sets all direct permissions for a user (replaces existing direct permissions)
func (*RBACService) SetRolePermissions ¶
func (s *RBACService) SetRolePermissions(ctx context.Context, roleID uuid.UUID, permissionIDs []uuid.UUID) error
SetRolePermissions replaces all permissions for a role (bulk update)
func (*RBACService) SetUserRoles ¶
func (s *RBACService) SetUserRoles(ctx context.Context, userID uuid.UUID, roleIDs []uuid.UUID) error
SetUserRoles sets all roles for a user (replaces existing roles)
func (*RBACService) UpdateRole ¶
func (s *RBACService) UpdateRole(ctx context.Context, params UpdateRoleParams) (*Role, error)
UpdateRole updates a role
func (*RBACService) UserRolesRequireMFA ¶
UserRolesRequireMFA checks if any of the user's assigned roles require MFA
type RefreshToken ¶
type RefreshToken struct {
ID uuid.UUID
UserID uuid.UUID
TokenHash string
FamilyID uuid.UUID // Token family for rotation tracking
UserAgent string
IPAddress string
CreatedAt time.Time
LastUsedAt time.Time
ExpiresAt time.Time
RevokedAt *time.Time
}
RefreshToken represents a stored session for session management
type Scope ¶
Scope is an alias for jwt.Scope
const ( // User management scopes ScopeUserCreate Scope = "heimdall:user:create" // Create new user accounts ScopeUserRead Scope = "heimdall:user:read" // View user information and their role/permission assignments ScopeUserUpdate Scope = "heimdall:user:update" // Update user profile (email, name, status) ScopeUserDelete Scope = "heimdall:user:delete" // Delete user accounts ScopeUserAssign Scope = "heimdall:user:assign" // Assign roles and permissions to users // Role management scopes ScopeRoleCreate Scope = "heimdall:role:create" // Create new roles ScopeRoleRead Scope = "heimdall:role:read" // View roles and their permissions ScopeRoleUpdate Scope = "heimdall:role:update" // Update roles and their permission assignments ScopeRoleDelete Scope = "heimdall:role:delete" // Delete roles // OIDC provider management scopes ScopeOIDCCreate Scope = "heimdall:oidc:create" // Create OIDC/SSO provider configurations ScopeOIDCRead Scope = "heimdall:oidc:read" // View OIDC/SSO provider configurations ScopeOIDCUpdate Scope = "heimdall:oidc:update" // Update OIDC/SSO provider settings ScopeOIDCDelete Scope = "heimdall:oidc:delete" // Delete OIDC/SSO provider configurations )
System-wide scopes for Heimdall authentication and authorization service
type SessionService ¶
SessionService manages refresh token storage for session management
func (*SessionService) DeleteExpiredSessions ¶
func (s *SessionService) DeleteExpiredSessions(ctx context.Context) error
DeleteExpiredSessions cleans up expired and old revoked tokens
func (*SessionService) ListSessions ¶
func (s *SessionService) ListSessions(ctx context.Context, userID uuid.UUID) ([]*RefreshToken, error)
ListSessions returns all active sessions for a user
func (*SessionService) RevokeAllSessions ¶
RevokeAllSessions revokes all sessions for a user (sign out everywhere)
func (*SessionService) RevokeSession ¶
RevokeSession revokes a specific session by ID
func (*SessionService) RevokeSessionByToken ¶
func (s *SessionService) RevokeSessionByToken(ctx context.Context, refreshToken string) error
RevokeSessionByToken revokes a session by the raw refresh token (for logout)
func (*SessionService) RotateSession ¶
func (s *SessionService) RotateSession(ctx context.Context, refreshToken string) (*RefreshToken, error)
RotateSession validates a refresh token and revokes it for rotation. Returns the old token's metadata (including FamilyID) for creating the new token.
func (*SessionService) StoreSession ¶
func (s *SessionService) StoreSession(ctx context.Context, rt *RefreshToken) error
StoreSession stores a refresh token in the database
func (*SessionService) ValidateSession ¶
func (s *SessionService) ValidateSession(ctx context.Context, refreshToken string) (*RefreshToken, error)
ValidateSession checks if a refresh token is valid (not revoked, not expired)
type SessionTokens ¶
type SessionTokens struct {
AccessToken string
RefreshToken string
MFAChallengeToken string
MFASetupToken string
DeviceToken string // Trusted device token (set when user opts to trust device after MFA)
AccessExpiration time.Duration
RefreshExpiration time.Duration
MFAChallengeExpiration time.Duration
MFASetupExpiration time.Duration
}
SessionTokens contains all tokens for an authenticated session
func (*SessionTokens) RequiresMFA ¶
func (s *SessionTokens) RequiresMFA() bool
RequiresMFA returns true if MFA verification is needed to complete authentication
func (*SessionTokens) RequiresMFASetup ¶
func (s *SessionTokens) RequiresMFASetup() bool
RequiresMFASetup returns true if user must set up MFA before getting full access
type TrustedDevice ¶
type TrustedDevice struct {
ID uuid.UUID
UserID uuid.UUID
TokenHash string
UserAgent string
IPAddress string
CreatedAt time.Time
LastUsedAt time.Time
ExpiresAt time.Time
RevokedAt *time.Time
}
TrustedDevice represents a device trusted to skip MFA
type TrustedDeviceService ¶
TrustedDeviceService manages trusted device operations
func (*TrustedDeviceService) CreateTrustedDevice ¶
func (s *TrustedDeviceService) CreateTrustedDevice(ctx context.Context, device *TrustedDevice) (string, error)
CreateTrustedDevice creates a new trusted device entry and returns the raw token.
func (*TrustedDeviceService) DeleteExpiredDevices ¶
func (s *TrustedDeviceService) DeleteExpiredDevices(ctx context.Context) error
DeleteExpiredDevices cleans up expired and old revoked devices
func (*TrustedDeviceService) RevokeAllTrustedDevices ¶
RevokeAllTrustedDevices revokes all trusted devices for a user
type UpdateOIDCProviderParams ¶
type UpdateOIDCProviderParams struct {
ID uuid.UUID
ProviderName *string
ClientSecret *string
Scopes []string
Enabled *bool
AllowedDomains []string
AutoCreateUsers *bool
RequireEmailVerification *bool
}
UpdateOIDCProviderParams supports partial updates using optional pointer fields
type UpdateRoleParams ¶
UpdateRoleParams supports partial updates using optional pointer fields
type UpdateUserParams ¶
type UpdateUserParams struct {
ID uuid.UUID
PasswordHash *string
Status *UserStatus
}
UpdateUserParams supports partial updates using optional pointer fields
type User ¶
type User struct {
ID uuid.UUID
TenantID uuid.UUID
Email string
PasswordHash string
FirstName string
LastName string
Status UserStatus
LastLoginAt *time.Time
}
User represents a user in the system
type UserService ¶
type UserService struct {
UserDB userDB
PasswordValidator passwordValidator
TenantsDB tenantsDB
Hasher hasher
EmailClient emailClient
VerificationTokenDB tokenDB
OIDCService oidcService
RBACService rbacService
Logger *slog.Logger
}
UserService handles user registration, email verification, and user management
func (*UserService) CreateUser ¶
func (s *UserService) CreateUser(ctx context.Context, user *User, roleIDs []uuid.UUID) (*User, string, error)
CreateUser creates a new user and assigns specified roles
func (*UserService) Register ¶
func (s *UserService) Register(ctx context.Context, email, firstName, lastName string) (*User, error)
Register creates new user with email verification, rejects SSO-enforced domains
func (*UserService) VerifyEmailAndSetPassword ¶
func (s *UserService) VerifyEmailAndSetPassword(ctx context.Context, tokenStr string, password string) (*User, error)
VerifyEmailAndSetPassword verifies the email verification token, sets the password, and activates the account
type UserStatus ¶
type UserStatus string
UserStatus represents the status of a user
const ( UserStatusUnverified UserStatus = "unverified" UserStatusActive UserStatus = "active" UserStatusSuspended UserStatus = "suspended" UserStatusInactive UserStatus = "inactive" )