Skip to content

Commit

Permalink
Policy: add 'type' query parameter to /presentation_definition endpoi…
Browse files Browse the repository at this point in the history
…nt (#3019)
  • Loading branch information
reinkrul authored Apr 9, 2024
1 parent c59a40c commit b856651
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 5 deletions.
11 changes: 8 additions & 3 deletions auth/api/iam/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,11 +474,16 @@ func (r Wrapper) PresentationDefinition(ctx context.Context, request Presentatio
}
}

if _, ok := mapping[pe.WalletOwnerOrganization]; !ok {
return nil, oauthError(oauth.ServerError, "no presentation definition found for organization wallet")
walletOwnerType := pe.WalletOwnerOrganization
if request.Params.WalletOwnerType != nil {
walletOwnerType = *request.Params.WalletOwnerType
}
result, exists := mapping[walletOwnerType]
if !exists {
return nil, oauthError(oauth.InvalidRequest, fmt.Sprintf("no presentation definition found for '%s' wallet", walletOwnerType))
}

return PresentationDefinition200JSONResponse(mapping[pe.WalletOwnerOrganization]), nil
return PresentationDefinition200JSONResponse(result), nil
}

// toOwnedDIDForOAuth2 is like toOwnedDID but wraps the errors in oauth.OAuth2Error to make sure they're returned as specified by the OAuth2 RFC.
Expand Down
28 changes: 28 additions & 0 deletions auth/api/iam/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ func TestWrapper_PresentationDefinition(t *testing.T) {
webDID := did.MustParseDID("did:web:example.com:iam:123")
ctx := audit.TestContext()
walletOwnerMapping := pe.WalletOwnerMapping{pe.WalletOwnerOrganization: pe.PresentationDefinition{Id: "test"}}
userWalletType := pe.WalletOwnerUser

t.Run("ok", func(t *testing.T) {
test := newTestClient(t)
Expand All @@ -250,6 +251,33 @@ func TestWrapper_PresentationDefinition(t *testing.T) {
assert.True(t, ok)
})

t.Run("ok - user wallet", func(t *testing.T) {
walletOwnerMapping := pe.WalletOwnerMapping{pe.WalletOwnerUser: pe.PresentationDefinition{Id: "test"}}

test := newTestClient(t)
test.policy.EXPECT().PresentationDefinitions(gomock.Any(), webDID, "example-scope").Return(walletOwnerMapping, nil)
test.vdr.EXPECT().IsOwner(gomock.Any(), webDID).Return(true, nil)

response, err := test.client.PresentationDefinition(ctx, PresentationDefinitionRequestObject{Did: webDID.String(), Params: PresentationDefinitionParams{Scope: "example-scope", WalletOwnerType: &userWalletType}})

require.NoError(t, err)
require.NotNil(t, response)
_, ok := response.(PresentationDefinition200JSONResponse)
assert.True(t, ok)
})

t.Run("err - unknown wallet type", func(t *testing.T) {
test := newTestClient(t)
test.vdr.EXPECT().IsOwner(gomock.Any(), webDID).Return(true, nil)
test.policy.EXPECT().PresentationDefinitions(gomock.Any(), webDID, "example-scope").Return(walletOwnerMapping, nil)

response, err := test.client.PresentationDefinition(ctx, PresentationDefinitionRequestObject{Did: webDID.String(), Params: PresentationDefinitionParams{Scope: "example-scope", WalletOwnerType: &userWalletType}})

require.Error(t, err)
assert.Nil(t, response)
assert.Equal(t, "invalid_request - no presentation definition found for 'user' wallet", err.Error())
})

t.Run("error - unknown scope", func(t *testing.T) {
test := newTestClient(t)
test.vdr.EXPECT().IsOwner(gomock.Any(), webDID).Return(true, nil)
Expand Down
10 changes: 9 additions & 1 deletion auth/api/iam/generated.go

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

2 changes: 1 addition & 1 deletion auth/api/iam/openid4vp.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ func (r Wrapper) handleAccessTokenRequest(ctx context.Context, verifier did.DID,
return nil, withCallbackURI(oauthError(oauth.InvalidRequest, fmt.Sprintf("client_id does not match: %s vs %s", oauthSession.ClientID, *clientId)), callbackURI)
}

state := oauthSession.ServerState
state := oauthSession.ServerState
mapping, err := r.policyBackend.PresentationDefinitions(ctx, verifier, oauthSession.Scope)
if err != nil {
return nil, withCallbackURI(oauthError(oauth.ServerError, fmt.Sprintf("failed to fetch presentation definition: %s", err.Error())), callbackURI)
Expand Down
3 changes: 3 additions & 0 deletions auth/api/iam/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ type OAuthAuthorizationServerMetadata = oauth.AuthorizationServerMetadata
// OAuthClientMetadata is an alias
type OAuthClientMetadata = oauth.OAuthClientMetadata

// WalletOwnerType is an alias
type WalletOwnerType = pe.WalletOwnerType

const (
sessionExpiry = 5 * time.Minute
)
Expand Down
1 change: 1 addition & 0 deletions codegen/configs/auth_iam.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ output-options:
- TokenResponse
- VerifiablePresentation
- VerifiableCredential
- WalletOwnerType
12 changes: 12 additions & 0 deletions docs/_static/auth/iam.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ paths:
description: |
The scope for which a presentation definition is requested. Multiple scopes can be specified by separating them with a space.
example: usecase patient:x:read
- name: wallet_owner_type
in: query
schema:
$ref: '#/components/schemas/WalletOwnerType'
responses:
"200":
description: PresentationDefinition that matches scope is found.
Expand Down Expand Up @@ -804,6 +808,14 @@ components:
items:
$ref: '#/components/schemas/VerifiablePresentation'
description: The Verifiable Presentations that were used to request the access token using the same encoding as used in the access token request.
WalletOwnerType:
type: string
description: |
Wallet owner type that should fulfill the presentation definition.
Can either be an organization wallet or a user (personal) wallet.
enum:
- organization
- user
securitySchemes:
jwtBearerAuth:
type: http
Expand Down

0 comments on commit b856651

Please sign in to comment.