Skip to content

Commit

Permalink
feat: add interaction_details on ack request (trustbloc#1782)
Browse files Browse the repository at this point in the history
Signed-off-by: Misha Sizov <[email protected]>
  • Loading branch information
mishasizov-SK authored Oct 15, 2024
1 parent 29d4d67 commit 3616094
Show file tree
Hide file tree
Showing 22 changed files with 1,295 additions and 674 deletions.
408 changes: 204 additions & 204 deletions api/spec/openapi.gen.go

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions component/wallet-cli/pkg/oidc4vci/oidc4vci_flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -1150,15 +1150,18 @@ func (f *Flow) handleIssuanceAck(
)

ackRequest := oidc4civ1.AckRequest{
Credentials: []oidc4civ1.AcpRequestItem{},
Credentials: []oidc4civ1.AckRequestItem{},
InteractionDetails: lo.ToPtr(map[string]interface{}{
"notification_ids": notificationIDs,
}),
}

for _, notificationID := range notificationIDs {
if notificationID == "" {
continue
}

ackRequest.Credentials = append(ackRequest.Credentials, oidc4civ1.AcpRequestItem{
ackRequest.Credentials = append(ackRequest.Credentials, oidc4civ1.AckRequestItem{
Event: "credential_accepted",
EventDescription: nil,
IssuerIdentifier: wellKnown.CredentialIssuer,
Expand Down
8 changes: 8 additions & 0 deletions component/wallet-cli/pkg/oidc4vp/oidc4vp_flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package oidc4vp
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -196,12 +197,15 @@ func (f *Flow) Run(ctx context.Context) error {
vps, presentationSubmission, err := f.queryWallet(&pd, requestObject.ClientMetadata.VPFormats)
if err != nil {
if strings.Contains(err.Error(), "no matching credentials found") {
interactionDetailsBytes, _ := json.Marshal(map[string]string{"transaction_id": requestObject.State})

// Send wallet notification no_match_found.
v := url.Values{}

v.Add("error", "access_denied")
v.Add("error_description", "no_match_found")
v.Add("state", requestObject.State)
v.Add("interaction_details", base64.StdEncoding.EncodeToString(interactionDetailsBytes))

if e := f.postAuthorizationResponse(ctx, requestObject.ResponseURI, []byte(v.Encode())); e != nil {
slog.Error("failed to send wallet notification", "err", e)
Expand Down Expand Up @@ -487,6 +491,10 @@ func (f *Flow) sendAuthorizationResponse(
v.Add("presentation_submission", string(presentationSubmissionJSON))
v.Add("state", requestObject.State)

interactionDetailsBytes, _ := json.Marshal(map[string]string{"transaction_id": requestObject.State})

v.Add("interaction_details", base64.StdEncoding.EncodeToString(interactionDetailsBytes))

f.perfInfo.CreateAuthorizedResponse = time.Since(start)

return f.postAuthorizationResponse(ctx, requestObject.ResponseURI, []byte(v.Encode()))
Expand Down
8 changes: 5 additions & 3 deletions docs/v1/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2316,12 +2316,14 @@ components:
credentials:
type: array
items:
$ref: '#/components/schemas/AcpRequestItem'
$ref: '#/components/schemas/AckRequestItem'
interaction_details:
type: object
required:
- credentials
AcpRequestItem:
AckRequestItem:
type: object
description: AcpRequestItem
description: AckRequestItem
properties:
notification_id:
type: string
Expand Down
11 changes: 6 additions & 5 deletions pkg/restapi/v1/oidc4ci/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -648,11 +648,12 @@ func (c *Controller) OidcAcknowledgement(e echo.Context) error {
var finalErr error
for _, r := range body.Credentials {
if err := c.ackService.Ack(req.Context(), oidc4ci.AckRemote{
HashedToken: hashToken(token),
ID: r.NotificationId,
Event: r.Event,
EventDescription: lo.FromPtr(r.EventDescription),
IssuerIdentifier: lo.FromPtr(r.IssuerIdentifier),
HashedToken: hashToken(token),
ID: r.NotificationId,
Event: r.Event,
EventDescription: lo.FromPtr(r.EventDescription),
IssuerIdentifier: lo.FromPtr(r.IssuerIdentifier),
InteractionDetails: lo.FromPtr(body.InteractionDetails),
}); err != nil {
finalErr = errors.Join(finalErr, err)
}
Expand Down
7 changes: 6 additions & 1 deletion pkg/restapi/v1/oidc4ci/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4559,12 +4559,17 @@ func TestController_Ack(t *testing.T) {
assert.Equal(t, "tx_id", remote.ID)
assert.Equal(t, "credential_accepted", remote.Event)
assert.Equal(t, "err_txt", remote.EventDescription)
assert.Equal(t, map[string]interface{}{
"userId": "userId",
"transactionId": "transactionId",
}, remote.InteractionDetails)

return nil
})

req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBuffer([]byte(`{
"credentials" : [{"notification_id" : "tx_id", "event" : "credential_accepted", "event_description" : "err_txt"}]
"credentials" : [{"notification_id" : "tx_id", "event" : "credential_accepted", "event_description" : "err_txt"}],
"interaction_details": {"userId": "userId", "transactionId": "transactionId"}
}`)))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
req.Header.Set("Authorization", "Bearer xxxx")
Expand Down
7 changes: 4 additions & 3 deletions pkg/restapi/v1/oidc4ci/openapi.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 33 additions & 7 deletions pkg/restapi/v1/verifier/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package verifier

import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -67,6 +68,7 @@ type rawAuthorizationResponse struct {
Error string
ErrorDescription string
State string
InteractionDetails map[string]interface{}
}

type IDTokenClaims struct {
Expand Down Expand Up @@ -464,9 +466,10 @@ func (c *Controller) CheckAuthorizationResponse(e echo.Context) error {
// Error authorization response
// Spec: https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#section-6.4
return c.oidc4VPService.HandleWalletNotification(ctx, &oidc4vp.WalletNotification{
TxID: oidc4vp.TxID(rawAuthResp.State),
Error: rawAuthResp.Error,
ErrorDescription: rawAuthResp.ErrorDescription,
TxID: oidc4vp.TxID(rawAuthResp.State),
Error: rawAuthResp.Error,
ErrorDescription: rawAuthResp.ErrorDescription,
InteractionDetails: rawAuthResp.InteractionDetails,
})
}

Expand Down Expand Up @@ -645,10 +648,11 @@ func (c *Controller) verifyAuthorizationResponseTokens(
}

return &oidc4vp.AuthorizationResponseParsed{
CustomScopeClaims: idTokenClaims.CustomScopeClaims,
VPTokens: processedVPTokens,
AttestationVP: idTokenClaims.AttestationVP,
Attachments: idTokenClaims.Attachments,
CustomScopeClaims: idTokenClaims.CustomScopeClaims,
VPTokens: processedVPTokens,
AttestationVP: idTokenClaims.AttestationVP,
Attachments: idTokenClaims.Attachments,
InteractionDetails: authResp.InteractionDetails,
}, nil
}

Expand Down Expand Up @@ -865,6 +869,28 @@ func decodeAuthorizationResponse(ctx echo.Context) (*rawAuthorizationResponse, e
return nil, err
}

var rawInteractionDetails string
err = decodeFormValue(&rawInteractionDetails, "interaction_details", req.PostForm)
if err == nil {
var rawInteractionDetailsBytes []byte

rawInteractionDetailsBytes, err = base64.StdEncoding.DecodeString(rawInteractionDetails)
if err != nil {
return nil, resterr.NewValidationError(
resterr.InvalidValue,
"interaction_details",
fmt.Errorf("base64 decode: %w", err))
}

err = json.Unmarshal(rawInteractionDetailsBytes, &res.InteractionDetails)
if err != nil {
return nil, resterr.NewValidationError(
resterr.InvalidValue,
"interaction_details",
fmt.Errorf("json decode: %w", err))
}
}

err = decodeFormValue(&res.Error, "error", req.PostForm)
if err == nil {
// Error authorization response
Expand Down
Loading

0 comments on commit 3616094

Please sign in to comment.