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 + +