package models import ( "time" "github.com/google/uuid" ) // OAuthClient represents a registered OAuth 2.0 client application type OAuthClient struct { ID uuid.UUID `json:"id" db:"id"` ClientID string `json:"client_id" db:"client_id"` ClientSecret string `json:"-" db:"client_secret"` // Never expose in JSON Name string `json:"name" db:"name"` Description *string `json:"description,omitempty" db:"description"` RedirectURIs []string `json:"redirect_uris" db:"redirect_uris"` // JSON array Scopes []string `json:"scopes" db:"scopes"` // Allowed scopes GrantTypes []string `json:"grant_types" db:"grant_types"` // authorization_code, refresh_token IsPublic bool `json:"is_public" db:"is_public"` // Public clients (SPAs) don't have secret IsActive bool `json:"is_active" db:"is_active"` CreatedBy *uuid.UUID `json:"created_by,omitempty" db:"created_by"` CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` } // OAuthAuthorizationCode represents an authorization code for the OAuth flow type OAuthAuthorizationCode struct { ID uuid.UUID `json:"id" db:"id"` Code string `json:"-" db:"code"` // Hashed ClientID string `json:"client_id" db:"client_id"` UserID uuid.UUID `json:"user_id" db:"user_id"` RedirectURI string `json:"redirect_uri" db:"redirect_uri"` Scopes []string `json:"scopes" db:"scopes"` CodeChallenge *string `json:"-" db:"code_challenge"` // For PKCE CodeChallengeMethod *string `json:"-" db:"code_challenge_method"` // S256 or plain ExpiresAt time.Time `json:"expires_at" db:"expires_at"` UsedAt *time.Time `json:"used_at,omitempty" db:"used_at"` CreatedAt time.Time `json:"created_at" db:"created_at"` } // OAuthAccessToken represents an OAuth access token type OAuthAccessToken struct { ID uuid.UUID `json:"id" db:"id"` TokenHash string `json:"-" db:"token_hash"` ClientID string `json:"client_id" db:"client_id"` UserID uuid.UUID `json:"user_id" db:"user_id"` Scopes []string `json:"scopes" db:"scopes"` ExpiresAt time.Time `json:"expires_at" db:"expires_at"` RevokedAt *time.Time `json:"revoked_at,omitempty" db:"revoked_at"` CreatedAt time.Time `json:"created_at" db:"created_at"` } // OAuthRefreshToken represents an OAuth refresh token type OAuthRefreshToken struct { ID uuid.UUID `json:"id" db:"id"` TokenHash string `json:"-" db:"token_hash"` AccessTokenID uuid.UUID `json:"access_token_id" db:"access_token_id"` ClientID string `json:"client_id" db:"client_id"` UserID uuid.UUID `json:"user_id" db:"user_id"` Scopes []string `json:"scopes" db:"scopes"` ExpiresAt time.Time `json:"expires_at" db:"expires_at"` RevokedAt *time.Time `json:"revoked_at,omitempty" db:"revoked_at"` CreatedAt time.Time `json:"created_at" db:"created_at"` } // OAuthAuthorizeRequest for the authorization endpoint type OAuthAuthorizeRequest struct { ResponseType string `form:"response_type" binding:"required"` // Must be "code" ClientID string `form:"client_id" binding:"required"` RedirectURI string `form:"redirect_uri" binding:"required"` Scope string `form:"scope"` // Space-separated scopes State string `form:"state" binding:"required"` // CSRF protection CodeChallenge string `form:"code_challenge"` // PKCE CodeChallengeMethod string `form:"code_challenge_method"` // S256 (recommended) or plain } // OAuthTokenRequest for the token endpoint type OAuthTokenRequest struct { GrantType string `form:"grant_type" binding:"required"` // authorization_code or refresh_token Code string `form:"code"` // For authorization_code grant RedirectURI string `form:"redirect_uri"` // For authorization_code grant ClientID string `form:"client_id" binding:"required"` ClientSecret string `form:"client_secret"` // For confidential clients CodeVerifier string `form:"code_verifier"` // For PKCE RefreshToken string `form:"refresh_token"` // For refresh_token grant Scope string `form:"scope"` // For refresh_token grant (optional) } // OAuthTokenResponse for successful token requests type OAuthTokenResponse struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` // Always "Bearer" ExpiresIn int `json:"expires_in"` // Seconds until expiration RefreshToken string `json:"refresh_token,omitempty"` Scope string `json:"scope,omitempty"` } // OAuthErrorResponse for OAuth errors (RFC 6749) type OAuthErrorResponse struct { Error string `json:"error"` ErrorDescription string `json:"error_description,omitempty"` ErrorURI string `json:"error_uri,omitempty"` }