Documentation
¶
Overview ¶
Package auth provides authentication and authorization for the DivineSense server.
This package is used by: - server/router/api/v1: gRPC and Connect API interceptors - server/router/fileserver: HTTP file server authentication
Authentication methods supported: - JWT access tokens: Short-lived tokens (15 minutes) for API access - JWT refresh tokens: Long-lived tokens (30 days) for obtaining new access tokens - Personal Access Tokens (PAT): Long-lived tokens for programmatic access
Index ¶
- Constants
- func ExtractBearerToken(authHeader string) string
- func ExtractRefreshTokenFromCookie(cookieHeader string) string
- func GenerateAccessToken(username string, userID int32, expirationTime time.Time, secret []byte) (string, error)
- func GenerateAccessTokenV2(userID int32, username, role, status string, secret []byte) (string, time.Time, error)
- func GeneratePersonalAccessToken() string
- func GenerateRefreshToken(userID int32, tokenID string, secret []byte) (string, time.Time, error)
- func GetAccessToken(ctx context.Context) string
- func GetUserID(ctx context.Context) int32
- func HashPersonalAccessToken(token string) string
- func SetUserClaimsInContext(ctx context.Context, claims *UserClaims) context.Context
- func SetUserInContext(ctx context.Context, user *store.User, accessToken string) context.Context
- type AccessTokenClaims
- type AuthResult
- type Authenticator
- func (a *Authenticator) Authenticate(ctx context.Context, authHeader string) *AuthResult
- func (a *Authenticator) AuthenticateByAccessTokenV2(accessToken string) (*UserClaims, error)
- func (a *Authenticator) AuthenticateByPAT(ctx context.Context, token string) (*store.User, *storepb.PersonalAccessTokensUserSetting_PersonalAccessToken, ...)
- func (a *Authenticator) AuthenticateByRefreshToken(ctx context.Context, refreshToken string) (*store.User, string, error)
- type ClaimsMessage
- type ContextKey
- type RefreshTokenClaims
- type UserClaims
Constants ¶
const ( // Issuer is the issuer claim in JWT tokens. // This identifies tokens as issued by Memos. Issuer = "memos" // KeyID is the key identifier used in JWT header. // Version "v1" allows for future key rotation while maintaining backward compatibility. // If signing mechanism changes, add "v2", "v3", etc. and verify both versions. KeyID = "v1" // AccessTokenAudienceName is the audience claim for JWT access tokens. // This ensures tokens are only used for API access, not other purposes. AccessTokenAudienceName = "user.access-token" // AccessTokenDuration is the lifetime of access tokens (15 minutes). AccessTokenDuration = 15 * time.Minute // RefreshTokenDuration is the lifetime of refresh tokens (30 days). RefreshTokenDuration = 30 * 24 * time.Hour // RefreshTokenAudienceName is the audience claim for refresh tokens. RefreshTokenAudienceName = "user.refresh-token" // RefreshTokenCookieName is the cookie name for refresh tokens. RefreshTokenCookieName = "memos_refresh" // PersonalAccessTokenPrefix is the prefix for PAT tokens. PersonalAccessTokenPrefix = "memos_pat_" )
Variables ¶
This section is empty.
Functions ¶
func ExtractBearerToken ¶
ExtractBearerToken extracts the JWT token from an Authorization header value. Expected format: "Bearer {token}" Returns empty string if no valid bearer token is found.
func ExtractRefreshTokenFromCookie ¶
ExtractRefreshTokenFromCookie extracts the refresh token from cookie header.
func GenerateAccessToken ¶
func GenerateAccessToken(username string, userID int32, expirationTime time.Time, secret []byte) (string, error)
GenerateAccessToken generates a JWT access token for a user.
Parameters: - username: The user's username (stored in "name" claim) - userID: The user's ID (stored in "sub" claim) - expirationTime: When the token expires (pass zero time for no expiration) - secret: Server secret used to sign the token
Returns a signed JWT string or an error.
func GenerateAccessTokenV2 ¶
func GenerateAccessTokenV2(userID int32, username, role, status string, secret []byte) (string, time.Time, error)
GenerateAccessTokenV2 generates a short-lived access token with user claims.
func GeneratePersonalAccessToken ¶
func GeneratePersonalAccessToken() string
GeneratePersonalAccessToken generates a random PAT string.
func GenerateRefreshToken ¶
GenerateRefreshToken generates a long-lived refresh token.
func GetAccessToken ¶
GetAccessToken retrieves the JWT access token from the context. Returns empty string if not authenticated via bearer token.
func GetUserID ¶
GetUserID retrieves the authenticated user's ID from the context. Returns 0 if no user ID is set (unauthenticated request).
func HashPersonalAccessToken ¶
HashPersonalAccessToken returns SHA-256 hash of a PAT.
func SetUserClaimsInContext ¶
func SetUserClaimsInContext(ctx context.Context, claims *UserClaims) context.Context
SetUserClaimsInContext sets the user claims in context.
func SetUserInContext ¶
SetUserInContext sets the authenticated user's information in the context. This is a simpler alternative to AuthorizeAndSetContext for cases where authorization is handled separately (e.g., HTTP middleware).
Parameters:
- user: The authenticated user
- accessToken: Set if authenticated via JWT token (empty string otherwise)
Types ¶
type AccessTokenClaims ¶
type AccessTokenClaims struct {
Type string `json:"type"` // "access"
Role string `json:"role"` // User role
Status string `json:"status"` // User status
Username string `json:"username"` // Username for display
jwt.RegisteredClaims
}
AccessTokenClaims contains claims for short-lived access tokens. These tokens are validated by signature only (stateless).
func ParseAccessTokenV2 ¶
func ParseAccessTokenV2(tokenString string, secret []byte) (*AccessTokenClaims, error)
ParseAccessTokenV2 parses and validates a short-lived access token.
type AuthResult ¶
type AuthResult struct {
User *store.User // Set for PAT authentication
Claims *UserClaims // Set for Access Token V2 (stateless)
AccessToken string // Non-empty if authenticated via JWT
}
AuthResult contains the result of an authentication attempt.
type Authenticator ¶
type Authenticator struct {
// contains filtered or unexported fields
}
Authenticator provides shared authentication and authorization logic. Used by gRPC interceptor, Connect interceptor, and file server to ensure consistent authentication behavior across all API endpoints.
Authentication methods: - JWT access tokens: Short-lived tokens (15 minutes) for API access - Personal Access Tokens (PAT): Long-lived tokens for programmatic access
This struct is safe for concurrent use.
func NewAuthenticator ¶
func NewAuthenticator(store *store.Store, secret string) *Authenticator
NewAuthenticator creates a new Authenticator instance.
func (*Authenticator) Authenticate ¶
func (a *Authenticator) Authenticate(ctx context.Context, authHeader string) *AuthResult
Authenticate tries to authenticate using the provided credentials. Priority: 1. Access Token V2, 2. PAT Returns nil if no valid credentials are provided.
func (*Authenticator) AuthenticateByAccessTokenV2 ¶
func (a *Authenticator) AuthenticateByAccessTokenV2(accessToken string) (*UserClaims, error)
AuthenticateByAccessTokenV2 validates a short-lived access token. Returns claims without database query (stateless validation).
func (*Authenticator) AuthenticateByPAT ¶
func (a *Authenticator) AuthenticateByPAT(ctx context.Context, token string) (*store.User, *storepb.PersonalAccessTokensUserSetting_PersonalAccessToken, error)
AuthenticateByPAT validates a Personal Access Token.
func (*Authenticator) AuthenticateByRefreshToken ¶
func (a *Authenticator) AuthenticateByRefreshToken(ctx context.Context, refreshToken string) (*store.User, string, error)
AuthenticateByRefreshToken validates a refresh token against the database.
type ClaimsMessage ¶
type ClaimsMessage struct {
Name string `json:"name"` // Username
jwt.RegisteredClaims
}
ClaimsMessage represents the claims structure in a JWT token.
JWT Claims include: - name: Username (custom claim) - iss: Issuer = "memos" - aud: Audience = "user.access-token" - sub: Subject = user ID - iat: Issued at time - exp: Expiration time (optional, may be empty for never-expiring tokens).
type ContextKey ¶
type ContextKey int
ContextKey is the key type for context values. Using a custom type prevents collisions with other packages.
const ( // UserIDContextKey stores the authenticated user's ID. // Set for all authenticated requests. // Use GetUserID(ctx) to retrieve this value. UserIDContextKey ContextKey = iota // AccessTokenContextKey stores the JWT token for token-based auth. // Only set when authenticated via Bearer token. AccessTokenContextKey // UserClaimsContextKey stores the claims from access token. UserClaimsContextKey // RefreshTokenIDContextKey stores the refresh token ID. RefreshTokenIDContextKey )
type RefreshTokenClaims ¶
type RefreshTokenClaims struct {
Type string `json:"type"` // "refresh"
TokenID string `json:"tid"` // Token ID for revocation lookup
jwt.RegisteredClaims
}
RefreshTokenClaims contains claims for long-lived refresh tokens. These tokens are validated against the database for revocation.
func ParseRefreshToken ¶
func ParseRefreshToken(tokenString string, secret []byte) (*RefreshTokenClaims, error)
ParseRefreshToken parses and validates a refresh token.
type UserClaims ¶
UserClaims represents authenticated user info from access token.
func GetUserClaims ¶
func GetUserClaims(ctx context.Context) *UserClaims
GetUserClaims retrieves the user claims from context. Returns nil if not authenticated via access token.