Documentation
¶
Index ¶
- Constants
- Variables
- func GetHTTPStatus(err error) int
- func IsOAuthError(err error) bool
- type AuthorizeRequest
- type AuthorizeResponse
- type CallbackRequest
- type CallbackResponse
- type Client
- func (c *Client) AddPresentationTemplateForTesting(template *configuration.PresentationRequestTemplate)
- func (c *Client) Authorize(ctx context.Context, req *AuthorizeRequest) (*AuthorizeResponse, error)
- func (c *Client) CompletedResponseCode(ctx context.Context, sessionID string) (string, error)
- func (c *Client) ConfirmCredentialDisplay(ctx context.Context, req *ConfirmCredentialDisplayRequest) (*ConfirmCredentialDisplayResponse, error)
- func (c *Client) CreateRequestObject(ctx context.Context, sessionID string, dcqlQuery *openid4vp.DCQL, nonce string, ...) (string, error)
- func (c *Client) DeleteClient(ctx context.Context, req *DeleteClientRequest) error
- func (c *Client) GetClientInformation(ctx context.Context, req *GetClientInformationRequest) (*ClientInformationResponse, error)
- func (c *Client) GetCredentialDisplayData(ctx context.Context, req *GetCredentialDisplayDataRequest) (*GetCredentialDisplayDataResponse, error)
- func (c *Client) GetDiscoveryMetadata(ctx context.Context) (*DiscoveryMetadata, error)
- func (c *Client) GetJWKS(ctx context.Context) (*jose.JWKS, error)
- func (c *Client) GetOIDCRequestObject(ctx context.Context, req *GetRequestObjectRequest) (*GetRequestObjectResponse, error)
- func (c *Client) GetPollStatus(ctx context.Context, sessionID string) (*SessionPollResponse, error)
- func (c *Client) GetQRCode(ctx context.Context, req *GetQRCodeRequest) (*GetQRCodeResponse, error)
- func (c *Client) GetRequestObject(ctx context.Context, sessionID string) (*openid4vp.RequestObject, error)
- func (c *Client) GetUserInfo(ctx context.Context, req *UserInfoRequest) (UserInfoResponse, error)
- func (c *Client) HandleDirectPost(ctx context.Context, sessionID string, vpToken string, ...) error
- func (c *Client) Health(ctx context.Context, req *apiv1_status.StatusRequest) (*apiv1_status.StatusReply, error)
- func (c *Client) IsActiveAuthSession(ctx context.Context, sessionID string) (bool, error)
- func (c *Client) OAuthMetadata(ctx context.Context) (*oauth2.AuthorizationServerMetadata, error)
- func (c *Client) PollSession(ctx context.Context, req *PollSessionRequest) (*PollSessionResponse, error)
- func (c *Client) ProcessCallback(ctx context.Context, req *CallbackRequest) (*CallbackResponse, error)
- func (c *Client) ProcessDirectPost(ctx context.Context, req *DirectPostRequest) (*DirectPostResponse, error)
- func (c *Client) RegisterClient(ctx context.Context, req *ClientRegistrationRequest) (*ClientRegistrationResponse, error)
- func (c *Client) ScopeQueryIDs(ctx context.Context, dcql *openid4vp.DCQL, scopes []string) map[string]string
- func (c *Client) SetSigningKeyForTesting(key any) error
- func (c *Client) Token(ctx context.Context, req *TokenRequest) (*TokenResponse, error)
- func (c *Client) UIInteraction(ctx context.Context, req *UIInteractionRequest) (*UIInteractionReply, error)
- func (c *Client) UIMetadata(ctx context.Context) (*UIMetadataReply, error)
- func (c *Client) UIResume(ctx context.Context, sessionID string) (*UIResumeReply, error)
- func (c *Client) UpdateClient(ctx context.Context, req *UpdateClientRequest) (*ClientRegistrationResponse, error)
- func (c *Client) UpdateSessionPreference(ctx context.Context, req *UpdateSessionPreferenceRequest) (*UpdateSessionPreferenceResponse, error)
- func (c *Client) VerificationCallback(ctx context.Context, req *VerificationCallbackRequest) (*VerificationCallbackResponse, error)
- func (c *Client) VerificationDirectPost(ctx context.Context, req *VerificationDirectPostRequest) (*VerificationDirectPostResponse, error)
- func (c *Client) VerificationRequestObject(ctx context.Context, req *VerificationRequestObjectRequest) (string, error)
- type ClientInformationResponse
- type ClientRegistrationRequest
- type ClientRegistrationResponse
- type ConfirmCredentialDisplayRequest
- type ConfirmCredentialDisplayResponse
- type CredentialFormat
- type DeleteClientRequest
- type DirectPostRequest
- type DirectPostResponse
- type DiscoveryMetadata
- type GetClientInformationRequest
- type GetCredentialDisplayDataRequest
- type GetCredentialDisplayDataResponse
- type GetQRCodeRequest
- type GetQRCodeResponse
- type GetRequestObjectRequest
- type GetRequestObjectResponse
- type OAuthError
- func AsOAuthError(err error) *OAuthError
- func NewInvalidClientError(description string) *OAuthError
- func NewInvalidGrantError(description string) *OAuthError
- func NewInvalidRequestError(description string) *OAuthError
- func NewInvalidScopeError(description string) *OAuthError
- func NewOAuthError(code string, description string, httpStatus int) *OAuthError
- func NewServerError(description string, cause error) *OAuthError
- type PollSessionRequest
- type PollSessionResponse
- type SessionPollResponse
- type TokenRequest
- type TokenResponse
- type UICredentialInfo
- type UIInteractionReply
- type UIInteractionRequest
- type UIMetadataReply
- type UIPreset
- type UIPresetClaim
- type UIPresetCredential
- type UIPresetMeta
- type UIResumeReply
- type UIResumeStatus
- type UpdateClientRequest
- type UpdateSessionPreferenceRequest
- type UpdateSessionPreferenceResponse
- type UserInfoRequest
- type UserInfoResponse
- type VerificationCallbackRequest
- type VerificationCallbackResponse
- type VerificationDirectPostRequest
- type VerificationDirectPostResponse
- type VerificationRequestObjectRequest
- type WalletLink
Constants ¶
const ( ErrCodeInvalidRequest = "invalid_request" ErrCodeInvalidClient = "invalid_client" ErrCodeInvalidGrant = "invalid_grant" ErrCodeUnsupportedGrantType = "unsupported_grant_type" ErrCodeInvalidScope = "invalid_scope" ErrCodeAccessDenied = "access_denied" ErrCodeUnsupportedResponseType = "unsupported_response_type" ErrCodeServerError = "server_error" // OIDC specific errors ErrCodeInteractionRequired = "interaction_required" ErrCodeLoginRequired = "login_required" ErrCodeAccountSelection = "account_selection_required" ErrCodeConsentRequired = "consent_required" ErrCodeInvalidRequestURI = "invalid_request_uri" ErrCodeInvalidRequestObject = "invalid_request_object" // Additional errors ErrCodeInvalidToken = "invalid_token" ErrCodeExpiredToken = "expired_token" ErrCodeSessionExpired = "session_expired" )
Standard OAuth 2.0 error codes
Variables ¶
var ( ErrInvalidRequest = &OAuthError{ ErrorCode: ErrCodeInvalidRequest, ErrorDescription: "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed", HTTPStatus: http.StatusBadRequest, } ErrInvalidClient = &OAuthError{ ErrorCode: ErrCodeInvalidClient, ErrorDescription: "Client authentication failed", HTTPStatus: http.StatusUnauthorized, } ErrInvalidGrant = &OAuthError{ ErrorCode: ErrCodeInvalidGrant, ErrorDescription: "The provided authorization grant is invalid, expired, revoked, or does not match the redirection URI", HTTPStatus: http.StatusBadRequest, } ErrorCode: ErrCodeUnauthorizedClient, ErrorDescription: "The client is not authorized to request an authorization code or access token using this method", HTTPStatus: http.StatusUnauthorized, } ErrUnsupportedGrantType = &OAuthError{ ErrorCode: ErrCodeUnsupportedGrantType, ErrorDescription: "The authorization grant type is not supported by the authorization server", HTTPStatus: http.StatusBadRequest, } ErrInvalidScope = &OAuthError{ ErrorCode: ErrCodeInvalidScope, ErrorDescription: "The requested scope is invalid, unknown, or malformed", HTTPStatus: http.StatusBadRequest, } ErrAccessDenied = &OAuthError{ ErrorCode: ErrCodeAccessDenied, ErrorDescription: "The resource owner or authorization server denied the request", HTTPStatus: http.StatusForbidden, } ErrUnsupportedResponseType = &OAuthError{ ErrorCode: ErrCodeUnsupportedResponseType, ErrorDescription: "The authorization server does not support obtaining an authorization code using this method", HTTPStatus: http.StatusBadRequest, } ErrServerError = &OAuthError{ ErrorCode: ErrCodeServerError, ErrorDescription: "The authorization server encountered an unexpected condition that prevented it from fulfilling the request", HTTPStatus: http.StatusInternalServerError, } ErrorCode: ErrCodeTemporarilyUnavailable, ErrorDescription: "The authorization server is currently unable to handle the request due to temporary overloading or maintenance", HTTPStatus: http.StatusServiceUnavailable, } ErrInvalidToken = &OAuthError{ ErrorCode: ErrCodeInvalidToken, ErrorDescription: "The access token provided is expired, revoked, malformed, or invalid for other reasons", HTTPStatus: http.StatusUnauthorized, } ErrExpiredToken = &OAuthError{ ErrorCode: ErrCodeExpiredToken, ErrorDescription: "The token has expired", HTTPStatus: http.StatusUnauthorized, } ErrSessionNotFound = &OAuthError{ ErrorCode: ErrCodeInvalidGrant, ErrorDescription: "Session not found or expired", HTTPStatus: http.StatusBadRequest, } ErrSessionExpired = &OAuthError{ ErrorCode: ErrCodeSessionExpired, ErrorDescription: "The session has expired", HTTPStatus: http.StatusBadRequest, } ErrInvalidVP = &OAuthError{ ErrorCode: ErrCodeInvalidRequest, ErrorDescription: "Invalid verifiable presentation", HTTPStatus: http.StatusBadRequest, } // ErrNotFound is a generic not found error ErrNotFound = errors.New("not found") // ErrRequestNotSupported indicates the OP does not support the request ErrRequestNotSupported = &OAuthError{ ErrorCode: ErrCodeInvalidRequest, ErrorDescription: "The request is not supported by this server", HTTPStatus: http.StatusNotFound, } )
Pre-defined error variables for common cases
Functions ¶
func GetHTTPStatus ¶
GetHTTPStatus returns the HTTP status code for an error Returns the OAuthError's HTTPStatus if it's an OAuthError, otherwise 500
func IsOAuthError ¶
IsOAuthError checks if an error is an OAuthError
Types ¶
type AuthorizeRequest ¶
type AuthorizeRequest struct {
ResponseType string `form:"response_type" binding:"required" validate:"required,max=128,printascii"`
ClientID string `form:"client_id" binding:"required" validate:"required,max=128,printascii"`
RedirectURI string `form:"redirect_uri" binding:"required" validate:"required,max=2048,printascii"`
Scope string `form:"scope" binding:"required" validate:"required,max=1024,printascii"`
State string `form:"state" validate:"omitempty,max=500,printascii"`
Nonce string `form:"nonce" validate:"omitempty,max=256,printascii"`
CodeChallenge string `form:"code_challenge" validate:"omitempty,max=128,printascii"`
CodeChallengeMethod string `form:"code_challenge_method" validate:"omitempty,max=128,printascii"`
ResponseMode string `form:"response_mode" validate:"omitempty,max=128,printascii"`
Display string `form:"display" validate:"omitempty,max=128,printascii"`
Prompt string `form:"prompt" validate:"omitempty,max=128,printascii"`
MaxAge int `form:"max_age"`
UILocales string `form:"ui_locales" validate:"omitempty,max=256,printascii"`
IDTokenHint string `form:"id_token_hint" validate:"omitempty,max=8192,printascii"`
LoginHint string `form:"login_hint" validate:"omitempty,max=256,printascii"`
ACRValues string `form:"acr_values" validate:"omitempty,max=512,printascii"`
}
AuthorizeRequest represents an OIDC authorization request
type AuthorizeResponse ¶
type AuthorizeResponse struct {
SessionID string `json:"session_id"`
QRCodeData string `json:"qr_code_data"`
QRCodeImageURL string `json:"qr_code_image_url"`
DeepLinkURL string `json:"deep_link_url"`
PollURL string `json:"poll_url"`
WalletLinks []WalletLink `json:"wallet_links,omitempty"`
PreferredFormats []string `json:"preferred_formats"`
UseJAR bool `json:"use_jar"`
ResponseMode string `json:"response_mode"`
Title string `json:"title"`
Subtitle string `json:"subtitle"`
PrimaryColor string `json:"primary_color"`
SecondaryColor string `json:"secondary_color"`
Theme string `json:"theme"`
CustomCSS string `json:"custom_css"`
CSSFile string `json:"css_file"`
LogoURL string `json:"logo_url"`
}
AuthorizeResponse represents the response to an authorization request
type CallbackRequest ¶
type CallbackRequest struct {
State string `form:"state" binding:"required" validate:"required,max=128,printascii"`
Code string `form:"code" validate:"omitempty,max=128,printascii"`
Error string `form:"error" validate:"omitempty,max=1000,printascii"`
}
CallbackRequest represents a callback request
type CallbackResponse ¶
type CallbackResponse struct {
RedirectURI string
}
CallbackResponse contains the redirect URI
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client holds the public api object
func New ¶
func New(ctx context.Context, db *db.Service, notify *notify.Service, cacheService *cache.Service, cfg *model.Cfg, tracer *trace.Tracer, meter *metric.Meter, log *logger.Log) (*Client, error)
New creates a new instance of the public api
func (*Client) AddPresentationTemplateForTesting ¶
func (c *Client) AddPresentationTemplateForTesting(template *configuration.PresentationRequestTemplate)
AddPresentationTemplateForTesting adds a presentation template for testing This rebuilds the presentation builder with the new template
func (*Client) Authorize ¶
func (c *Client) Authorize(ctx context.Context, req *AuthorizeRequest) (*AuthorizeResponse, error)
Authorize handles the OIDC authorization request
func (*Client) CompletedResponseCode ¶ added in v0.7.21
CompletedResponseCode returns the VerifierResponseCode set on the authorization context named by sessionID, or "" when the session is unknown or still in flight. Used by /ui/resume so a verifier UI reloaded after the wallet has already answered can recover the response_code it never had a chance to receive over SSE.
A nil error with "" means the lookup succeeded and the context is still pending (or genuinely absent). A non-nil error means the authorization store itself failed; the caller surfaces that so the client can retry instead of latching onto a bogus "pending" and never reconciling the lost completion.
func (*Client) ConfirmCredentialDisplay ¶
func (c *Client) ConfirmCredentialDisplay(ctx context.Context, req *ConfirmCredentialDisplayRequest) (*ConfirmCredentialDisplayResponse, error)
ConfirmCredentialDisplay handles user confirmation after viewing credential details
func (*Client) CreateRequestObject ¶
func (c *Client) CreateRequestObject(ctx context.Context, sessionID string, dcqlQuery *openid4vp.DCQL, nonce string, transactionData []openid4vp.TransactionData) (string, error)
CreateRequestObject creates and signs an OpenID4VP request object
func (*Client) DeleteClient ¶
func (c *Client) DeleteClient(ctx context.Context, req *DeleteClientRequest) error
DeleteClient deletes a client registration (RFC 7592)
func (*Client) GetClientInformation ¶
func (c *Client) GetClientInformation(ctx context.Context, req *GetClientInformationRequest) (*ClientInformationResponse, error)
GetClientInformation retrieves client configuration (RFC 7592)
func (*Client) GetCredentialDisplayData ¶
func (c *Client) GetCredentialDisplayData(ctx context.Context, req *GetCredentialDisplayDataRequest) (*GetCredentialDisplayDataResponse, error)
GetCredentialDisplayData retrieves data needed for the credential display page
func (*Client) GetDiscoveryMetadata ¶
func (c *Client) GetDiscoveryMetadata(ctx context.Context) (*DiscoveryMetadata, error)
GetDiscoveryMetadata returns OpenID Provider configuration
func (*Client) GetOIDCRequestObject ¶
func (c *Client) GetOIDCRequestObject(ctx context.Context, req *GetRequestObjectRequest) (*GetRequestObjectResponse, error)
GetOIDCRequestObject generates and returns a signed JWT request object for OpenID4VP
func (*Client) GetPollStatus ¶
GetPollStatus returns the current status of a session for polling
func (*Client) GetQRCode ¶
func (c *Client) GetQRCode(ctx context.Context, req *GetQRCodeRequest) (*GetQRCodeResponse, error)
GetQRCode generates a QR code image for a session
func (*Client) GetRequestObject ¶
func (c *Client) GetRequestObject(ctx context.Context, sessionID string) (*openid4vp.RequestObject, error)
GetRequestObject retrieves a request object by session ID
func (*Client) GetUserInfo ¶
func (c *Client) GetUserInfo(ctx context.Context, req *UserInfoRequest) (UserInfoResponse, error)
GetUserInfo returns user claims based on a JWT access token. The endpoint is fully stateless: it validates the JWT signature and expiration using the same signing key that issued the token, then returns the embedded claims.
func (*Client) HandleDirectPost ¶
func (c *Client) HandleDirectPost(ctx context.Context, sessionID string, vpToken string, presentationSubmission any) error
HandleDirectPost processes the OpenID4VP direct_post response from a wallet
func (*Client) Health ¶
func (c *Client) Health(ctx context.Context, req *apiv1_status.StatusRequest) (*apiv1_status.StatusReply, error)
Health returns the readiness of the verifier service.
func (*Client) IsActiveAuthSession ¶ added in v0.7.21
IsActiveAuthSession reports whether sessionID names an authorization context the verifier currently tracks. Used by /ui/notify to refuse to open an SSE listener for an unknown id, which would otherwise let any unauthenticated caller inflate notify.Service's broadcaster map.
(false, nil) means the lookup succeeded and the id is unknown (ErrNoDocuments) or empty. A non-nil error means the authorization store itself failed; the HTTP endpoint surfaces that as a retryable 5xx so a transient Mongo/Redis error in HA does not get mis-reported as 404 and strand the EventSource reconciliation that would run on retry.
func (*Client) OAuthMetadata ¶
func (*Client) PollSession ¶
func (c *Client) PollSession(ctx context.Context, req *PollSessionRequest) (*PollSessionResponse, error)
PollSession returns the current status of a session
func (*Client) ProcessCallback ¶
func (c *Client) ProcessCallback(ctx context.Context, req *CallbackRequest) (*CallbackResponse, error)
ProcessCallback processes a callback request
func (*Client) ProcessDirectPost ¶
func (c *Client) ProcessDirectPost(ctx context.Context, req *DirectPostRequest) (*DirectPostResponse, error)
ProcessDirectPost processes a direct_post response from a wallet
func (*Client) RegisterClient ¶
func (c *Client) RegisterClient(ctx context.Context, req *ClientRegistrationRequest) (*ClientRegistrationResponse, error)
RegisterClient handles dynamic client registration (RFC 7591)
func (*Client) ScopeQueryIDs ¶ added in v0.7.21
func (c *Client) ScopeQueryIDs(ctx context.Context, dcql *openid4vp.DCQL, scopes []string) map[string]string
ScopeQueryIDs pairs each requested scope with the id of the DCQL credential query that stands for it, for the pairs where the two differ. It fills cache.AuthorizationContext.ScopeQueryIDs.
Pairing is by constraint, not by name: a template names its queries whatever its author chose ("eudi_pid" for scope "pid"), so a query stands for a scope when it carries that scope's doctype or its vct. Queries built from credential_metadata are keyed by the scope already.
W3C scopes are skipped: credential_metadata carries no type list for them yet, so a template query cannot be recognised as theirs. They keep the scope-keyed lookup.
func (*Client) SetSigningKeyForTesting ¶
SetSigningKeyForTesting sets the OIDC signing key for testing purposes. This is needed because the production code has a TODO for loading the key from config. Returns error if the key type is unsupported.
func (*Client) Token ¶
func (c *Client) Token(ctx context.Context, req *TokenRequest) (*TokenResponse, error)
Token handles the OIDC token request
func (*Client) UIInteraction ¶
func (c *Client) UIInteraction(ctx context.Context, req *UIInteractionRequest) (*UIInteractionReply, error)
UIInteraction handles front-end interactions, replying with an Authorization Request that contains a Request URI and DCQL query, the latter for UI to show.
func (*Client) UIMetadata ¶
func (c *Client) UIMetadata(ctx context.Context) (*UIMetadataReply, error)
func (*Client) UIResume ¶ added in v0.7.21
UIResume reports whether the wallet interaction named by sessionID is still pending, already complete, expired, or unknown, and for pending sessions returns the QR state so a reloaded UI can rebuild its page. A fresh DC API request_uri is minted on each pending call for the same reason tryReuseInFlightSession does: a reload cannot resume a native navigator.credentials.get call, so the existing one is left to time out.
func (*Client) UpdateClient ¶
func (c *Client) UpdateClient(ctx context.Context, req *UpdateClientRequest) (*ClientRegistrationResponse, error)
UpdateClient updates client configuration (RFC 7592)
func (*Client) UpdateSessionPreference ¶
func (c *Client) UpdateSessionPreference(ctx context.Context, req *UpdateSessionPreferenceRequest) (*UpdateSessionPreferenceResponse, error)
UpdateSessionPreference updates the session's credential display preference
func (*Client) VerificationCallback ¶
func (c *Client) VerificationCallback(ctx context.Context, req *VerificationCallbackRequest) (*VerificationCallbackResponse, error)
func (*Client) VerificationDirectPost ¶
func (c *Client) VerificationDirectPost(ctx context.Context, req *VerificationDirectPostRequest) (*VerificationDirectPostResponse, error)
func (*Client) VerificationRequestObject ¶
type ClientInformationResponse ¶
type ClientInformationResponse struct {
ClientRegistrationResponse
}
ClientInformationResponse represents RFC 7592 client information response (GET)
type ClientRegistrationRequest ¶
type ClientRegistrationRequest struct {
// REQUIRED or OPTIONAL OAuth 2.0 parameters
RedirectURIs []string `json:"redirect_uris,omitempty" validate:"required,min=1,dive,redirect_uri"`
TokenEndpointAuthMethod string `` /* 144-byte string literal not displayed */
GrantTypes []string `` /* 128-byte string literal not displayed */
ResponseTypes []string `json:"response_types,omitempty" default:"[\"code\"]" validate:"omitempty,dive,oneof=code"`
ClientName string `json:"client_name,omitempty"`
ClientURI string `json:"client_uri,omitempty" validate:"omitempty,httpsurl"`
LogoURI string `json:"logo_uri,omitempty" validate:"omitempty,httpsurl"`
Scope string `json:"scope,omitempty" default:"openid"`
Contacts []string `json:"contacts,omitempty"`
TosURI string `json:"tos_uri,omitempty" validate:"omitempty,httpsurl"`
PolicyURI string `json:"policy_uri,omitempty" validate:"omitempty,httpsurl"`
JWKSUri string `json:"jwks_uri,omitempty" validate:"omitempty,excluded_with=JWKS"`
JWKS any `json:"jwks,omitempty"`
SoftwareID string `json:"software_id,omitempty"`
SoftwareVersion string `json:"software_version,omitempty"`
// OpenID Connect specific
ApplicationType string `json:"application_type,omitempty" default:"web" validate:"omitempty,oneof=web native"`
SectorIdentifierURI string `json:"sector_identifier_uri,omitempty"`
SubjectType string `json:"subject_type,omitempty" default:"public" validate:"omitempty,oneof=public pairwise"`
IDTokenSignedRespAlg string `json:"id_token_signed_response_alg,omitempty" default:"RS256"`
IDTokenEncryptedRespAlg string `json:"id_token_encrypted_response_alg,omitempty"`
IDTokenEncryptedRespEnc string `json:"id_token_encrypted_response_enc,omitempty"`
UserinfoSignedRespAlg string `json:"userinfo_signed_response_alg,omitempty"`
RequestObjectSigningAlg string `json:"request_object_signing_alg,omitempty"`
DefaultMaxAge int `json:"default_max_age,omitempty"`
RequireAuthTime bool `json:"require_auth_time,omitempty"`
DefaultACRValues []string `json:"default_acr_values,omitempty"`
InitiateLoginURI string `json:"initiate_login_uri,omitempty"`
RequestURIs []string `json:"request_uris,omitempty"`
// PKCE (RFC 7636)
CodeChallengeMethod string `json:"code_challenge_method,omitempty" default:"S256" validate:"omitempty,oneof=S256 plain"`
}
ClientRegistrationRequest represents RFC 7591 client registration request
type ClientRegistrationResponse ¶
type ClientRegistrationResponse 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"` // 0 = never expires, REQUIRED per RFC 7591
RedirectURIs []string `json:"redirect_uris,omitempty"`
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`
GrantTypes []string `json:"grant_types,omitempty"`
ResponseTypes []string `json:"response_types,omitempty"`
ClientName string `json:"client_name,omitempty"`
ClientURI string `json:"client_uri,omitempty"`
LogoURI string `json:"logo_uri,omitempty"`
Scope string `json:"scope,omitempty"`
Contacts []string `json:"contacts,omitempty"`
TosURI string `json:"tos_uri,omitempty"`
PolicyURI string `json:"policy_uri,omitempty"`
JWKSUri string `json:"jwks_uri,omitempty"`
JWKS any `json:"jwks,omitempty"`
SoftwareID string `json:"software_id,omitempty"`
SoftwareVersion string `json:"software_version,omitempty"`
RegistrationAccessToken string `json:"registration_access_token,omitempty"`
RegistrationClientURI string `json:"registration_client_uri,omitempty"`
// OpenID Connect specific
ApplicationType string `json:"application_type,omitempty"`
SectorIdentifierURI string `json:"sector_identifier_uri,omitempty"`
SubjectType string `json:"subject_type,omitempty"`
IDTokenSignedRespAlg string `json:"id_token_signed_response_alg,omitempty"`
DefaultMaxAge int `json:"default_max_age,omitempty"`
RequireAuthTime bool `json:"require_auth_time,omitempty"`
DefaultACRValues []string `json:"default_acr_values,omitempty"`
InitiateLoginURI string `json:"initiate_login_uri,omitempty"`
RequestURIs []string `json:"request_uris,omitempty"`
// PKCE
CodeChallengeMethod string `json:"code_challenge_method,omitempty"`
}
ClientRegistrationResponse represents RFC 7591 client registration response
type ConfirmCredentialDisplayRequest ¶
type ConfirmCredentialDisplayRequest struct {
SessionID string `json:"-" uri:"session_id" validate:"required,max=128,printascii"`
Confirmed bool `json:"confirmed"`
}
ConfirmCredentialDisplayRequest represents a confirmation from the credential display page
type ConfirmCredentialDisplayResponse ¶
type ConfirmCredentialDisplayResponse struct {
RedirectURI string `json:"redirect_uri"`
}
ConfirmCredentialDisplayResponse contains the redirect URI
type CredentialFormat ¶
type CredentialFormat string
CredentialFormat represents the format of a verifiable credential.
const ( // FormatSDJWT represents SD-JWT Verifiable Credentials (vc+sd-jwt, dc+sd-jwt) FormatSDJWT CredentialFormat = "vc+sd-jwt" // FormatMDoc represents ISO/IEC 18013-5 mDOC credentials (mso_mdoc) FormatMDoc CredentialFormat = "mso_mdoc" // FormatMDocZK represents a zero-knowledge-proof presentation of an // ISO/IEC 18013-5 mDOC credential (mso_mdoc_zk) - see pkg/mdoc/zk*.go. FormatMDocZK CredentialFormat = "mso_mdoc_zk" // FormatUnknown represents an unrecognized format FormatUnknown CredentialFormat = "unknown" )
type DeleteClientRequest ¶
type DeleteClientRequest struct {
ClientID string `json:"-" uri:"client_id" validate:"required,max=128,printascii"`
RegistrationAccessToken string `json:"-" header:"Authorization" validate:"required"`
}
DeleteClientRequest represents a request to delete a client
type DirectPostRequest ¶
type DirectPostRequest struct {
// Not binding:"required": with response_mode=direct_post.jwt the wallet
// posts only `response`, and state travels inside that JWE (OpenID4VP 1.0
// 8.3.1). Requiring it here rejected a conformant wallet before anything
// could be decrypted. ProcessDirectPost requires one of state/response.
State string `json:"state" form:"state" validate:"omitempty,max=256,printascii"`
VPToken string `json:"vp_token" form:"vp_token" validate:"omitempty"` // For standard direct_post (JWT, can be very large)
PresentationSubmission string `json:"presentation_submission" form:"presentation_submission" validate:"omitempty"` // For standard direct_post (JSON, can be large)
Response string `json:"response" form:"response" validate:"omitempty"` // For DC API encrypted JWT response (can be very large)
}
DirectPostRequest represents a direct_post callback from a wallet
type DirectPostResponse ¶
type DirectPostResponse struct {
RedirectURI string
}
DirectPostResponse contains the response to a direct_post request
type DiscoveryMetadata ¶
type DiscoveryMetadata 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"`
RegistrationEndpoint string `json:"registration_endpoint,omitempty"` // RFC 7591
ResponseTypesSupported []string `json:"response_types_supported"`
SubjectTypesSupported []string `json:"subject_types_supported"`
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
ScopesSupported []string `json:"scopes_supported"`
ClaimsSupported []string `json:"claims_supported"`
GrantTypesSupported []string `json:"grant_types_supported"`
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
}
DiscoveryMetadata represents OpenID Provider metadata
type GetClientInformationRequest ¶
type GetClientInformationRequest struct {
ClientID string `json:"-" uri:"client_id" validate:"required,max=128,printascii"`
RegistrationAccessToken string `json:"-" header:"Authorization" validate:"required"`
}
GetClientInformationRequest represents a request to get client information
type GetCredentialDisplayDataRequest ¶
type GetCredentialDisplayDataRequest struct {
SessionID string `json:"-" uri:"session_id" validate:"required,max=128,printascii"`
}
GetCredentialDisplayDataRequest represents a request to get display data
type GetCredentialDisplayDataResponse ¶
type GetCredentialDisplayDataResponse struct {
SessionID string `json:"session_id"`
VPToken string `json:"vp_token"`
Claims map[string]any `json:"claims"`
ClientID string `json:"client_id"`
RedirectURI string `json:"redirect_uri"`
State string `json:"state"`
ShowRawCredential bool `json:"show_raw_credential"`
ShowClaims bool `json:"show_claims"`
PrimaryColor string `json:"primary_color"`
SecondaryColor string `json:"secondary_color"`
CustomCSS string `json:"custom_css"`
}
GetCredentialDisplayDataResponse contains data for the credential display page
type GetQRCodeRequest ¶
type GetQRCodeRequest struct {
SessionID string `json:"-" uri:"session_id" validate:"required,max=128,printascii"`
WalletName string `json:"-" form:"wallet" validate:"omitempty,max=128"` // Optional: generate QR for a specific web wallet (display names may contain non-ASCII)
}
GetQRCodeRequest represents a request for a QR code image
type GetQRCodeResponse ¶
type GetQRCodeResponse struct {
ImageData []byte
}
GetQRCodeResponse contains the QR code image data
type GetRequestObjectRequest ¶
type GetRequestObjectRequest struct {
SessionID string `json:"-" uri:"session_id" validate:"required,max=128,printascii"`
}
GetRequestObjectRequest represents a request to get an OpenID4VP request object
type GetRequestObjectResponse ¶
type GetRequestObjectResponse struct {
RequestObject string
}
GetRequestObjectResponse contains the signed JWT request object
type OAuthError ¶
type OAuthError struct {
// Error code as defined in OAuth 2.0 spec
ErrorCode string `json:"error"`
// Human-readable description
ErrorDescription string `json:"error_description,omitempty"`
// URI for more information
ErrorURI string `json:"error_uri,omitempty"`
// HTTP status code to return
HTTPStatus int `json:"-"`
// Original error for internal logging
Cause error `json:"-"`
}
OAuthError represents an OAuth 2.0/OIDC error response Following RFC 6749 Section 5.2 (Error Response) and RFC 6750 Section 3.1 (Error Codes) and OpenID Connect Core Section 3.1.2.6 (Authentication Error Response)
func AsOAuthError ¶
func AsOAuthError(err error) *OAuthError
AsOAuthError converts an error to OAuthError, or wraps it if it's not already one
func NewInvalidClientError ¶
func NewInvalidClientError(description string) *OAuthError
NewInvalidClientError creates an invalid_client error with custom description
func NewInvalidGrantError ¶
func NewInvalidGrantError(description string) *OAuthError
NewInvalidGrantError creates an invalid_grant error with custom description
func NewInvalidRequestError ¶
func NewInvalidRequestError(description string) *OAuthError
NewInvalidRequestError creates an invalid_request error with custom description
func NewInvalidScopeError ¶
func NewInvalidScopeError(description string) *OAuthError
NewInvalidScopeError creates an invalid_scope error with custom description
func NewOAuthError ¶
func NewOAuthError(code string, description string, httpStatus int) *OAuthError
NewOAuthError creates a new OAuth error with a custom description
func NewServerError ¶
func NewServerError(description string, cause error) *OAuthError
NewServerError creates a server_error with optional cause
func (*OAuthError) Unwrap ¶
func (e *OAuthError) Unwrap() error
Unwrap returns the underlying error for errors.Is and errors.As
type PollSessionRequest ¶
type PollSessionRequest struct {
SessionID string `json:"-" uri:"session_id" validate:"required,max=128,printascii"`
}
PollSessionRequest represents a polling request for session status
type PollSessionResponse ¶
type PollSessionResponse struct {
Status string `json:"status"`
RedirectURI string `json:"redirect_uri,omitempty"`
}
PollSessionResponse contains the session status
type SessionPollResponse ¶
type SessionPollResponse struct {
SessionID string `json:"session_id"`
Status string `json:"status"`
AuthorizationCode string `json:"authorization_code,omitempty"`
RedirectURI string `json:"redirect_uri,omitempty"`
State string `json:"state,omitempty"`
}
SessionPollResponse represents the response from polling a session
type TokenRequest ¶
type TokenRequest struct {
GrantType string `form:"grant_type" binding:"required" validate:"required,max=128,printascii"`
Code string `form:"code" validate:"omitempty,max=256,printascii"`
RedirectURI string `form:"redirect_uri" validate:"omitempty,max=2048,printascii"`
ClientID string `form:"client_id" validate:"omitempty,max=128,printascii"`
ClientSecret string `form:"client_secret" validate:"omitempty,max=256,printascii"`
CodeVerifier string `form:"code_verifier" validate:"omitempty,max=128,printascii"`
RefreshToken string `form:"refresh_token" validate:"omitempty,max=256,printascii"`
}
TokenRequest represents an OIDC token request
type TokenResponse ¶
type TokenResponse struct {
AccessToken string `json:"access_token,omitempty"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
IDToken string `json:"id_token"`
Scope string `json:"scope,omitempty"`
}
TokenResponse represents an OIDC token response
type UICredentialInfo ¶
type UICredentialInfo struct {
Format string `json:"format"`
// VCT is the credential's own type identifier - the value
// BuildCredentialWithSigner embeds as the credential's "vct" claim. Kept
// as the single display identifier for the UI's credential picker.
VCT string `json:"vct"`
// VCTValues is the credential's canonical vct as a single-element list,
// for DCQL meta.vct_values. ResolveVCTUrls yields exactly one identifier
// per VCTM -- the file's own vct when present (URN or foreign URL), or
// the apigw hosting URL when a local file left vct empty -- so the list
// carries at most one value.
// omitempty: mso_mdoc scopes get no list (they're identified by doctype,
// not vct), so this drops the field entirely for them rather than
// emitting a meaningless "vct_values": null.
VCTValues []string `json:"vct_values,omitempty"`
Attributes map[string]map[string][]*string `json:"attributes"`
}
UICredentialInfo is a sanitized view of a credential for the UI.
type UIInteractionReply ¶
type UIInteractionReply struct {
// SessionID identifies the authorization context this reply belongs to.
// Returned so the browser can address later POSTs (e.g. session-preference)
// to the exact request it was created for, rather than relying on the
// shared per-origin cookie session that any other tab can overwrite.
SessionID string `json:"session_id"`
// AuthorizationRequest is the request reached through request_uri: the QR
// code, the same-device link, and the polyfill's redirect fallback. Its
// response_mode is direct_post.jwt, because a wallet arriving this way
// has no browser DC API call to answer inside.
AuthorizationRequest string `json:"authorization_request"`
QRCode string `json:"qr_code"`
// DCAPIAuthorizationRequest is the request for navigator.credentials.get,
// carrying response_mode dc_api.jwt. Empty when the Digital Credentials
// API is disabled.
//
// Two requests rather than one, because response_mode has to follow the
// delivery channel: dc_api modes are defined only for a request handed to
// the browser DC API, where the response returns inside that call and the
// transcript binds to the calling origin. Serving one request object to
// both channels - which is what this flow did - meant every wallet that
// scanned the QR or followed the link got a mode it could not honour, and
// only found out after the user had selected credentials and signed
// (SUNET/vc#652).
DCAPIAuthorizationRequest string `json:"dc_api_authorization_request,omitempty"`
}
type UIInteractionRequest ¶
type UIInteractionRequest struct {
DCQLQuery *openid4vp.DCQL `json:"dcql_query" validate:"required"`
Validations map[string][]openid4vp.ClaimValidation `json:"validations,omitempty" validate:"omitempty,dive,dive"`
// SessionID is a reuse hint sourced ONLY from the request body (which
// mirrors the tab-scoped sessionStorage value). The HTTP layer
// deliberately does NOT populate it from the shared gin cookie
// session, because that cookie is overwritten by any sibling tab and
// would otherwise let a fresh tab inherit another tab's in-flight
// authorization context. When this id names a still-valid,
// still-unclaimed context with the same DCQL / validations, the
// response returns that context's existing request_uri/QR so a
// reload mid-flow does not orphan the wallet's outstanding scan.
// Otherwise a fresh session id is minted and returned in the reply.
SessionID string `json:"session_id,omitempty" validate:"omitempty,max=128,printascii"`
}
type UIMetadataReply ¶
type UIMetadataReply struct {
Credentials map[string]*UICredentialInfo `json:"credentials"`
SupportedWallets map[string]string `json:"supported_wallets"`
Presets map[string]*UIPreset `json:"presets,omitempty"`
// PresetCategoryOrder lists every distinct non-empty Category found
// across Presets, in display order - lowest-Order preset within the
// category first, ties broken alphabetically by category name. JSON map
// keys always serialize alphabetically (encoding/json), so this is the
// only way an operator's intended category ordering (via
// PresetDefinition.Order) survives onto the wire; the UI groups/orders
// preset buttons by this list rather than alphabetizing category names
// itself. Excludes the empty/uncategorized group, which the UI always
// renders last under its own generic heading.
PresetCategoryOrder []string `json:"preset_category_order,omitempty"`
// DCAPIEnabled mirrors verifier.digital_credentials.enable, so the UI only
// attempts the native W3C Digital Credentials API when an operator has
// opted in, rather than always trying it regardless of server config.
DCAPIEnabled bool `json:"dc_api_enabled"`
// DCAPIAutoAttempt mirrors verifier.digital_credentials.auto_attempt -
// see that field's own doc comment for why this is separate from
// DCAPIEnabled (an OS-level DC API matcher rejection can pre-empt any
// application code, with no clean fallback to catch).
DCAPIAutoAttempt bool `json:"dc_api_auto_attempt"`
}
type UIPreset ¶ added in v0.6.0
type UIPreset struct {
Label string `json:"label"`
// Category groups this preset with every other preset sharing the same
// string, for progressive/grouped rendering - empty for an uncategorized
// preset. See model.PresetDefinition.Category.
Category string `json:"category,omitempty"`
// Order is this preset's position within its Category (ascending; ties,
// including the default 0, broken alphabetically by Label client-side).
Order int `json:"order"`
// Featured presets are shown immediately rather than behind the
// progressive-disclosure grouping. See model.PresetDefinition.Featured.
Featured bool `json:"featured"`
Credentials []UIPresetCredential `json:"credentials"`
}
UIPreset is a verification preset served to the UI.
type UIPresetClaim ¶ added in v0.6.0
type UIPresetClaim struct {
Path []*string `json:"path"`
}
UIPresetClaim is a claim path within a preset credential.
type UIPresetCredential ¶ added in v0.6.0
type UIPresetCredential struct {
ID string `json:"id"`
Format string `json:"format"`
Meta UIPresetMeta `json:"meta"`
Claims []UIPresetClaim `json:"claims,omitempty"`
Validations []openid4vp.ClaimValidation `json:"validations,omitempty"`
}
UIPresetCredential is a credential query within a preset.
type UIPresetMeta ¶ added in v0.6.0
type UIPresetMeta struct {
VCTValues []string `json:"vct_values,omitempty"`
// DoctypeValue is set for mdoc/ZK-mdoc scopes (openid4vp.MetaQuery's
// mdoc-format field) - mirrors UICredentialInfo.VCT's mdoc branch.
DoctypeValue string `json:"doctype_value,omitempty"`
// ZKSystemType is set when the preset's VerificationPresetScope
// overrides it - see that type's own doc comment.
ZKSystemType []openid4vp.ZKSystemTypeSpec `json:"zk_system_type,omitempty"`
}
UIPresetMeta holds credential metadata for the preset.
Which field applies depends on the credential's format (OpenID4VP 1.0 6.4.1): vct_values for sd-jwt credentials, doctype_value for mso_mdoc. They are mutually exclusive, hence omitempty on both - sending an empty vct_values alongside a doctype, or vice versa, is a malformed query.
type UIResumeReply ¶ added in v0.7.21
type UIResumeReply struct {
Status UIResumeStatus `json:"status"`
// Pending-only fields: same shape as UIInteractionReply so the client
// can reuse its existing render path.
SessionID string `json:"session_id,omitempty"`
AuthorizationRequest string `json:"authorization_request,omitempty"`
QRCode string `json:"qr_code,omitempty"`
DCAPIAuthorizationRequest string `json:"dc_api_authorization_request,omitempty"`
DCQLQuery *openid4vp.DCQL `json:"dcql_query,omitempty"`
Validations map[string][]openid4vp.ClaimValidation `json:"validations,omitempty"`
// Complete-only field.
ResponseCode string `json:"response_code,omitempty"`
}
UIResumeReply carries one of three alternatives selected by Status: pending (QR state), complete (response_code), or unknown/expired (no payload). JSON omitempty leaves irrelevant fields off the wire so clients can discriminate by field presence as well as Status.
type UIResumeStatus ¶ added in v0.7.21
type UIResumeStatus string
UIResumeStatus names the possible outcomes of a /ui/resume call.
const ( // UIResumeUnknown means sessionID names no live authorization context. UIResumeUnknown UIResumeStatus = "unknown" // UIResumePending means the wallet has not answered yet; the reply // carries the original QR code / authorization request so a reloaded // verifier UI can rebuild its QR screen without starting over. UIResumePending UIResumeStatus = "pending" // UIResumeComplete means the wallet has already answered; the reply // carries the response_code the SSE event would have delivered. UIResumeComplete UIResumeStatus = "complete" // UIResumeExpired means the auth context exists but its request object // has been evicted, so the QR / request_uri is no longer resolvable. UIResumeExpired UIResumeStatus = "expired" )
type UpdateClientRequest ¶
type UpdateClientRequest struct {
ClientID string `json:"-" uri:"client_id" validate:"required,max=128,printascii"`
RegistrationAccessToken string `json:"-" header:"Authorization" validate:"required"`
ClientRegistrationRequest
}
UpdateClientRequest represents a request to update client configuration
type UpdateSessionPreferenceRequest ¶
type UpdateSessionPreferenceRequest struct {
// SessionID is the authorization context this call targets. Callers
// supply it in the JSON body: the OIDC-OP flow has it from template
// render time; the standalone verifier UI gets it from the reply of
// /ui/interaction (also persisted in sessionStorage so it survives a
// reload). The HTTP layer falls back to the gin cookie session only
// when the body is empty - a legacy / storage-blocked compatibility
// path, not the normal channel.
SessionID string `json:"session_id" validate:"omitempty,max=128,printascii"`
ShowCredentialDetails bool `json:"show_credential_details"`
// WalletFollowsRedirect is optional. When non-nil it records that the
// user is continuing in a same-device web wallet that should follow
// redirect_uri from direct_post. Omitted on credential-display saves
// so those POSTs do not clear a previously set flag.
WalletFollowsRedirect *bool `json:"wallet_follows_redirect"`
}
UpdateSessionPreferenceRequest represents a request to update session display preference
type UpdateSessionPreferenceResponse ¶
type UpdateSessionPreferenceResponse struct {
Success bool `json:"success"`
}
UpdateSessionPreferenceResponse contains the response
type UserInfoRequest ¶
type UserInfoRequest struct {
Authorization string `json:"-" header:"Authorization" validate:"required,max=8192,printascii"`
AccessToken string `json:"-"` // Parsed from Authorization header
}
UserInfoRequest represents a UserInfo endpoint request
type VerificationCallbackRequest ¶
type VerificationCallbackRequest struct {
ResponseCode string `form:"response_code" uri:"response_code"`
}
type VerificationCallbackResponse ¶
type VerificationCallbackResponse struct {
CredentialData []sdjwtvc.CredentialCache `json:"credential_data"`
}
type VerificationDirectPostRequest ¶
type VerificationDirectPostRequest struct {
Response string `json:"response" form:"response"`
// DCAPI marks a response returned inside a navigator.credentials.get
// call and forwarded here by the verifier's own page, rather than POSTed
// by a wallet reached through request_uri. The two bind their mdoc
// session transcripts to different handovers, so this selects which one
// the verifier recomputes - see mdoc.BuildOID4VPDCAPISessionTranscript.
//
// Client-supplied and not trusted as an assertion: the origin bound into
// the transcript comes from configuration, never from the caller, so a
// caller that sets this wrongly only fails its own verification. It
// cannot choose what the presentation is checked against.
DCAPI bool `json:"dc_api" form:"dc_api"`
SessionID string `json:"-"` // Set by HTTP layer if same-device flow
}
func (*VerificationDirectPostRequest) GetKID ¶
func (v *VerificationDirectPostRequest) GetKID() (string, error)
type VerificationDirectPostResponse ¶
type VerificationDirectPostResponse struct {
// RedirectURI is present for same-device flows so the wallet can send
// the browser back to the verifier. Cross-device flows omit it: the
// still-open verifier tab is nudged over SSE instead.
RedirectURI string `json:"redirect_uri,omitempty"`
}
type VerificationRequestObjectRequest ¶
type VerificationRequestObjectRequest struct {
ID string `json:"-" form:"id" uri:"id" validate:"required,max=128,printascii"`
}
type WalletLink ¶
type WalletLink struct {
Name string `json:"name"`
URL string `json:"url"`
QRCodeImageURL string `json:"qr_code_image_url"` // QR code image URL for cross-device flow
}
WalletLink represents a clickable link to a known web wallet