Skip to content

Commit

Permalink
feat: Token endpoint
Browse files Browse the repository at this point in the history
Signed-off-by: Mykhailo Sizov <[email protected]>
  • Loading branch information
mishasizov-SK committed Mar 9, 2024
1 parent 536101c commit d5d00fb
Show file tree
Hide file tree
Showing 11 changed files with 355 additions and 305 deletions.
352 changes: 178 additions & 174 deletions api/spec/openapi.gen.go

Large diffs are not rendered by default.

51 changes: 35 additions & 16 deletions component/wallet-cli/pkg/oidc4vci/oidc4vci_flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ type Flow struct {
credentialType string
oidcCredentialFormat vcsverifiable.OIDCFormat
clientID string
credentialConfigurationID string
scopes []string
redirectURI string
enableDiscoverableClientID bool
Expand Down Expand Up @@ -206,6 +207,7 @@ func NewFlow(p provider, opts ...Opt) (*Flow, error) {
credentialType: o.credentialType,
oidcCredentialFormat: o.oidcCredentialFormat,
clientID: o.clientID,
credentialConfigurationID: o.credentialConfigurationID,
scopes: o.scopes,
redirectURI: o.redirectURI,
enableDiscoverableClientID: o.enableDiscoverableClientID,
Expand Down Expand Up @@ -743,7 +745,7 @@ func (f *Flow) receiveVC(

b, err := json.Marshal(CredentialRequest{
Format: oidcCredentialFormat,
Types: []string{"VerifiableCredential", f.credentialType},
Types: []string{"VerifiableCredential", f.credentialType}, //todo: remove. Is not a part of spec
Proof: *proof,
})
if err != nil {
Expand Down Expand Up @@ -849,19 +851,19 @@ func (f *Flow) getCredentialRequestOIDCCredentialFormat(
}

// For cases, when oidcCredentialFormat is not supplied:
if f.credentialConfigurationID != "" {
// CredentialConfigurationID option available so take format from well-known configuration.
// Spec: https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html#section-5.1.1
format := wellKnown.CredentialConfigurationsSupported.AdditionalProperties[f.credentialConfigurationID].Format
if format == "" {
return "", fmt.Errorf(
"unable to obtain OIDC credential format from issuer well-known configuration. "+
"Check if `issuer.credentialMetadata.credential_configurations_supported` contains key `%s` "+
"with nested `format` field", f.credentialConfigurationID)
}

return vcsverifiable.OIDCFormat(format), nil
}
//if f.credentialConfigurationID != "" {
// // CredentialConfigurationID option available so take format from well-known configuration.
// // Spec: https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html#section-5.1.1
// format := wellKnown.CredentialConfigurationsSupported.AdditionalProperties[f.credentialConfigurationID].Format
// if format == "" {
// return "", fmt.Errorf(
// "unable to obtain OIDC credential format from issuer well-known configuration. "+
// "Check if `issuer.credentialMetadata.credential_configurations_supported` contains key `%s` "+
// "with nested `format` field", f.credentialConfigurationID)
// }
//
// return vcsverifiable.OIDCFormat(format), nil
//}

if len(f.scopes) > 0 {
// scopes option available so take format from well-known configuration.
Expand All @@ -882,6 +884,7 @@ func (f *Flow) getCredentialRequestOIDCCredentialFormat(

return "", errors.New("obtain OIDC credential format")
}

func (f *Flow) handleIssuanceAck(
wellKnown *issuerv1.WellKnownOpenIDIssuerConfiguration,
credResponse *CredentialResponse,
Expand Down Expand Up @@ -959,7 +962,16 @@ func (f *Flow) getAuthorizationDetailsRequestBody(
res := make([]common.AuthorizationDetails, 0)

switch {
case credentialOfferResponse != nil: // Priority 1. Based on credentialConfigurationID.
case f.credentialConfigurationID != "": // Priority 1. Based on credentialConfigurationID.
res = append(res, common.AuthorizationDetails{
CredentialConfigurationId: &f.credentialConfigurationID,
CredentialDefinition: nil,
Format: nil,
Locations: nil, // Not supported for now.
Type: "openid_credential",
})
// For FlowTypeWalletInitiated credentialOfferResponse might be empty.
case credentialOfferResponse != nil: // Priority 2. Based on credentialOfferResponse request all credentials from credential offer.
for _, credentialConfigurationID := range credentialOfferResponse.CredentialConfigurationIDs {
res = append(res, common.AuthorizationDetails{
CredentialConfigurationId: &credentialConfigurationID,
Expand All @@ -969,7 +981,7 @@ func (f *Flow) getAuthorizationDetailsRequestBody(
Type: "openid_credential",
})
}
case oidcCredentialFormat != "": // Priority 2. Based on credentialFormat.
case oidcCredentialFormat != "": // Priority 3. Based on credentialFormat.
res = append(res, common.AuthorizationDetails{
CredentialConfigurationId: nil,
CredentialDefinition: &common.CredentialDefinition{
Expand Down Expand Up @@ -1042,6 +1054,7 @@ type options struct {
credentialType string
oidcCredentialFormat vcsverifiable.OIDCFormat
clientID string
credentialConfigurationID string
scopes []string
redirectURI string
enableDiscoverableClientID bool
Expand Down Expand Up @@ -1137,3 +1150,9 @@ func WithWalletDIDIndex(idx int) Opt {
opts.walletDIDIndex = idx
}
}

func WithCredentialConfigurationID(credentialConfigurationID string) Opt {
return func(opts *options) {
opts.credentialConfigurationID = credentialConfigurationID
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (w *Wrapper) InitiateIssuance(
return resp, nil
}

func (w *Wrapper) PushAuthorizationDetails(ctx context.Context, opState string, ad *oidc4ci.AuthorizationDetails) error {
func (w *Wrapper) PushAuthorizationDetails(ctx context.Context, opState string, ad []*oidc4ci.AuthorizationDetails) error {
return w.svc.PushAuthorizationDetails(ctx, opState, ad)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestWrapper_PushAuthorizationDetails(t *testing.T) {

w := Wrap(svc, trace.NewNoopTracerProvider().Tracer(""))

err := w.PushAuthorizationDetails(context.Background(), "opState", &oidc4ci.AuthorizationDetails{})
err := w.PushAuthorizationDetails(context.Background(), "opState", []*oidc4ci.AuthorizationDetails{{}})
require.NoError(t, err)
}

Expand Down
1 change: 1 addition & 0 deletions pkg/restapi/resterr/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const (
OIDCClientAuthenticationFailed ErrorCode = "oidc-client-authentication-failed"
InvalidOrMissingProofOIDCErr ErrorCode = "invalid_or_missing_proof"
OIDCInvalidEncryptionParameters ErrorCode = "oidc-invalid-encryption-parameters"
OIDCInvalidCredentialRequest ErrorCode = "invalid_credential_request" //todo: add usage of this error code

ProfileNotFound ErrorCode = "profile-not-found"
ProfileInactive ErrorCode = "profile-inactive"
Expand Down
28 changes: 15 additions & 13 deletions pkg/restapi/v1/issuer/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,14 +452,16 @@ func (c *Controller) initiateIssuance(
CredentialConfiguration: make(map[string]oidc4ci.InitiateIssuanceCredentialConfiguration),
}

for credentialConfigurationID, multiCredentialIssuance := range req.CredentialConfiguration.AdditionalProperties {
issuanceReq.CredentialConfiguration[credentialConfigurationID] = oidc4ci.InitiateIssuanceCredentialConfiguration{
ClaimData: lo.FromPtr(multiCredentialIssuance.ClaimData),
ClaimEndpoint: lo.FromPtr(multiCredentialIssuance.ClaimEndpoint),
CredentialTemplateId: lo.FromPtr(multiCredentialIssuance.CredentialTemplateId),
CredentialExpiresAt: multiCredentialIssuance.CredentialExpiresAt,
CredentialName: lo.FromPtr(multiCredentialIssuance.CredentialName),
CredentialDescription: lo.FromPtr(multiCredentialIssuance.CredentialDescription),
if req.CredentialConfiguration != nil {
for credentialConfigurationID, multiCredentialIssuance := range req.CredentialConfiguration.AdditionalProperties {
issuanceReq.CredentialConfiguration[credentialConfigurationID] = oidc4ci.InitiateIssuanceCredentialConfiguration{
ClaimData: lo.FromPtr(multiCredentialIssuance.ClaimData),
ClaimEndpoint: lo.FromPtr(multiCredentialIssuance.ClaimEndpoint),
CredentialTemplateId: lo.FromPtr(multiCredentialIssuance.CredentialTemplateId),
CredentialExpiresAt: multiCredentialIssuance.CredentialExpiresAt,
CredentialName: lo.FromPtr(multiCredentialIssuance.CredentialName),
CredentialDescription: lo.FromPtr(multiCredentialIssuance.CredentialDescription),
}
}
}

Expand Down Expand Up @@ -652,9 +654,8 @@ func (c *Controller) ExchangeAuthorizationCodeRequest(ctx echo.Context) error {
}

var authorizationDetailsDTOList []common.AuthorizationDetails
if exchangeAuthorizationCodeResult.AuthorizationDetails != nil {
authorizationDetailsDTO := exchangeAuthorizationCodeResult.AuthorizationDetails.ToDTO()
authorizationDetailsDTOList = []common.AuthorizationDetails{authorizationDetailsDTO}
for _, ad := range exchangeAuthorizationCodeResult.AuthorizationDetails {
authorizationDetailsDTOList = append(authorizationDetailsDTOList, ad.ToDTO())
}

return util.WriteOutput(ctx)(
Expand Down Expand Up @@ -709,7 +710,8 @@ func (c *Controller) PrepareCredential(e echo.Context) error {
return err
}

vcFormat, err := common.ValidateVCFormat(common.VCFormat(lo.FromPtr(body.Format)))
requestedFormat := lo.FromPtr(body.Format)
_, err := common.ValidateVCFormat(common.VCFormat(requestedFormat))
if err != nil {
return resterr.NewValidationError(resterr.InvalidValue, "format", err)
}
Expand All @@ -721,7 +723,7 @@ func (c *Controller) PrepareCredential(e echo.Context) error {
&oidc4ci.PrepareCredential{
TxID: oidc4ci.TxID(body.TxId),
CredentialTypes: body.Types,
CredentialFormat: vcFormat,
CredentialFormat: vcsverifiable.OIDCFormat(requestedFormat),
DID: lo.FromPtr(body.Did),
AudienceClaim: body.AudienceClaim,
HashedToken: body.HashedToken,
Expand Down
32 changes: 16 additions & 16 deletions pkg/service/oidc4ci/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ type PrepareClaimDataAuthorizationResponse struct {
type PrepareCredential struct {
TxID TxID
CredentialTypes []string
CredentialFormat vcsverifiable.Format
CredentialFormat vcsverifiable.OIDCFormat
DID string
AudienceClaim string
HashedToken string
Expand Down Expand Up @@ -251,20 +251,20 @@ type AuthorizeState struct {
}

type EventPayload struct {
WebHook string `json:"webHook,omitempty"`
ProfileID string `json:"profileID,omitempty"`
ProfileVersion string `json:"profileVersion,omitempty"`
CredentialTemplateID string `json:"credentialTemplateID,omitempty"`
OrgID string `json:"orgID,omitempty"`
WalletInitiatedFlow bool `json:"walletInitiatedFlow"`
PinRequired bool `json:"pinRequired"`
PreAuthFlow bool `json:"preAuthFlow"`
Format string `json:"format,omitempty"`
InitiateIssuanceURL string `json:"initiateIssuanceURL,omitempty"`
AuthorizationEndpoint string `json:"authorizationEndpoint,omitempty"`
Error string `json:"error,omitempty"`
ErrorCode string `json:"errorCode,omitempty"`
ErrorComponent string `json:"errorComponent,omitempty"`
WebHook string `json:"webHook,omitempty"`
ProfileID string `json:"profileID,omitempty"`
ProfileVersion string `json:"profileVersion,omitempty"`
CredentialTemplateID string `json:"credentialTemplateID,omitempty"`
OrgID string `json:"orgID,omitempty"`
WalletInitiatedFlow bool `json:"walletInitiatedFlow"`
PinRequired bool `json:"pinRequired"`
PreAuthFlow bool `json:"preAuthFlow"`
Format vcsverifiable.Format `json:"format,omitempty"`
InitiateIssuanceURL string `json:"initiateIssuanceURL,omitempty"`
AuthorizationEndpoint string `json:"authorizationEndpoint,omitempty"`
Error string `json:"error,omitempty"`
ErrorCode string `json:"errorCode,omitempty"`
ErrorComponent string `json:"errorComponent,omitempty"`
}

type AuthorizationCodeGrant struct {
Expand Down Expand Up @@ -354,7 +354,7 @@ type ExchangeAuthorizationCodeResult struct {
TxID TxID
// AuthorizationDetails REQUIRED when authorization_details parameter is used to request issuance
// of a certain Credential type in Authorization Request. It MUST NOT be used otherwise.
AuthorizationDetails *AuthorizationDetails
AuthorizationDetails []*AuthorizationDetails
}

var ErrDataNotFound = errors.New("data not found")
Loading

0 comments on commit d5d00fb

Please sign in to comment.