From 4d977308d14358616a0577834714bbad290f9729 Mon Sep 17 00:00:00 2001 From: Yurii Shynbuiev - IOHK Date: Wed, 3 Jul 2024 15:01:54 +0700 Subject: [PATCH] feat: make a nonce in a token response optional (#8) Signed-off-by: Yurii Shynbuiev --- README.md | 39 +++++++++++-------- .../identus/keycloak/IdentusClient.java | 9 +++-- .../keycloak/OID4VCITokenEndpoint.java | 10 +++-- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index ffe6db2..c58f565 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ # Overview -This repository provides a Keycloak Plugin that extends Keycloak's functionality to handle Self-Sovereign Identity (SSI) tasks, +This repository provides a Keycloak Plugin that extends Keycloak's functionality to handle Self-Sovereign Identity (SSI) +tasks, including OpenID for verifiable credential issuance. # Getting started @@ -16,8 +17,10 @@ including OpenID for verifiable credential issuance. The plugin is available as a pre-bundled Docker image. This image includes Keycloak and the plugin enabled for basic use cases. -For a more complex setup, the JAR file published in the Maven repository should be used to build a custom Keycloak image. -The docker-compose configuration below allows spinning up a basic Keycloak instance with the plugin enabled as part of the Identus cloud agent stack. +For a more complex setup, the JAR file published in the Maven repository should be used to build a custom Keycloak +image. +The docker-compose configuration below allows spinning up a basic Keycloak instance with the plugin enabled as part of +the Identus cloud agent stack. ```yaml services: @@ -68,8 +71,10 @@ for customization using JAR providers. ## Using published JAR -Each plugin is available individually on [Github maven packages](https://github.com/orgs/hyperledger/packages?repo_name=identus-keycloak-plugins), -for easy integration with your build process and fine-grained control over which plugins are included when customizing Keycloak. +Each plugin is available individually +on [Github maven packages](https://github.com/orgs/hyperledger/packages?repo_name=identus-keycloak-plugins), +for easy integration with your build process and fine-grained control over which plugins are included when customizing +Keycloak. Please refer to the official [Keycloak documentation](https://www.keycloak.org/server/containers) for customization using JAR providers. @@ -78,25 +83,27 @@ for customization using JAR providers. ## `identus-keycloak-oid4vci` -Extends Keycloak for integration with Hyperledger Identus Cloud Agent in [OID4VCI](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html) flow. +Extends Keycloak for integration with Hyperledger Identus Cloud Agent +in [OID4VCI](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html) flow. The Keycloak instance to use this is the Issuer Authorization Server where the plugin takes care of the OpenID extension in the issuance flow. The plugin supports the Authorization Endpoint and Token Endpoint according to the specification. -Additionally, the plugin communicates with the cloud agent during holder authorization to coordinate the issuance session. +Additionally, the plugin communicates with the cloud agent during holder authorization to coordinate the issuance +session. ### Features - [Authorization code flow](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-authorization-code-flow) - - _AuthorizationRequest_ supported parameters - - [`issuer_state`](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#section-5.1.3-2.3) - - _TokenResponse_ supported parameters - - [`c_nonce`](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#section-6.2-4.1) - - [`c_nonce_expires_in`](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#section-6.2-4.2) + - _AuthorizationRequest_ supported parameters + - [`issuer_state`](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#section-5.1.3-2.3) + - _TokenResponse_ supported parameters + - [`c_nonce`](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#section-6.2-4.1) + - [`c_nonce_expires_in`](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#section-6.2-4.2) - [Pre-authorized-code flow](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-pre-authorized-code-flow) - - Not yet supported + - Not yet supported ### Environment Variables -|Name|Description| -|-|-| -|`IDENTUS_URL`|URL of the Identus Cloud Agent to coordinate the issuance session.| +| Name | Description | +|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| +| `IDENTUS_URL` | URL of the Identus Cloud Agent to coordinate the issuance session. If the variable is not set, the TokenResponse will not contain the `nonce` parameter. | diff --git a/src/main/java/org/hyperledger/identus/keycloak/IdentusClient.java b/src/main/java/org/hyperledger/identus/keycloak/IdentusClient.java index 726e08a..c45944c 100644 --- a/src/main/java/org/hyperledger/identus/keycloak/IdentusClient.java +++ b/src/main/java/org/hyperledger/identus/keycloak/IdentusClient.java @@ -17,17 +17,20 @@ public class IdentusClient { private static final Logger logger = Logger.getLogger(IdentusClient.class); - private final String identusUrl; + private final String identusUrl = System.getenv("IDENTUS_URL"); private final Supplier httpClient = IdentusClient::newCloseableHttpClient; public IdentusClient() { - this.identusUrl = System.getenv("IDENTUS_URL"); if (this.identusUrl == null) { - throw new NullPointerException("The URL of identus client is null. The IDENTUS_URL environment variable is not set."); + logger.warn("The URL of the Identus Cloud Agent client is null. The IDENTUS_URL environment variable is not set. The token response will not contain a nonce."); } } + public Boolean isIdentusUrlSet() { + return this.identusUrl != null; + } + public static CloseableHttpClient newCloseableHttpClient() { return HttpClientBuilder.create().build(); } diff --git a/src/main/java/org/hyperledger/identus/keycloak/OID4VCITokenEndpoint.java b/src/main/java/org/hyperledger/identus/keycloak/OID4VCITokenEndpoint.java index 6f4f585..7bf50a9 100644 --- a/src/main/java/org/hyperledger/identus/keycloak/OID4VCITokenEndpoint.java +++ b/src/main/java/org/hyperledger/identus/keycloak/OID4VCITokenEndpoint.java @@ -36,10 +36,12 @@ public Response createTokenResponse(UserModel user, UserSessionModel userSession Response originalResponse = super.createTokenResponse(user, userSession, clientSessionCtx, scopeParam, true, clientPolicyContextGenerator); AccessTokenResponse responseEntity = (AccessTokenResponse) originalResponse.getEntity(); - String token = responseEntity.getToken(); - NonceResponse nonceResponse = identusClient.getNonce(token, issuerState); - responseEntity.setOtherClaims(OID4VCIConstants.C_NONCE, nonceResponse.getNonce()); - responseEntity.setOtherClaims(OID4VCIConstants.C_NONCE_EXPIRE, nonceResponse.getNonceExpiresIn()); + if (identusClient.isIdentusUrlSet()) { + String token = responseEntity.getToken(); + NonceResponse nonceResponse = identusClient.getNonce(token, issuerState); + responseEntity.setOtherClaims(OID4VCIConstants.C_NONCE, nonceResponse.getNonce()); + responseEntity.setOtherClaims(OID4VCIConstants.C_NONCE_EXPIRE, nonceResponse.getNonceExpiresIn()); + } return Response.fromResponse(originalResponse) .entity(responseEntity) .build();