eu-digital-identity-wallet / eudi-srv-web-verifier-endpoint-23220-4-kt

Web application (Backend Restful service) that acts as a Verifier/RP trusted end-point.
Apache License 2.0
9 stars 11 forks source link
kotlin openid4vp rfc9101 siopv2 springboot3

EUDI Verifier Endpoint

Important! Before you proceed, please read the EUDI Wallet Reference Implementation project description

License

Table of contents

Overview

This is a Web application (Backend Restful service) that acts as a Verifier/RP trusted end-point. This backend service is accompanied by a Web UI application implemented here.

See section Run all verifier components together on how to boot both applications together.

Application exposes two APIs

The Verifier API, supports two operations:

An Open API v3 specification of these operations is available here.

The Wallet API, provides the following main operations

Please note that

Both of those concerns have not been tackled by the current version of the application, since in its current version is merely a development tool, rather a production application.

Disclaimer

The released software is a initial development release version:

How to build and run

To start the service locally you can execute

./gradlew bootRun

To build a local docker image of the service execute

./gradlew bootBuildImage

Run all verifier components together

To start both verifier UI and verifier backend services together a docker compose file has been implemented that can be found here Running the command below will start the following service:

To start the docker compose environment

# From project root directory 
cd docker
docker-compose up -d

To stop the docker compose environment

# From project root directory 
cd docker
docker-compose down

The 'verifier' service can be configured by setting its configuration properties described here by setting them as environment variables of the service in docker-compose.yaml

Example:

  verifier:
    image: ghcr.io/eu-digital-identity-wallet/eudi-srv-web-verifier-endpoint-23220-4-kt:latest
    container_name: verifier-backend
    ports:
      - "8080:8080"
    environment:
      VERIFIER_PUBLICURL: "https://10.240.174.10"
      VERIFIER_RESPONSE_MODE: "DirectPost"
      VERIFIER_JAR_SIGNING_KEY_KEYSTORE: file:///keystore.jks

Mount external keystore to be used with Authorization Request signing

When property VERIFIER_JAR_SIGNING_KEY is set to LoadFromKeystore the service can be configured (as described here) to read from a keystore the certificate used for signing authorization requests. To provide an external keystore mount it to the path designated by the value of property VERIFIER_JAR_SIGNING_KEY_KEYSTORE.

Example:

  verifier:
    image: ghcr.io/eu-digital-identity-wallet/eudi-srv-web-verifier-endpoint-23220-4-kt:latest
    container_name: verifier-backend
    ports:
      - "8080:8080"
    environment:
      VERIFIER_PUBLICURL: "https://10.240.174.10"
      VERIFIER_RESPONSE_MODE: "DirectPost"
      VERIFIER_JAR_SIGNING_KEY_KEYSTORE: file:///certs/keystore.jks
    volumes:
      - <PATH OF KEYSTORE IN HOST MACHINE>/keystore.jks:/certs/keystore.jks

Presentation Flows

Same device

sequenceDiagram    
    participant UA as User Agent
    participant W as Wallet
    participant V as Verifier
    participant VE as Verifier Endpoint
    UA->>V: Trigger presentation 

    V->>+VE: Initiate transaction
    VE-->>-V: Authorization request as request_url

    V->>UA: Render request as deep link
    UA->>W: Trigger wallet and pass request

    W->>+VE: Get authorization request via request_uri 
    VE-->>-W: authorization_request

    W->>W: Parse authorization request

    W->>+VE: Get presentation definition 
    VE-->>-W: presentation_definition

    W->>W: Prepare response     

    W->>+VE: Post vp_token response 
    VE->>VE: Validate response and prepare response_code
    VE-->>-W: Return redirect_uri with response_code

    W->>UA: Refresh user agent to follow redirect_uri
    UA->>V: Follow redirect_uri passing response_code

    V->>+VE: Get wallet response passing response_code 
    VE->>VE: Validate response_code matches wallet response
    VE-->>-V: Return wallet response

    V->>UA: Render wallet response 

Cross device

sequenceDiagram    
    participant UA as User Agent
    participant W as Wallet
    participant V as Verifier
    participant VE as Verifier Endpoint
    UA->>V: Trigger presentation 

    V->>+VE:  Initiate transaction
    VE-->>-V: Authorization request as request_url

    V->>UA: Render request as QR Code

    loop
    V->>+VE: Get wallet response
    VE-->>-V: Return wallet response
    Note over V,VE: Verifier starts polling Verifier Endpoint for Wallet Response
    end

    UA->>W: Scan QR Code, trigger wallet, and pass request

    W->>+VE: Get authorization request via request_uri 
    VE-->>-W: authorization_request

    W->>W: Parse authorization request

    W->>+VE: Get presentation definition 
    VE-->>-W: presentation_definition

    W->>W: Prepare response     

    W->>+VE: Post vp_token response 
    VE->>VE: Validate response

    loop
    V->>+VE: Get wallet response
    VE-->>-V: Return wallet response
    end

    V->>UA: Render wallet response

Endpoints

Initialize transaction endpoint

An endpoint to control the content of the authorization request that will be prepared from the verifier backend service. Payload of this request is a json object with the following acceptable attributes:

Usage:

curl -X POST -H "Content-type: application/json" -d '{
  "type": "vp_token",  
  "presentation_definition": {
        "id": "32f54163-7166-48f1-93d8-ff217bdb0653",
        "input_descriptors": [
            {
                "constraints": {
                    "fields": [
                        {
                            "intent_to_retain": false,
                            "path": [
                                "$['eu.europa.ec.eudiw.pid.1']['family_name']"
                            ]
                        }
                    ]
                },
                "id": "eu.europa.ec.eudiw.pid.1",
                "format": {
                  "mso_mdoc": {
                    "alg": [
                      "ES256",
                      "ES384",
                      "ES512",
                      "EdDSA"
                    ]
                  }
                }
                "name": "EUDI PID",
                "purpose": "We need to verify your identity"
            }
        ]
    },
  "nonce": "nonce"
}' 'http://localhost:8080/ui/presentations'

Returns:

{
  "presentation_id": "STMMbidoCQTtyk9id5IcoL8CqdC8rxgks5FF8cqqUrHvw0IL3AaIHGnwxvrvcEyUJ6uUPNdoBQDa7yCqpjtKaw",
  "client_id": "dev.verifier-backend.eudiw.dev",
  "request_uri": "https://localhost:8080/wallet/request.jwt/5N6E7VZsmwXOGLz1Xlfi96MoyZVC3FZxwdAuJ26DnGcan-vYs-VAKErioQ58BWEsKlVw2_X49jpZHyp0Mk9nKw"
}

You can also try it out in Swagger UI.

Get authorization request

An endpoint to be used by wallet when the OpenId4VP authorization request is passed to wallet by reference as a request_uri. In essence this is the endpoint that responds to the url included as the request_uri attribute of the Initialize transaction endpoint's response.

Usage:

curl https://localhost:8080/wallet/request.jwt/5N6E7VZsmwXOGLz1Xlfi96MoyZVC3FZxwdAuJ26DnGcan-vYs-VAKErioQ58BWEsKlVw2_X49jpZHyp0Mk9nKw

Returns: The authorization request payload as a signed JWT.

Get presentation definition

An endpoint to be used by wallet when the presentation definition of the OpenId4VP authorization request is not embedded inline in the request but by reference as a presentation_definition_uri.

Usage:

curl https://localhost:8080/wallet/pd/5N6E7VZsmwXOGLz1Xlfi96MoyZVC3FZxwdAuJ26DnGcan-vYs-VAKErioQ58BWEsKlVw2_X49jpZHyp0Mk9nKw

Returns: The presentation definition of the authorization request as JSON.

Send wallet response

An endpoint available to wallet to post its response. Based on the response_mode of the OpenId4VP authorization request this endpoint can accept 2 type of payloads:

_response_mode = direct_post_

A form post (application/x-www-form-urlencoded encoding) with the following form parameters:

_response_mode = direct_post.jwt_

A form post (application/x-www-form-urlencoded encoding) with the following form parameters:

Usage:

STATE=IsoY9VwZXJ8GS7zg4CEHsCNu-5LpAiPGjbwYssZ2nh3tnkhytNw2mNZLSFsKOwdG2Ww33hX6PUp6P9xImdS-qA
curl -v -X POST 'http://localhost:8080/wallet/direct_post' \
  -H "Content-type: application/x-www-form-urlencoded" \
  -H "Accept: application/json" \
  --data-urlencode "state=$STATE" \
  --data-urlencode 'vp_token={"id": "123456"}' \
  --data-urlencode presentation_submission@- << EOF
{
  "id": "a30e3b91-fb77-4d22-95fa-871689c322e2",
  "definition_id": "32f54163-7166-48f1-93d8-ff217bdb0653",
  "descriptor_map": [
    {
      "id": "employment_input",
      "format": "jwt_vc",
      "path": "$.verifiableCredential[0]"
    }
  ]
}
EOF

Returns:

Get wallet response

curl http://localhost:8080/ui/presentations/5N6E7VZsmwXOGLz1Xlfi96MoyZVC3FZxwdAuJ26DnGcan-vYs-VAKErioQ58BWEsKlVw2_X49jpZHyp0Mk9nKw?response_code=5272d373-ebab-40ec-b44d-0a9909d0da69

Returns: The wallet submitted response as JSON.

You can also try it out in Swagger UI.

Get presentation event log

curl http://localhost:8080/ui/presentations/5N6E7VZsmwXOGLz1Xlfi96MoyZVC3FZxwdAuJ26DnGcan-vYs-VAKErioQ58BWEsKlVw2_X49jpZHyp0Mk9nKw?response_code=5272d373-ebab-40ec-b44d-0a9909d0da69/events

Returns: The log of notable events for the specific presentation.

You can also try it out in Swagger UI.

Configuration

The Verifier Endpoint application can be configured using the following environment variables:

Variable: SPRING_WEBFLUX_BASEPATH
Description: Context path for the Verifier Endpoint application.
Default value: /

Variable: SERVER_PORT
Description: Port for the HTTP listener of the Verifier Endpoint application
Default value: 8080

Variable: VERIFIER_CLIENTID
Description: Client Id of the Verifier Endpoint application
Default value: Verifier

Variable: VERIFIER_CLIENTIDSCHEME
Description: Client Id Scheme used by the Verifier Endpoint application
Possible values: pre-registered, x509_san_dns, x509_san_uri
Default value: pre-registered

Variable: VERIFIER_JAR_SIGNING_ALGORITHM
Description: Algorithm used to sign Authorization Request
Possible values: Any Algorithm Name of an IANA registered asymmetric signature algorithm (i.e. Usage is alg): https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
Note: The configured signing algorithm must be compatible with the configured signing key
Default value: RS256

Variable: VERIFIER_JAR_SIGNING_KEY
Description: Key to use for Authorization Request signing
Possible values: GenerateRandom, LoadFromKeystore
Setting this value to GenerateRandom will result in the generation of a random RSA key
Note: The configured signing key must be compatible with the configured signing algorithm
Default value: GenerateRandom

Variable: VERIFIER_PUBLICURL
Description: Public URL of the Verifier Endpoint application
Default value: http://localhost:${SERVER_PORT}

Variable: VERIFIER_REQUESTJWT_EMBED
Description: How Authorization Requests will be provided
Possible values: ByValue, ByReference
Default value: ByReference

Variable: VERIFIER_JWK_EMBED
Description: How the Ephemeral Keys used for Authorization Response Encryption will be provided in Authorization Requests
Possible values: ByValue, ByReference
Default value: ByReference

Variable: VERIFIER_PRESENTATIONDEFINITION_EMBED
Description: How Presentation Definitions will be provided in Authorization Requests
Possible values: ByValue, ByReference
Default value: ByValue

Variable: VERIFIER_RESPONSE_MODE
Description: How Authorization Responses are expected
Possible values: DirectPost, DirectPostJwt
Default value: DirectPostJwt

Variable: VERIFIER_MAXAGE
Description: TTL of an Authorization Request
Notes: Provide a value using Java Duration syntax
Example: PT6400M
Default value: PT6400M

Variable: VERIFIER_PRESENTATIONS_CLEANUP_MAXAGE
Description: Age of Authorization Requests. Authorization Requests older than this, are deleted.
Notes: Provide a value using Java Duration syntax
Example: P10D
Default value: P10D

Variable: VERIFIER_CLIENTMETADATA_AUTHORIZATIONSIGNEDRESPONSEALG
Description: Accept only Authorization Responses that are signed using this algorithm
Possible values: Any Algorithm Name of an IANA registered asymmetric signature algorithm (i.e. Usage is alg): https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms

Variable: VERIFIER_CLIENTMETADATA_AUTHORIZATIONENCRYPTEDRESPONSEALG
Description: Accept only Authorization Responses that are encrypted using this algorithm
Possible values: Any Algorithm Name of an IANA registered asymmetric encryption algorithm (i.e. Usage is alg): https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
Default value: ECDH-ES

Variable: VERIFIER_CLIENTMETADATA_AUTHORIZATIONENCRYPTEDRESPONSEENC
Description: Accept only Authorization Responses that are encrypted using this method
Possible values: Any Algorithm Name of an IANA registered asymmetric encryption method (i.e. Usage is enc): https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
Default value: A128CBC-HS256

Variable: CORS_ORIGINS
Description: Comma separated list of allowed Origins for cross-origin requests
Default value: *

Variable: CORS_ORIGINPATTERNS
Description: Comma separated list of patterns used for more fine grained matching of allowed Origins for cross-origin requests
Default value: *

Variable: CORS_METHODS
Description: Comma separated list of HTTP methods allowed for cross-origin requests
Default value: *

Variable: CORS_HEADERS
Description: Comma separated list of allowed and exposed HTTP Headers for cross-origin requests
Default value: *

Variable: CORS_CREDENTIALS
Description: Whether credentials (i.e. Cookies or Authorization Header) are allowed for cross-origin requests Default value: false

Variable: CORS_MAXAGE
Description: Time in seconds of how long pre-flight request responses can be cached by clients
Default value: 3600

When VERIFIER_JAR_SIGNING_KEY is set to LoadFromKeystore the following environment variables must also be configured.

Variable: VERIFIER_JAR_SIGNING_KEY_KEYSTORE
Description: URL of the Keystore from which to load the Key to use for JAR signing
Examples: classpath:keystore.jks, file:///keystore.jks

Variable: VERIFIER_JAR_SIGNING_KEY_KEYSTORE_TYPE
Description: Type of the Keystore from which to load the Key to use for JAR signing
Examples: jks, pkcs12

Variable: VERIFIER_JAR_SIGNING_KEY_KEYSTORE_PASSWORD
Description: Password of the Keystore from which to load the Key to use for JAR signing

Variable: VERIFIER_JAR_SIGNING_KEY_ALIAS
Description: Alias of the Key to use for JAR signing, in the configured Keystore

Variable: VERIFIER_JAR_SIGNING_KEY_PASSWORD
Description: Password of the Key to use for JAR signing, in the configured Keystore

How to contribute

We welcome contributions to this project. To ensure that the process is smooth for everyone involved, follow the guidelines found in CONTRIBUTING.md.

License

License details

Copyright (c) 2023 European Commission

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.