diff --git a/.github/workflows/chart_release.yaml b/.github/workflows/chart_release.yaml index 749b6952..b427540d 100644 --- a/.github/workflows/chart_release.yaml +++ b/.github/workflows/chart_release.yaml @@ -18,7 +18,7 @@ jobs: git config user.name "$GITHUB_ACTOR" git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - name: Install Helm - uses: azure/setup-helm@v3 + uses: azure/setup-helm@v4 - name: Add bitnami repository run: helm repo add bitnami https://charts.bitnami.com/bitnami - name: Run chart-releaser diff --git a/charts/vc-authn-oidc/Chart.yaml b/charts/vc-authn-oidc/Chart.yaml index a7f619a2..e97884e3 100644 --- a/charts/vc-authn-oidc/Chart.yaml +++ b/charts/vc-authn-oidc/Chart.yaml @@ -6,25 +6,25 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.7 +version: 0.1.8 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "2.0.0" +appVersion: "2.0.1-rc0" -# Charts the vc-authn-oidc service depends on +# Charts the vc-authn-oidc service depends on dependencies: -- name: mongodb - version: "13.13.1" - repository: "https://charts.bitnami.com/bitnami" -- name: postgresql - version: 11.9.13 - repository: https://charts.bitnami.com/bitnami/ - condition: postgresql.enabled -- name: common - repository: "https://charts.bitnami.com/bitnami" - tags: - - bitnami-common - version: 2.x.x + - name: mongodb + version: "13.13.1" + repository: "https://charts.bitnami.com/bitnami" + - name: postgresql + version: 11.9.13 + repository: https://charts.bitnami.com/bitnami/ + condition: postgresql.enabled + - name: common + repository: "https://charts.bitnami.com/bitnami" + tags: + - bitnami-common + version: 2.x.x diff --git a/charts/vc-authn-oidc/README.md b/charts/vc-authn-oidc/README.md index 4e8431d3..9fc62759 100644 --- a/charts/vc-authn-oidc/README.md +++ b/charts/vc-authn-oidc/README.md @@ -1,6 +1,6 @@ # VC-AuthN OIDC -![Version: 0.1.7](https://img.shields.io/badge/Version-0.1.7-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.0.0](https://img.shields.io/badge/AppVersion-2.0.0-informational?style=flat-square) +![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.0.1-rc0](https://img.shields.io/badge/AppVersion-2.0.1-rc0-informational?style=flat-square) A Helm chart to deploy Verifiable Credential Identity Provider for OpenID Connect. @@ -39,14 +39,13 @@ The command deploys vc-authn-oidc with AcaPY agent, along with the MongoDB and P If necessary, vc-authn-oidc can be installed without AcaPY agent. This is accomplished by setting `acapy.enabled` to `false` and providing the necessary values to configure vc-authn-oidc to connect to an external AcaPy instance. - -| Name | Description | Value | -| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------- | -| `acapy.enabled` | Set to `false` to not deploy included AcaPy instance | `false` | -| `acapy.agentUrl` | Provide URL of the AcaPy agent instance || -| `acapy.adminUrl` | Provide URL of the AcaPy agent admin interface || -| `acapy.argfile.yml.wallet-name` | Provide the name of the wallet (`wallet-id`) || -| `acapy.existingSecret` | Provide the name of an existing secret containing the values for `adminApiKey` (otherwise set using `acapy.adminApiKey`), and `walletKey` || +| Name | Description | Value | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `acapy.enabled` | Set to `false` to not deploy included AcaPy instance | `false` | +| `acapy.agentUrl` | Provide URL of the AcaPy agent instance | | +| `acapy.adminUrl` | Provide URL of the AcaPy agent admin interface | | +| `acapy.argfile.yml.wallet-name` | Provide the name of the wallet (`wallet-id`) | | +| `acapy.existingSecret` | Provide the name of an existing secret containing the values for `adminApiKey` (otherwise set using `acapy.adminApiKey`), and `walletKey` | | To obtain the `controllerApiKey` to be used with the external AcaPy instance, run the following command: @@ -56,7 +55,6 @@ export WEBHOOK_API_KEY=$(kubectl get secret --namespace my-namespace my-release- echo $WEBHOOK_API_KEY ``` - ## Uninstalling the Chart To uninstall/delete the `my-release` deployment: @@ -86,7 +84,7 @@ kubectl delete secret,pvc --selector "app.kubernetes.io/instance"=my-release | `image.repository` | | `ghcr.io/bcgov/vc-authn-oidc` | | `image.pullPolicy` | | `IfNotPresent` | | `image.pullSecrets` | | `[]` | -| `image.tag` | Overrides the image tag which defaults to the chart appVersion. | `2.0.0-alpha2` | +| `image.tag` | Overrides the image tag which defaults to the chart appVersion. | `2.0.1-rc0` | | `ingressSuffix` | Domain suffix to be used for default hostpaths in ingress | `.apps.silver.devops.gov.bc.ca` | ### Controller Configuration @@ -94,7 +92,7 @@ kubectl delete secret,pvc --selector "app.kubernetes.io/instance"=my-release | Name | Description | Value | | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------- | | `acapyTenancyMode` | Agent tenancy mode, either `single` or `multi` | `single` | -| `setNonRevoked` | if True, the `non_revoked` attributed will be added to each of the present-proof request `requested_attribute` and `requested_predicate` with 'from=0' and'to=`int(time.time())` | `true` | +| `setNonRevoked` | if True, the `non_revoked` attributed will be added to each of the present-proof request `requested_attribute` and `requested_predicate` with 'from=0' and'to=`int(time.time())` | `true` | | `useOobPresentProof` | if True, the present-proof request will be provided as a an [out of band](https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband) invitation with a [present-proof](https://github.com/hyperledger/aries-rfcs/tree/main/features/0037-present-proof) request inside. If False, the present-proof request will be use the [service-decorator](https://github.com/hyperledger/aries-rfcs/tree/main/features/0056-service-decorator) | `false` | | `useOobLocalDIDService` | | `false` | | `controllerCameraRedirectUrl` | The redirect url can be a web link or the name of a template | `wallet_howto` | @@ -121,7 +119,7 @@ kubectl delete secret,pvc --selector "app.kubernetes.io/instance"=my-release | `resources.requests.memory` | The requested memory for the controller containers | `128Mi` | | `resources.requests.cpu` | The requested cpu for the controller containers | `10m` | | `replicaCount` | Number of controller replicas to deploy | `1` | -| `autoscaling.enabled` | Enable Horizontal POD autoscaling forthe controller | `true` | +| `autoscaling.enabled` | Enable Horizontal POD autoscaling forthe controller | `true` | | `autoscaling.minReplicas` | Minimum number of controller replicas | `1` | | `autoscaling.maxReplicas` | Maximum number of controller replicas | `2` | | `autoscaling.targetCPUUtilizationPercentage` | Target CPU utilization percentage | `80` | @@ -140,7 +138,7 @@ kubectl delete secret,pvc --selector "app.kubernetes.io/instance"=my-release | Name | Description | Value | | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------- | | `acapy.enabled` | Deploy AcaPy agent instance | `true` | -| `acapy.agentUrl` | Agent host, required if `enabled`` is `false`, otherwise ignored | `""` | +| `acapy.agentUrl` | Agent host, required if `enabled` is `false`, otherwise ignored | `""` | | `acapy.adminUrl` | Agent admin host, required if `enabled` is `false`, otherwise ignored | `""` | | `acapy.existingSecret` | Name of existing secret, required if `enabled` is `false`; Secret must contain `adminApiKey`, `walletKey`, and `webhookApiKey` keys. | `""` | | `acapy.agentSeed` | | `""` | @@ -185,7 +183,7 @@ Note: Secure values of the configuration are passed via equivalent environment v | `acapy.argfile.yml.public-invites` | Send invitations out using the public DID for the agent, and receive connection requests solicited by invitations which use the public DID. Default: false. | `true` | | `acapy.argfile.yml.read-only-ledger` | Sets ledger to read-only to prevent updates. Default: false. | `true` | | `acapy.argfile.yml.wallet-name` | Specifies the wallet name to be used by the agent. This is useful if your deployment has multiple wallets. | `askar-wallet` | -| `acapy.argfile.yml.wallet-storage-type` | Specifies the type of Indy wallet backend to use. Supported internal storage types are 'basic' (memory), 'default' (sqlite), and 'postgres_storage'. The default, if not specified, is 'default'. | `postgres_storage` | +| `acapy.argfile.yml.wallet-storage-type` | Specifies the type of Indy wallet backend to use. Supported internal storage types are 'basic' (memory), 'default' (sqlite), and 'postgres_storage'. The default, if not specified, is 'default'. | `postgres_storage` | | `acapy.argfile.yml.wallet-type` | Specifies the type of Indy wallet provider to use. Supported internal storage types are 'basic' (memory) and 'indy'. The default (if not specified) is 'basic'. | `askar` | | `acapy.argfile.yml.webhook-url` | Send webhooks containing internal state changes to the specified URL. Optional API key to be passed in the request body can be appended using a hash separator [#]. This is useful for a controller to monitor agent events and respond to those events using the admin API. If not specified, webhooks are not published by the agent. | `{{ include "vc-authn-oidc.host" . }}` | | `acapy.ledgers.yml` | | `{}` | @@ -201,14 +199,14 @@ Note: Secure values of the configuration are passed via equivalent environment v ### Wallet Storage Credentials -| Name | Description | Value | -| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | -| `acapy.walletStorageCredentials.json` | Raw json with database credentials. Overrides all other values including postgres subchart values. e.g.: '{"account":"postgres","password":"mysecretpassword","admin_account":"postgres","admin_password":"mysecretpassword"}' | `""` | -| `acapy.walletStorageCredentials.account` | Database account name. | `""` | -| `acapy.walletStorageCredentials.password` | Database password. | `""` | -| `acapy.walletStorageCredentials.admin_account` | Database account with CREATEDB role used to create additional databases per wallet. | `postgres` | -| `acapy.walletStorageCredentials.admin_password` | Database password for admin account. | `""` | -| `acapy.walletStorageCredentials.existingSecret` | Name of an existing secret containing 'database-user', 'database-password', 'admin-password' keys. | `""` | +| Name | Description | Value | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | +| `acapy.walletStorageCredentials.json` | Raw json with database credentials. Overrides all other values including postgres subchart values. e.g.: '{"account":"postgres","password":"mysecretpassword","admin_account":"postgres","admin_password":"mysecretpassword"}' | `""` | +| `acapy.walletStorageCredentials.account` | Database account name. | `""` | +| `acapy.walletStorageCredentials.password` | Database password. | `""` | +| `acapy.walletStorageCredentials.admin_account` | Database account with CREATEDB role used to create additional databases per wallet. | `postgres` | +| `acapy.walletStorageCredentials.admin_password` | Database password for admin account. | `""` | +| `acapy.walletStorageCredentials.existingSecret` | Name of an existing secret containing 'database-user', 'database-password', 'admin-password' keys. | `""` | ### Acapy tails persistence configuration @@ -224,19 +222,19 @@ Note: Secure values of the configuration are passed via equivalent environment v | Name | Description | Value | | --------------------------------- | --------------------------------------------- | ----------- | -| `acapy.resources.limits.memory` | The memory limit for the Acapy containers | `1000Mi` | -| `acapy.resources.limits.cpu` | The cpu limit for the Acapy containers | `1` | -| `acapy.resources.requests.memory` | The requested memory for the Acapy containers | `384Mi` | -| `acapy.resources.requests.cpu` | The requested cpu for the Acapy containers | `250m` | -| `acapy.podAnnotations` | Map of annotations to add to the acapy pods | `{}` | -| `acapy.podSecurityContext` | Pod Security Context | `{}` | -| `acapy.containerSecurityContext` | Container Security Context | `{}` | -| `acapy.service.type` | Kubernetes Service type | `ClusterIP` | -| `acapy.service.adminPort` | Port to expose for admin service | `8031` | -| `acapy.service.httpPort` | Port to expose for http service | `8030` | -| `acapy.affinity` | Affinity for acapy pods assignment | `{}` | -| `acapy.nodeSelector` | Node labels for acapy pods assignment | `{}` | -| `acapy.tolerations` | Tolerations for acapy pods assignment | `[]` | +| `acapy.resources.limits.memory` | The memory limit for the Acapy containers | `1000Mi` | +| `acapy.resources.limits.cpu` | The cpu limit for the Acapy containers | `1` | +| `acapy.resources.requests.memory` | The requested memory for the Acapy containers | `384Mi` | +| `acapy.resources.requests.cpu` | The requested cpu for the Acapy containers | `250m` | +| `acapy.podAnnotations` | Map of annotations to add to the acapy pods | `{}` | +| `acapy.podSecurityContext` | Pod Security Context | `{}` | +| `acapy.containerSecurityContext` | Container Security Context | `{}` | +| `acapy.service.type` | Kubernetes Service type | `ClusterIP` | +| `acapy.service.adminPort` | Port to expose for admin service | `8031` | +| `acapy.service.httpPort` | Port to expose for http service | `8030` | +| `acapy.affinity` | Affinity for acapy pods assignment | `{}` | +| `acapy.nodeSelector` | Node labels for acapy pods assignment | `{}` | +| `acapy.tolerations` | Tolerations for acapy pods assignment | `[]` | ### Acapy NetworkPolicy parameters @@ -308,9 +306,9 @@ Note: Secure values of the configuration are passed via equivalent environment v | `postgresql.primary.resources.requests.memory` | The requested memory for the PostgreSQL Primary containers | `1300Mi` | | `postgresql.primary.resources.requests.cpu` | The requested cpu for the PostgreSQL Primary containers | `300m` | | `postgresql.primary.service.ports.postgresql` | PostgreSQL service port | `5432` | -| `postgresql.primary.extendedConfiguration` | Extended PostgreSQL Primary configuration (appended to main or default configuration) | `max_connections = 500 -` | +| `postgresql.primary.extendedConfiguration` | Extended PostgreSQL Primary configuration (appended to main or default configuration) | `max_connections = 500` | | `postgresql-ha.enabled` | Deploy HA PostgreSQL chart. Not currently supported, provided for future use. | `false` | ----------------------------------------------- +--- + Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/charts/vc-authn-oidc/values.yaml b/charts/vc-authn-oidc/values.yaml index d9d57dea..17834f7c 100644 --- a/charts/vc-authn-oidc/values.yaml +++ b/charts/vc-authn-oidc/values.yaml @@ -1,11 +1,11 @@ ## @section Common Configuration ## -## @param nameOverride +## @param nameOverride nameOverride: "" ## @param fullnameOverride fullnameOverride: "" -## @param image.repository +## @param image.repository ## @param image.pullPolicy ## @param image.pullSecrets [array] ## @param image.tag Overrides the image tag which defaults to the chart appVersion. @@ -53,12 +53,14 @@ podAnnotations: {} ## @param podSecurityContext Pod Security Context ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ ## -podSecurityContext: {} +podSecurityContext: + {} # fsGroup: 2000 ## @param containerSecurityContext Container Security Context ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ ## -containerSecurityContext: {} +containerSecurityContext: + {} # capabilities: # drop: # - ALL @@ -79,7 +81,7 @@ networkPolicy: enabled: true namespaceSelector: [] ## Example: - # network.openshift.io/policy-group: ingress + # network.openshift.io/policy-group: ingress podSelector: {} ## Service configuration @@ -108,9 +110,9 @@ ingress: ## annotations: [] ## Example: - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - # route.openshift.io/termination: edge + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # route.openshift.io/termination: edge ## @param ingress.tls Enable TLS configuration for the host defined at ingress. tls: [] # - secretName: chart-example-tls @@ -150,7 +152,7 @@ autoscaling: minReplicas: 1 maxReplicas: 2 targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: '' + targetMemoryUtilizationPercentage: "" stabilizationWindowSeconds: 300 ## ServiceAccount configuration @@ -180,13 +182,12 @@ nodeSelector: {} ## tolerations: [] - ## @section Acapy Configuration ## acapy: ## @param acapy.enabled Deploy AcaPy agent instance enabled: true - ## @param acapy.agentUrl Agent host, required if `enabled`` is `false`, otherwise ignored + ## @param acapy.agentUrl Agent host, required if `enabled` is `false`, otherwise ignored agentUrl: "" ## @param acapy.adminUrl Agent admin host, required if `enabled` is `false`, otherwise ignored adminUrl: "" @@ -194,10 +195,10 @@ acapy: existingSecret: "" ## @param acapy.agentSeed agentSeed: "" - ## @param acapy.image.repository + ## @param acapy.image.repository ## @param acapy.image.pullPolicy ## @param acapy.image.pullSecrets [array] - ## @param acapy.image.tag + ## @param acapy.image.tag ## image: repository: ghcr.io/hyperledger/aries-cloudagent-python @@ -236,7 +237,7 @@ acapy: minReplicas: 1 maxReplicas: 100 targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: '' + targetMemoryUtilizationPercentage: "" stabilizationWindowSeconds: 300 ## @param acapy.labelOverride @@ -296,24 +297,24 @@ acapy: ledgers.yml: - id: BCovrinDev is_production: true - genesis_url: 'http://dev.bcovrin.vonx.io/genesis' + genesis_url: "http://dev.bcovrin.vonx.io/genesis" - id: BCovrinTest is_production: true - genesis_url: 'http://test.bcovrin.vonx.io/genesis' + genesis_url: "http://test.bcovrin.vonx.io/genesis" - id: SovrinStagingNet is_production: true - genesis_url: 'https://raw.githubusercontent.com/sovrin-foundation/sovrin/stable/sovrin/pool_transactions_sandbox_genesis' + genesis_url: "https://raw.githubusercontent.com/sovrin-foundation/sovrin/stable/sovrin/pool_transactions_sandbox_genesis" - id: CANdyDev is_production: true - genesis_url: 'https://raw.githubusercontent.com/ICCS-ISAC/dtrust-reconu/main/CANdy/dev/pool_transactions_genesis' + genesis_url: "https://raw.githubusercontent.com/ICCS-ISAC/dtrust-reconu/main/CANdy/dev/pool_transactions_genesis" - id: CANdyTest is_production: true is_write: true - genesis_url: 'https://raw.githubusercontent.com/ICCS-ISAC/dtrust-reconu/main/CANdy/test/pool_transactions_genesis' + genesis_url: "https://raw.githubusercontent.com/ICCS-ISAC/dtrust-reconu/main/CANdy/test/pool_transactions_genesis" ## @section Wallet Storage configuration - ## Specifies the storage configuration to use for the wallet. - ## This is required if you are for using 'postgres_storage' wallet 'storage type. + ## Specifies the storage configuration to use for the wallet. + ## This is required if you are for using 'postgres_storage' wallet 'storage type. ## For example, '{"url":"localhost:5432", "wallet_scheme":"MultiWalletSingleTable"}'. ## This configuration maps to the indy sdk postgres plugin (PostgresConfig). ## @@ -323,8 +324,8 @@ acapy: ## @param acapy.walletStorageConfig.wallet_scheme Wallet scheme. ## walletStorageConfig: - json: '' - url: '' + json: "" + url: "" max_connections: 10 wallet_scheme: DatabasePerWallet @@ -343,11 +344,11 @@ acapy: ## @param acapy.walletStorageCredentials.existingSecret Name of an existing secret containing 'database-user', 'database-password', 'admin-password' keys. ## walletStorageCredentials: - json: '' - account: '' - password: '' + json: "" + account: "" + password: "" admin_account: postgres - admin_password: '' + admin_password: "" existingSecret: "" ## @section Acapy tails persistence configuration persistence: @@ -382,7 +383,7 @@ acapy: ## resources: limits: - cpu: '1' + cpu: "1" memory: 1000Mi requests: cpu: 250m @@ -394,12 +395,14 @@ acapy: ## @param acapy.podSecurityContext Pod Security Context ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ ## - podSecurityContext: {} + podSecurityContext: + {} # fsGroup: 2000 ## @param acapy.containerSecurityContext Container Security Context ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ ## - containerSecurityContext: {} + containerSecurityContext: + {} # capabilities: # drop: # - ALL @@ -433,7 +436,7 @@ acapy: ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ ## tolerations: [] - + ## @section Acapy NetworkPolicy parameters ## Add networkpolicies @@ -535,8 +538,8 @@ mongodb: ## @param mongodb.auth.usernames List of custom users to be created during the initialization ## @param mongodb.auth.databases List of custom databases to be created during the initialization ## - usernames: ['vcauthn'] - databases: ['vcauthn'] + usernames: ["vcauthn"] + databases: ["vcauthn"] ## @param mongodb.commonLabels [array] Add labels to all the deployed resources (sub-charts are not considered). Evaluated as a template ## commonLabels: @@ -676,11 +679,12 @@ postgresql: service: ports: postgresql: 5432 - ## @param postgresql.primary.extendedConfiguration Extended PostgreSQL Primary configuration (appended to main or default configuration) - ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf - ## - extendedConfiguration: | - max_connections = 500 + ## @param postgresql.primary.extendedConfiguration Extended PostgreSQL Primary configuration (appended to main or default configuration) + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf + ## + primary: + extendedConfiguration: | + max_connections = 500 ## @param postgresql-ha.enabled Deploy HA PostgreSQL chart. Not currently supported, provided for future use. postgresql-ha: diff --git a/oidc-controller/api/authSessions/models.py b/oidc-controller/api/authSessions/models.py index c8fdc257..67e84c15 100644 --- a/oidc-controller/api/authSessions/models.py +++ b/oidc-controller/api/authSessions/models.py @@ -1,6 +1,6 @@ from datetime import datetime, timedelta from enum import StrEnum, auto -from typing import Dict +from typing import Dict, Optional from api.core.acapy.client import AcapyClient from api.core.models import UUIDModel @@ -25,6 +25,7 @@ class AuthSessionBase(BaseModel): request_parameters: dict pyop_auth_code: str response_url: str + presentation_request_msg: Optional[dict] = None class Config: allow_population_by_field_name = True diff --git a/oidc-controller/api/routers/oidc.py b/oidc-controller/api/routers/oidc.py index 7c7d044d..27407808 100644 --- a/oidc-controller/api/routers/oidc.py +++ b/oidc-controller/api/routers/oidc.py @@ -1,5 +1,6 @@ import base64 import io +import json from typing import cast import uuid from datetime import datetime @@ -18,6 +19,14 @@ from ..authSessions.crud import AuthSessionCreate, AuthSessionCRUD from ..authSessions.models import AuthSessionPatch, AuthSessionState from ..core.acapy.client import AcapyClient +from ..core.aries import ( + OOBServiceDecorator, + OutOfBandMessage, + OutOfBandPresentProofAttachment, + PresentationRequestMessage, + PresentProofv10Attachment, + ServiceDecorator, +) from ..core.config import settings from ..core.logger_util import log_debug from ..core.oidc import provider @@ -105,19 +114,71 @@ async def get_authorize(request: Request, db: Database = Depends(get_db)): # Create presentation_request to show on screen response = client.create_presentation_request(ver_config.generate_proof_request()) + pres_exch_dict = response.dict() + # Prepeare the presentation request + client = AcapyClient() + use_public_did = ( + not settings.USE_OOB_PRESENT_PROOF + ) and settings.USE_OOB_LOCAL_DID_SERVICE + wallet_did = client.get_wallet_did(public=use_public_did) + + byo_attachment = PresentProofv10Attachment.build( + pres_exch_dict["presentation_request"] + ) + + msg = None + if settings.USE_OOB_PRESENT_PROOF: + if settings.USE_OOB_LOCAL_DID_SERVICE: + oob_s_d = OOBServiceDecorator( + service_endpoint=client.service_endpoint, + recipient_keys=[wallet_did.verkey], + ).dict() + else: + wallet_did = client.get_wallet_did(public=True) + oob_s_d = wallet_did.verkey + + msg = PresentationRequestMessage( + id=pres_exch_dict["thread_id"], + request=[byo_attachment], + ) + oob_msg = OutOfBandMessage( + request_attachments=[ + OutOfBandPresentProofAttachment( + id="request-0", + data={"json": msg.dict(by_alias=True)}, + ) + ], + id=pres_exch_dict["thread_id"], + services=[oob_s_d], + ) + msg_contents = oob_msg + else: + s_d = ServiceDecorator( + service_endpoint=client.service_endpoint, recipient_keys=[wallet_did.verkey] + ) + msg = PresentationRequestMessage( + id=pres_exch_dict["thread_id"], + request=[byo_attachment], + service=s_d, + ) + msg_contents = msg + + + # Create and save OIDC AuthSession new_auth_session = AuthSessionCreate( response_url=authn_response.request(auth_req["redirect_uri"]), pyop_auth_code=authn_response["code"], request_parameters=model.to_dict(), ver_config_id=ver_config_id, pres_exch_id=response.presentation_exchange_id, - presentation_exchange=response.dict(), + presentation_exchange=pres_exch_dict, + presentation_request_msg=msg_contents.dict(by_alias=True), ) - - # save OIDC AuthSession auth_session = await AuthSessionCRUD(db).create(new_auth_session) + formated_msg = json.dumps(msg_contents.dict(by_alias=True)) + # QR CONTENTS controller_host = settings.CONTROLLER_URL url_to_message = ( @@ -129,6 +190,12 @@ async def get_authorize(request: Request, db: Database = Depends(get_db)): image_contents = base64.b64encode(buff.getvalue()).decode("utf-8") callback_url = f"""{controller_host}{AuthorizeCallbackUri}?pid={auth_session.id}""" + # BC Wallet deep link + # base64 encode the formated_msg + base64_msg = base64.b64encode(formated_msg.encode("utf-8")).decode("utf-8") + wallet_deep_link = f"bcwallet://aries_proof-request?c_i={base64_msg}" + + # This is the payload to send to the template data = { "image_contents": image_contents, @@ -139,6 +206,7 @@ async def get_authorize(request: Request, db: Database = Depends(get_db)): "pid": auth_session.id, "controller_host": controller_host, "challenge_poll_uri": ChallengePollUri, + "wallet_deep_link": wallet_deep_link, } # Prepare the template diff --git a/oidc-controller/api/routers/presentation_request.py b/oidc-controller/api/routers/presentation_request.py index 055455a2..23a751a7 100644 --- a/oidc-controller/api/routers/presentation_request.py +++ b/oidc-controller/api/routers/presentation_request.py @@ -7,15 +7,7 @@ from ..authSessions.crud import AuthSessionCRUD from ..authSessions.models import AuthSession, AuthSessionState -from ..core.acapy.client import AcapyClient -from ..core.aries import ( - OOBServiceDecorator, - OutOfBandMessage, - OutOfBandPresentProofAttachment, - PresentationRequestMessage, - PresentProofv10Attachment, - ServiceDecorator, -) + from ..core.config import settings from ..routers.socketio import (sio, connections_reload) from ..db.session import get_db @@ -65,51 +57,7 @@ async def send_connectionless_proof_req( await AuthSessionCRUD(db).patch(auth_session.id, auth_session) await sio.emit('status', {'status': 'pending'}, to=sid) - client = AcapyClient() - use_public_did = ( - not settings.USE_OOB_PRESENT_PROOF - ) and settings.USE_OOB_LOCAL_DID_SERVICE - wallet_did = client.get_wallet_did(public=use_public_did) - - byo_attachment = PresentProofv10Attachment.build( - auth_session.presentation_exchange["presentation_request"] - ) + msg = auth_session.presentation_request_msg - msg = None - if settings.USE_OOB_PRESENT_PROOF: - if settings.USE_OOB_LOCAL_DID_SERVICE: - oob_s_d = OOBServiceDecorator( - service_endpoint=client.service_endpoint, - recipient_keys=[wallet_did.verkey], - ).dict() - else: - wallet_did = client.get_wallet_did(public=True) - oob_s_d = wallet_did.verkey - - msg = PresentationRequestMessage( - id=auth_session.presentation_exchange["thread_id"], - request=[byo_attachment], - ) - oob_msg = OutOfBandMessage( - request_attachments=[ - OutOfBandPresentProofAttachment( - id="request-0", - data={"json": msg.dict(by_alias=True)}, - ) - ], - id=auth_session.presentation_exchange["thread_id"], - services=[oob_s_d], - ) - msg_contents = oob_msg - else: - s_d = ServiceDecorator( - service_endpoint=client.service_endpoint, recipient_keys=[wallet_did.verkey] - ) - msg = PresentationRequestMessage( - id=auth_session.presentation_exchange["thread_id"], - request=[byo_attachment], - service=s_d, - ) - msg_contents = msg - logger.debug(msg_contents.dict(by_alias=True)) - return JSONResponse(msg_contents.dict(by_alias=True)) + logger.debug(msg) + return JSONResponse(msg) diff --git a/oidc-controller/api/templates/verified_credentials.html b/oidc-controller/api/templates/verified_credentials.html index 0553e5a9..3e9d238a 100644 --- a/oidc-controller/api/templates/verified_credentials.html +++ b/oidc-controller/api/templates/verified_credentials.html @@ -16,6 +16,7 @@ .container { text-align: center; border-radius: 0.5rem; + border:none; box-shadow: 2px 2px 3px 3px #dedede; } .content { @@ -41,10 +42,19 @@ width: 18rem; margin-left: 3rem; } + .header-share { + display: grid; + grid-template-columns: 5rem 1fr; + width: 22rem; + margin-top: 1.5rem; + margin-bottom: 1.75rem; + } .qr-code-desc { text-align: left; } .qr-code { + display: flex; + justify-content: center; position: relative; margin: 2rem 0 2rem -0.5rem; } @@ -79,7 +89,7 @@ background-color: white; height: 100%; width: 19rem; - margin-left: 2.8rem; + /* margin-left: 2.8rem; */ align-items: center; justify-content: center; z-index: 1; @@ -144,6 +154,10 @@ padding: 1rem 2rem 1rem 0.5rem; margin-left: 1.5rem; } + .header-desc.expired.expired-deep-link { + margin-left: 0; + width: 100%; + } .header-desc.pending svg { width: 2rem; height: 2rem; @@ -158,6 +172,9 @@ .header-desc.expired { background-color: #f0f0f0; } + .header-desc.expired-deep-link { + margin-bottom: 1.5rem; + } .header-desc.failed { background-color: #f2dede; } @@ -188,21 +205,79 @@ .text-link label { display: block; } + + /* BC Gov style buttons */ + .BC-Gov-PrimaryButton, + .BC-Gov-SecondaryButton { + text-align: center; + text-decoration: none; + display: block; + font-size: 18px; + font-weight: 700; + letter-spacing: 1px; + cursor: pointer; + border-radius: 4px; + } + .BC-Gov-PrimaryButton:hover, + .BC-Gov-SecondaryButton:hover { + text-decoration: underline; + opacity: 0.80; + } + .BC-Gov-PrimaryButton:focus, + .BC-Gov-SecondaryButton:focus{ + outline: 4px solid #3B99FC; + outline-offset: 1px; + } + .BC-Gov-PrimaryButton { + background-color: #003366; + border: none; + color: white; + padding: 12px 32px; + margin-bottom: 1.5rem; + margin-top: 1.5rem; + } + .BC-Gov-PrimaryButton:active { + opacity: 1; + } + .BC-Gov-SecondaryButton { + background: none; + border: 2px solid #003366; + padding: 10px 30px; + color: #003366; + margin-bottom: 1.5rem; + } + .BC-Gov-SecondaryButton:hover { + background-color: #003366; + color: #FFFFFF; + } + .BC-Gov-SecondaryButton:active { + opacity: 1; + } + .BC-Gov-PrimaryButton-disabled { + display: block; + background-color: #003366; + opacity: 0.3; + border: none; + color: white; + padding: 12px 32px; + cursor: not-allowed; + margin-bottom: 1.5rem; + margin-top: 1.5rem; + } + + /* Mobile device */ + .mobile-device{ + display: none; + }
{{add_asset("BCID_H_rgb_rev.svg")}}
-

Scan with a Digital Wallet

- -
-
{{add_asset("hand-qrcode.svg")}}
-
- Scanning this QR code will send you a request to share your - information -
-
+ +

Scan with a Digital Wallet

+

Continue with:

{{add_asset("circle-check.svg")}}
@@ -211,42 +286,33 @@

Scan with a Digital Wallet

-
+
{{add_asset("circle-x.svg")}}
Proof not accepted.
- Please try again. + Please try again.
- -
+ +
{{add_asset("expired.svg")}}
Proof has expired.
- Refresh QR code. + Refresh Proof.
- +
-
{{add_asset("circle-x.svg")}}
-
- Proof declined -
- Try again. -
-
- +
{{add_asset("circle-x.svg")}}
+
+ Proof declined +
+ Try again. +
+
+
{{add_asset("hourglass.svg")}}
@@ -254,25 +320,62 @@

Scan with a Digital Wallet

-
- +
+
QR code scanned
- -
-
QR code scanned
+
{{add_asset("dashed-border.svg")}}
+ {{image_contents}}
-
{{add_asset("dashed-border.svg")}}
- {{image_contents}}
@@ -286,25 +389,59 @@

Scan with a Digital Wallet

>{{url_to_message}}
-
+

Don't have a digital wallet? -

- Download BC Wallet +

+

+ Download the BC Wallet app + +