apiv1

package
v0.7.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2026 License: BSD-2-Clause Imports: 49 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ErrCodeInvalidRequest          = "invalid_request"
	ErrCodeInvalidClient           = "invalid_client"
	ErrCodeInvalidGrant            = "invalid_grant"
	ErrCodeUnauthorizedClient      = "unauthorized_client"
	ErrCodeUnsupportedGrantType    = "unsupported_grant_type"
	ErrCodeInvalidScope            = "invalid_scope"
	ErrCodeAccessDenied            = "access_denied"
	ErrCodeUnsupportedResponseType = "unsupported_response_type"
	ErrCodeServerError             = "server_error"
	ErrCodeTemporarilyUnavailable  = "temporarily_unavailable"

	// 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

View Source
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,
	}

	ErrUnauthorizedClient = &OAuthError{
		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,
	}

	ErrTemporarilyUnavailable = &OAuthError{
		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

func GetHTTPStatus(err error) int

GetHTTPStatus returns the HTTP status code for an error Returns the OAuthError's HTTPStatus if it's an OAuthError, otherwise 500

func IsOAuthError

func IsOAuthError(err error) bool

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) ConfirmCredentialDisplay

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

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) GetJWKS

func (c *Client) GetJWKS(ctx context.Context) (*jose.JWKS, error)

GetJWKS returns the JSON Web Key Set

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

func (c *Client) GetPollStatus(ctx context.Context, sessionID string) (*SessionPollResponse, error)

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

Health returns the readiness of the verifier service.

func (*Client) OAuthMetadata

func (c *Client) OAuthMetadata(ctx context.Context) (*oauth2.AuthorizationServerMetadata, error)

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

RegisterClient handles dynamic client registration (RFC 7591)

func (*Client) SetSigningKeyForTesting

func (c *Client) SetSigningKeyForTesting(key any) error

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) UpdateClient

UpdateClient updates client configuration (RFC 7592)

func (*Client) UpdateSessionPreference

UpdateSessionPreference updates the session's credential display preference

func (*Client) VerificationCallback

func (*Client) VerificationDirectPost

func (*Client) VerificationRequestObject

func (c *Client) VerificationRequestObject(ctx context.Context, req *VerificationRequestObjectRequest) (string, error)

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 {
	State                  string `json:"state" form:"state" binding:"required" validate:"required,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) Error

func (e *OAuthError) Error() string

Error implements the error interface

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 every identifier a wallet might legitimately match this
	// credential type by, for use as DCQL meta.vct_values.
	//
	// Both forms have to be offered, because deployed wallets disagree about
	// which one identifies a credential, and each behaviour is live-verified
	// in this repo:
	//
	//   - The EUDI reference wallet (multipaz) matches the ISSUER METADATA's
	//     declared vct - our published type-metadata URL. Offer.kt sets
	//     SdJwtVcFormat(vct = configuration.type) and DcqlRequestProcessor
	//     filters on that tag before ever parsing the credential body. See
	//     the finding-18 note in internal/apigw/apiv1/handlers_verifier.go.
	//
	//   - Other wallets (e.g. wwWallet/wallet-frontend) match the credential's
	//     own embedded "vct" claim, i.e. VCTM.VCT. See the finding-16 note on
	//     VCTIdentifiersForScopes in pkg/model/config.go.
	//
	// vct_values is an acceptable-value list by design (OpenID4VP DCQL), so
	// emitting both satisfies either wallet instead of picking a winner and
	// silently breaking the other.
	// 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. The UI's schema tolerates
	// either form - it declares vct_values as nullish and falls back to
	// [vct] for both absent and null - so this is about not sending noise
	// for mdoc credentials, not about satisfying a parsing constraint.
	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 {
	// 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 from http server endpoint
	SessionID string `json:"-"`
}

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 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             string `json:"session_id" binding:"required" validate:"required,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 UserInfoResponse

type UserInfoResponse map[string]any

UserInfoResponse contains user claims

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

type VerificationDirectPostResponse

type VerificationDirectPostResponse struct {
	// RedirectURI is optional - only included for same-device flows
	// For cross-device flows, the browser is notified via 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 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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL