Files
at-container-registry/pkg/auth/token/claims.go

78 lines
2.5 KiB
Go

package token
import (
"time"
"atcr.io/pkg/auth"
"github.com/golang-jwt/jwt/v5"
)
// Auth method constants
const (
AuthMethodOAuth = "oauth"
AuthMethodAppPassword = "app_password"
)
// Claims represents the JWT claims for registry authentication
// This follows the Docker Registry token specification
type Claims struct {
jwt.RegisteredClaims
Access []auth.AccessEntry `json:"access,omitempty"`
AuthMethod string `json:"auth_method,omitempty"` // "oauth" or "app_password"
}
// NewClaims creates a new Claims structure with standard fields
func NewClaims(subject, issuer, audience string, expiration time.Duration, access []auth.AccessEntry, authMethod string) *Claims {
now := time.Now()
return &Claims{
RegisteredClaims: jwt.RegisteredClaims{
Subject: subject, // User's DID
Issuer: issuer, // "atcr.io"
Audience: jwt.ClaimStrings{audience}, // Service name
IssuedAt: jwt.NewNumericDate(now),
NotBefore: jwt.NewNumericDate(now),
ExpiresAt: jwt.NewNumericDate(now.Add(expiration)),
},
Access: access,
AuthMethod: authMethod, // "oauth" or "app_password"
}
}
// ExtractAuthMethod parses a JWT token string and extracts the auth_method claim
// Returns the auth method or empty string if not found or token is invalid
// This does NOT validate the token - it only parses it to extract the claim
func ExtractAuthMethod(tokenString string) string {
// Parse token without validation (we only need the claims, validation is done by distribution library)
parser := jwt.NewParser(jwt.WithoutClaimsValidation())
token, _, err := parser.ParseUnverified(tokenString, &Claims{})
if err != nil {
return "" // Invalid token format
}
claims, ok := token.Claims.(*Claims)
if !ok {
return "" // Wrong claims type
}
return claims.AuthMethod
}
// ExtractSubject parses a JWT token string and extracts the Subject claim (the user's DID)
// Returns the subject or empty string if not found or token is invalid
// This does NOT validate the token - it only parses it to extract the claim
func ExtractSubject(tokenString string) string {
// Parse token without validation (we only need the claims, validation is done by distribution library)
parser := jwt.NewParser(jwt.WithoutClaimsValidation())
token, _, err := parser.ParseUnverified(tokenString, &Claims{})
if err != nil {
return "" // Invalid token format
}
claims, ok := token.Claims.(*Claims)
if !ok {
return "" // Wrong claims type
}
return claims.Subject
}