Skip to content

Support request byValue and byReference and presentationDefinition #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 139 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ logging:
verifier:
# did to be used by the verifier.
did:
# identification of the verifier in communication with wallets
clientIdentification:
# identification used by the verifier when requesting authorization. Can be a did, but also methods like x509_san_dns
id:
# path to the signing key(in pem format) for request object. Needs to correspond with the id
keyPath:
# algorithm to be used for signing the request. Needs to match the signing key
requestKeyAlgorithm:
# depending on the id type, the certificate chain needs to be included in the object(f.e. in case of x509_san_dns)
certificatePath:
# supported modes for requesting authentication. in case of byReference and byValue, the clientIdentification needs to be properly configured
supportedModes: ["urlEncoded", "byReference","byValue"]
# address of the (ebsi-compliant) trusted-issuers-registry to be used for verifying the issuer of a received credential
tirAddress:
# Expiry(in seconds) of an authentication session. After that, a new flow needs to be initiated.
Expand All @@ -118,6 +130,8 @@ verifier:
# * `baseContext`: validates that only the fields and values (when applicable)are present in the document. No extra fields are allowed (outside of credentialSubject).
# Default is set to `none` to ensure backwards compatibility
validationMode:
# algorithm to be used for the jwt signatures - currently supported: RS256 and ES256, default is RS256
keyAlgorithm:

# configuration of the service to retrieve configuration for
configRepo:
Expand All @@ -126,28 +140,57 @@ configRepo:
# static configuration for services
services:
# name of the service to be configured
testService:
# scope to be requested from the wallet
scope:
- VerifiableCredential
- CustomerCredential
# trusted participants endpoint configuration
trustedParticipants:
# the credentials type to configure the endpoint(s) for
VerifiableCredential:
- https://tir-pdc.ebsi.fiware.dev
# the credentials type to configure the endpoint(s) for
CustomerCredential:
- https://tir-pdc.ebsi.fiware.dev
# trusted issuers endpoint configuration
trustedIssuers:
# the credentials type to configure the endpoint(s) for
VerifiableCredential:
- https://tir-pdc.ebsi.fiware.dev
# the credentials type to configure the endpoint(s) for
CustomerCredential:
- https://tir-pdc.ebsi.fiware.dev

- id: testService
# default scope for the service
defaultOidcScope: "default"
# the concrete scopes for the service, defining the trust for credentials and the presentation definition to be requested
oidcScopes:
# the concrete scope configuration
default:
# credentials and their trust configuration
credentials:
- type: CustomerCredential
# trusted participants endpoint configuration
trustedParticipantsLists:
# the credentials type to configure the endpoint(s) for
VerifiableCredential:
- https://tir-pdc.ebsi.fiware.dev
# the credentials type to configure the endpoint(s) for
CustomerCredential:
- https://tir-pdc.ebsi.fiware.dev
# trusted issuers endpoint configuration
trustedIssuersLists:
# the credentials type to configure the endpoint(s) for
VerifiableCredential:
- https://tir-pdc.ebsi.fiware.dev
# the credentials type to configure the endpoint(s) for
CustomerCredential:
- https://tir-pdc.ebsi.fiware.dev
# configuration for verifying the holder of a credential
holderVerification:
# should it be checked?
enabled: true
# claim to retrieve the holder from
claim: subject
# credentials and claims to be requested
presentationDefinition:
id: my-presentation
# List of requested inputs
input_descriptors:
id: my-descriptor
# defines the infromation to be requested
constraints:
# array of objects to describe the information to be included
fields:
- id: my-field
path:
- $.vct
filter:
const: "CustomerCredential"
# format of the credential to be requested
format:
'sd+jwt-vc':
alg: ES256
```
#### Templating

Expand All @@ -165,6 +208,11 @@ In order to ease the integration into frontends, VCVerifier offers a login-page

In order to start a ```same-device```-flow(e.g. the credential is hold by the requestor, instead of an additional device like a mobile wallet) call:
```shell
# scope to be requested from the wallet
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Misplaced C&P?

scope:
- VerifiableCredential
- CustomerCredential

curl -X 'GET' \
'http://localhost:8080/api/v1/samedevice?state=274e7465-cc9d-4cad-b75f-190db927e56a'
```
Expand Down Expand Up @@ -235,6 +283,11 @@ configRepo:
# the credentials type to configure the endpoint(s) for
VerifiableCredential:
- type: ebsi
# scope to be requested from the wallet
scope:
- VerifiableCredential
- CustomerCredential

url: https://tir-pdc.ebsi.fiware.dev
```

Expand All @@ -258,7 +311,12 @@ configRepo:

### Gaia-X Registry

When using the [Gaia-X Digital Clearing House's](https://gaia-x.eu/services-deliverables/digital-clearing-house/) Registry Services, the issuer to be checked needs to fullfill the requirements of a Gaia-X participant. Thus, only did:web is supported for such and they need to provide a valid ```x5u``` location as part of their ```publicKeyJwk```. Usage of such registries can than be configured as following:
When using the [Gaia-X Digital Clearing House's](https://gaia-x.eu/services-deliverables/digital-clearing-house/) Registry Services, the issuer to be checked needs to fullfill the requirements of
# scope to be requested from the wallet
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again C&P? 😅

scope:
- VerifiableCredential
- CustomerCredential
a Gaia-X participant. Thus, only did:web is supported for such and they need to provide a valid ```x5u``` location as part of their ```publicKeyJwk```. Usage of such registries can than be configured as following:
```yaml
configRepo:
# static configuration for services
Expand Down Expand Up @@ -298,6 +356,64 @@ configRepo:
url: https://registry.lab.gaia-x.eu
```

### Request modes

In order to support various wallets, the verifier supports 3 modes of requesting authentication:
- Passing as URL with encoded parameters: "urlEncoded"
- Passing a request object as value: "byValue"
- Passing a request object by reference: "byReference"

Following the [RFC9101](https://www.rfc-editor.org/rfc/rfc9101.html), in the second and third case the request is encoded as a signed JWT. Therefor ```clientIdentification``` for the verifier needs to be properly configured.

The mode can be set during the intial requests, by sending the parameter "requestMode"(see [API Spec](./api/api.yaml)).Since requestObjects can become large and therefor also the QR-Codes generated out of them, the 3rd mode is recommended.

#### urlEncoded

Example:
```
openid4vp://?response_type=vp_token&response_mode=direct_post&client_id=did:key:verifier&redirect_uri=https://verifier.org/api/v1/authentication_response&state=randomState&nonce=randomNonce
```

#### byValue
Example:
```
openid4vp://?client_id=did:key:verifier&request=eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hdXRoLWF1dGh6LXJlcStqd3QifQ.eyJjbGllbnRfaWQiOiJkaWQ6a2V5OnZlcmlmaWVyIiwiZXhwIjozMCwiaXNzIjoiZGlkOmtleTp2ZXJpZmllciIsIm5vbmNlIjoicmFuZG9tTm9uY2UiLCJwcmVzZW50YXRpb25fZGVmaW5pdGlvbiI6eyJpZCI6IiIsImlucHV0X2Rlc2NyaXB0b3JzIjpudWxsLCJmb3JtYXQiOm51bGx9LCJyZWRpcmVjdF91cmkiOiJodHRwczovL3ZlcmlmaWVyLm9yZy9hcGkvdjEvYXV0aGVudGljYXRpb25fcmVzcG9uc2UiLCJyZXNwb25zZV90eXBlIjoidnBfdG9rZW4iLCJzY29wZSI6Im9wZW5pZCIsInN0YXRlIjoicmFuZG9tU3RhdGUifQ.Z0xv_E9vvhRN2nBeKQ49LgH8lkjkX-weR7R5eCmX9ebGr1aE8_6usa2PO9nJ4LRv8oWMg0q9fsQ2x5DTYbvLdA
```
Decoded:
```json
{
"alg": "ES256",
"typ": "oauth-authz-req+jwt"
}.
{
"client_id": "did:key:verifier",
"exp": 30,
"iss": "did:key:verifier",
"nonce": "randomNonce",
"presentation_definition": {
"id": "",
"input_descriptors": null,
"format": null
},
"redirect_uri": "https://verifier.org/api/v1/authentication_response",
"response_type": "vp_token",
"scope": "openid",
"state": "randomState"
}.
signature
```

#### byReference

Example:
```
openid4vp://?client_id=did:key:verifier&request_uri=verifier.org/api/v1/request/randomState&request_uri_method=get"
```
The object than can be retrived via:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The object than can be retrived via:
The object than can be retrieved via:

```shell
curl https://verifier.org/api/v1/request/randomState
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it help to show an example value of the retrieved data here?


## API

The API implements enpoints defined in [OIDC4VP](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#name-terminology) and [SIOP-2](https://openid.net/specs/openid-connect-self-issued-v2-1_0.html). The OpenAPI Specification of the implemented endpoints can be found at: [api/api.yaml](api/api.yaml).
Expand Down
36 changes: 35 additions & 1 deletion api/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ paths:
- $ref: '#/components/parameters/QueryState'
- $ref: '#/components/parameters/ClientCallback'
- $ref: '#/components/parameters/ClientId'
- $ref: '#/components/parameters/RequestMode'
operationId: VerifierPageDisplayQRSIOP
summary: Presents a qr as starting point for the auth process
description: Returns a rendered html with a QR encoding the login-starting point for the siop flow - e.g. 'openid://?scope=somethign&response_type=rt&response_mode=rm&client_id=ci&redirect_uri=uri&state=state&nonce=nonce'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: Returns a rendered html with a QR encoding the login-starting point for the siop flow - e.g. 'openid://?scope=somethign&response_type=rt&response_mode=rm&client_id=ci&redirect_uri=uri&state=state&nonce=nonce'
description: Returns a rendered html with a QR encoding the login-starting point for the siop flow - e.g. 'openid://?scope=somethign&response_type=rt&response_mode=rm&client_id=ci&redirect_uri=uri&state=state&nonce=nonce&request_mode=urlEncoded'

Expand All @@ -34,7 +35,30 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'


/api/v1/request/{id}:
get:
tags:
- api
parameters:
- $ref: '#/components/parameters/Id'
operationId: GetRequestByReference
summary: Get the request object by reference
description: Returns the request object by reference as defined in https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#section-5
responses:
'200':
description: The jwt encoded request object
content:
text/html:
schema:
type: string
'400':
description: In case of broken requests.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'

/api/v1/samedevice:
get:
tags:
Expand Down Expand Up @@ -248,6 +272,16 @@ components:
schema:
type: string
example: packet-delivery-portal
RequestMode:
name: request_mode
description: Mode to be used for the authorization request.
in: query
required: false
schema:
type: string
enum:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

byReference missing?

- urlEncoded
- byValue
ServiceId:
name: service_id
description: The id of the client/service that intents to start the authentication flow. Will be used to retrieve the scope and trust services to be used for verification.
Expand Down
14 changes: 14 additions & 0 deletions common/fileSystem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package common

import "os"

// file system interfaces

type FileAccessor interface {
ReadFile(filename string) ([]byte, error)
}
type DiskFileAccessor struct{}

func (DiskFileAccessor) ReadFile(filename string) ([]byte, error) {
return os.ReadFile(filename)
}
9 changes: 4 additions & 5 deletions common/tokenSigner.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package common

import (
"github.com/lestrrat-go/jwx/jwa"
"github.com/lestrrat-go/jwx/jwt"
"github.com/lestrrat-go/jwx/v3/jwt"
)

type TokenSigner interface {
Sign(t jwt.Token, alg jwa.SignatureAlgorithm, key interface{}, options ...jwt.SignOption) ([]byte, error)
Sign(t jwt.Token, options ...jwt.SignOption) ([]byte, error)
}

type JwtTokenSigner struct{}

func (JwtTokenSigner) Sign(t jwt.Token, alg jwa.SignatureAlgorithm, key interface{}, options ...jwt.SignOption) ([]byte, error) {
return jwt.Sign(t, alg, key, options...)
func (JwtTokenSigner) Sign(t jwt.Token, options ...jwt.SignOption) ([]byte, error) {
return jwt.Sign(t, options...)
}
15 changes: 15 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ type Logging struct {
type Verifier struct {
// did to be used by the verifier
Did string `mapstructure:"did"`
// Identification to be used for the verifier
ClientIdentification ClientIdentification `mapstructure:"clientIdentification"`
// supported request modes - currently 'urlEncoded', 'byValue' an 'byReference' are available. In case of byValue, the keyPath has to be set.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// supported request modes - currently 'urlEncoded', 'byValue' an 'byReference' are available. In case of byValue, the keyPath has to be set.
// supported request modes - currently 'urlEncoded', 'byValue' and 'byReference' are available. In case of byValue, the keyPath has to be set.

SupportedModes []string `mapstructure:"supportedModes" default:"urlEncoded"`
// address of the (ebsi-compatible) trusted-issuers-registry for verifying the issuer
TirAddress string `mapstructure:"tirAddress"`
// expiry of the tir-cache entries
Expand All @@ -80,6 +84,17 @@ type Verifier struct {
KeyAlgorithm string `mapstructure:"keyAlgorithm" default:"RS256"`
}

type ClientIdentification struct {
// path to the did signing key(in pem format) for request object mode
KeyPath string `mapstructure:"keyPath"`
// algorithm used for the request signing key
KeyAlgorithm string `mapstructure:"requestKeyAlgorithm"`
// identification used by the verifier when requesting authorization. Can be a did, but also methods like x509_san_dns
Id string `mapstructure:"id"`
// optional path to the certifcate to embed in the jwt header
CertificatePath string `mapstructure:"certificatePath"`
}

type Elsi struct {
// should the support for did:elsi be enabled
Enabled bool `mapstructure:"enabled" default:"false"`
Expand Down
Loading
Loading