diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 526478f8..8599d6ba 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -100,7 +100,7 @@ services: - vc_auth aca-py: - image: ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.12.1 + image: ghcr.io/hyperledger/aries-cloudagent-python:py3.12-1.0.0rc5 environment: - ACAPY_LABEL=${AGENT_NAME} - ACAPY_ENDPOINT=${AGENT_ENDPOINT} diff --git a/docker/manage b/docker/manage index 577a2616..d05b3ae3 100755 --- a/docker/manage +++ b/docker/manage @@ -181,7 +181,7 @@ configureEnvironment() { #controller app settings export SET_NON_REVOKED="True" - export USE_OOB_PRESENT_PROOF=${USE_OOB_PRESENT_PROOF:-"false"} + export USE_OOB_PRESENT_PROOF=${USE_OOB_PRESENT_PROOF:-"true"} export USE_OOB_LOCAL_DID_SERVICE=${USE_OOB_LOCAL_DID_SERVICE:-"true"} export USE_URL_DEEP_LINK=${USE_URL_DEEP_LINK:-"false"} export WALLET_DEEP_LINK_PREFIX=${WALLET_DEEP_LINK_PREFIX:-"bcwallet://aries_proof-request"} diff --git a/oidc-controller/api/authSessions/models.py b/oidc-controller/api/authSessions/models.py index 38a2e23e..7bc001e7 100644 --- a/oidc-controller/api/authSessions/models.py +++ b/oidc-controller/api/authSessions/models.py @@ -1,8 +1,7 @@ from datetime import datetime, timedelta from enum import StrEnum, auto -from typing import Dict, Optional +from typing import Optional -from api.core.acapy.client import AcapyClient from api.core.models import UUIDModel from pydantic import BaseModel, ConfigDict, Field @@ -35,11 +34,7 @@ class AuthSessionBase(BaseModel): class AuthSession(AuthSessionBase, UUIDModel): proof_status: AuthSessionState = Field(default=AuthSessionState.NOT_STARTED) - - @property - def presentation_exchange(self) -> Dict: - client = AcapyClient() - return client.get_presentation_request(self.pres_exch_id) + presentation_exchange: dict | None = Field(default_factory=dict) class AuthSessionCreate(AuthSessionBase): @@ -48,4 +43,5 @@ class AuthSessionCreate(AuthSessionBase): class AuthSessionPatch(AuthSessionBase): proof_status: AuthSessionState = Field(default=AuthSessionState.PENDING) + presentation_exchange: dict = Field(default_factory=dict) pass diff --git a/oidc-controller/api/core/acapy/client.py b/oidc-controller/api/core/acapy/client.py index f45b8f46..42fa0a3c 100644 --- a/oidc-controller/api/core/acapy/client.py +++ b/oidc-controller/api/core/acapy/client.py @@ -14,8 +14,8 @@ WALLET_DID_URI = "/wallet/did" PUBLIC_WALLET_DID_URI = "/wallet/did/public" -CREATE_PRESENTATION_REQUEST_URL = "/present-proof/create-request" -PRESENT_PROOF_RECORDS = "/present-proof/records" +CREATE_PRESENTATION_REQUEST_URL = "/present-proof-2.0/create-request" +PRESENT_PROOF_RECORDS = "/present-proof-2.0/records" OOB_CREATE_INVITATION = "/out-of-band/create-invitation" @@ -43,7 +43,9 @@ def create_presentation_request( self, presentation_request_configuration: dict ) -> CreatePresentationResponse: logger.debug(">>> create_presentation_request") - present_proof_payload = {"proof_request": presentation_request_configuration} + present_proof_payload = { + "presentation_request": {"indy": presentation_request_configuration} + } resp_raw = requests.post( self.acapy_host + CREATE_PRESENTATION_REQUEST_URL, @@ -79,24 +81,6 @@ def get_presentation_request(self, presentation_exchange_id: Union[UUID, str]): logger.debug(f"<<< get_presentation_request -> {resp}") return resp - def verify_presentation(self, presentation_exchange_id: Union[UUID, str]): - logger.debug(">>> verify_presentation") - - resp_raw = requests.post( - self.acapy_host - + PRESENT_PROOF_RECORDS - + "/" - + str(presentation_exchange_id) - + "/verify-presentation", - headers=self.agent_config.get_headers(), - ) - assert resp_raw.status_code == 200, resp_raw.content - - resp = json.loads(resp_raw.content) - - logger.debug(f"<<< verify_presentation -> {resp}") - return resp - def get_wallet_did(self, public=False) -> WalletDid: logger.debug(">>> get_wallet_did") url = None @@ -134,7 +118,7 @@ def oob_create_invitation( create_invitation_payload = { "attachments": [ { - "id": presentation_exchange["presentation_exchange_id"], + "id": presentation_exchange["pres_ex_id"], "type": "present-proof", "data": {"json": presentation_exchange}, } diff --git a/oidc-controller/api/core/acapy/models.py b/oidc-controller/api/core/acapy/models.py index 8aa9a62e..f85f5199 100644 --- a/oidc-controller/api/core/acapy/models.py +++ b/oidc-controller/api/core/acapy/models.py @@ -16,8 +16,8 @@ class WalletDidPublicResponse(BaseModel): class CreatePresentationResponse(BaseModel): thread_id: str - presentation_exchange_id: str - presentation_request: Dict + pres_ex_id: str + pres_request: Dict class OobCreateInvitationResponse(BaseModel): diff --git a/oidc-controller/api/core/acapy/tests/test_client.py b/oidc-controller/api/core/acapy/tests/test_client.py index 8fc8078e..19794eb2 100644 --- a/oidc-controller/api/core/acapy/tests/test_client.py +++ b/oidc-controller/api/core/acapy/tests/test_client.py @@ -144,48 +144,6 @@ async def test_get_presentation_throws_assertion_error_for_non_200_response_from assert e is not None -@pytest.mark.asyncio -async def test_verify_presentation_returns_sucessfully_with_valid_data(requests_mock): - requests_mock.post( - settings.ACAPY_ADMIN_URL - + PRESENT_PROOF_RECORDS - + "/" - + "1234-567890" - + "/verify-presentation", - headers={}, - json={"result": "success"}, - status_code=200, - ) - - client = AcapyClient() - client.agent_config.get_headers = mock.MagicMock(return_value={"x-api-key": ""}) - verification = client.verify_presentation("1234-567890") - assert verification is not None - - -@pytest.mark.asyncio -async def test_verify_presentation_throws_assertion_error_for_non_200_resp_from_acapy( - requests_mock, -): - requests_mock.post( - settings.ACAPY_ADMIN_URL - + PRESENT_PROOF_RECORDS - + "/" - + "1234-567890" - + "/verify-presentation", - headers={}, - json={"result": "success"}, - status_code=400, - ) - - client = AcapyClient() - client.agent_config.get_headers = mock.MagicMock(return_value={"x-api-key": ""}) - try: - client.verify_presentation("1234-567890") - except AssertionError as e: - assert e is not None - - @pytest.mark.asyncio async def test_get_wallet_did_public_returns_sucessfully_on_public_url_and_simple_resp( requests_mock, diff --git a/oidc-controller/api/core/aries/__init__.py b/oidc-controller/api/core/aries/__init__.py index 28d321c5..935f52ff 100644 --- a/oidc-controller/api/core/aries/__init__.py +++ b/oidc-controller/api/core/aries/__init__.py @@ -1,6 +1,6 @@ # flake8: noqa -from .present_proof_attachment import PresentProofv10Attachment +from .present_proof_attachment import PresentProofv20Attachment from .service_decorator import ServiceDecorator, OOBServiceDecorator from .present_proof_presentation import PresentationRequestMessage diff --git a/oidc-controller/api/core/aries/present_proof_attachment.py b/oidc-controller/api/core/aries/present_proof_attachment.py index d27c6c23..b54cebb1 100644 --- a/oidc-controller/api/core/aries/present_proof_attachment.py +++ b/oidc-controller/api/core/aries/present_proof_attachment.py @@ -1,24 +1,9 @@ -import json -import base64 - from typing import Dict from pydantic import BaseModel, Field -class PresentProofv10Attachment(BaseModel): - # https://github.com/hyperledger/aries-rfcs/blob/main/features/0037-present-proof/README.md#request-presentation +class PresentProofv20Attachment(BaseModel): + # https://github.com/hyperledger/aries-rfcs/tree/eace815c3e8598d4a8dd7881d8c731fdb2bcc0aa/features/0454-present-proof-v2 id: str = Field(default="libindy-request-presentation-0", alias="@id") mime_type: str = Field(default="application/json", alias="mime-type") data: Dict - - @classmethod - def build( - cls, presentation_request - ) -> "PresentProofv10Attachment": # bundle everything needed for the QR code - return cls( - data={ - "base64": base64.b64encode( - json.dumps(presentation_request).encode("ascii") - ).decode("ascii") - } - ) diff --git a/oidc-controller/api/core/aries/present_proof_presentation.py b/oidc-controller/api/core/aries/present_proof_presentation.py index 95b01b5e..ffe49b0c 100644 --- a/oidc-controller/api/core/aries/present_proof_presentation.py +++ b/oidc-controller/api/core/aries/present_proof_presentation.py @@ -1,19 +1,20 @@ import json import base64 -from typing import Optional, List +from typing import Optional, List, Dict from pydantic import BaseModel, ConfigDict, Field -from api.core.aries import PresentProofv10Attachment, ServiceDecorator +from api.core.aries import PresentProofv20Attachment, ServiceDecorator class PresentationRequestMessage(BaseModel): # https://github.com/hyperledger/aries-rfcs/blob/main/features/0037-present-proof/README.md#presentation id: str = Field(alias="@id") type: str = Field( - "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/request-presentation", + "https://didcomm.org/present-proof/2.0/request-presentation", alias="@type", ) - request: List[PresentProofv10Attachment] = Field( + formats: List[Dict] + request: List[PresentProofv20Attachment] = Field( alias="request_presentations~attach" ) comment: Optional[str] = None diff --git a/oidc-controller/api/core/oidc/issue_token_service.py b/oidc-controller/api/core/oidc/issue_token_service.py index 2feec8ea..9463a2b4 100644 --- a/oidc-controller/api/core/oidc/issue_token_service.py +++ b/oidc-controller/api/core/oidc/issue_token_service.py @@ -51,23 +51,26 @@ def get_claims( presentation_claims: Dict[str, Claim] = {} logger.info( - auth_session.presentation_exchange["presentation_request"][ - "requested_attributes" - ] + "pres_request_token" + + str( + auth_session.presentation_exchange["pres_request"]["indy"][ + "requested_attributes" + ] + ) ) referent: str requested_attr: ReqAttr try: for referent, requested_attrdict in auth_session.presentation_exchange[ - "presentation_request" - ]["requested_attributes"].items(): + "pres_request" + ]["indy"]["requested_attributes"].items(): requested_attr = ReqAttr(**requested_attrdict) logger.debug( f"Processing referent: {referent}, requested_attr: {requested_attr}" ) revealed_attrs: Dict[str, RevealedAttribute] = ( - auth_session.presentation_exchange["presentation"][ + auth_session.presentation_exchange["pres"]["indy"][ "requested_proof" ]["revealed_attr_groups"] ) diff --git a/oidc-controller/api/core/oidc/tests/__mocks__.py b/oidc-controller/api/core/oidc/tests/__mocks__.py index 9a859c3b..2aec37ac 100644 --- a/oidc-controller/api/core/oidc/tests/__mocks__.py +++ b/oidc-controller/api/core/oidc/tests/__mocks__.py @@ -3,86 +3,1326 @@ from api.verificationConfigs.models import VerificationConfig, VerificationProofRequest from api.authSessions.models import AuthSession +# Presentation returned from the debug webhook presentation = { - "thread_id": "428ab5dc-185f-40ba-8714-498c79b822f3", - "created_at": "2023-09-15T17:49:16.397954Z", + "state": "done", + "created_at": "2024-07-03T23:19:34.611906Z", + "updated_at": "2024-07-03T23:19:46.309431Z", + "trace": False, + "pres_ex_id": "ea6b9907-34d7-45df-9b2c-ebf0b17606e3", + "thread_id": "5cc7ac29-1b6c-404a-9820-cb52348f5cd8", + "initiator": "self", "role": "verifier", - "auto_present": False, - "presentation_exchange_id": "ccaac3c5-1606-44fb-ade3-33937dfb6dca", - "presentation_request": { - "nonce": "633368193772519315256591", - "name": "proof_requested", - "version": "0.0.1", - "requested_attributes": "invalid", # Add test requested attributes - "requested_predicates": {}, - }, - "presentation": { - "proof": { - "proofs": [ - { - "primary_proof": { - "eq_proof": { - "revealed_attrs": { - "email": "73814602767252868561268261832462872577293109184327908660400248444458427915643" + # Since we only rely on the by_format entry from the webhook we will exclude the pres_request and pres entries + "pres": {}, + "pres_request": {}, + "by_format": { + "pres_request": { + "indy": { + "name": "proof_requested", + "version": "0.0.1", + "requested_attributes": { + "req_attr_0": { + "names": ["given_names", "family_name", "country"], + "restrictions": [ + { + "schema_name": "Person", + "issuer_did": "L6ASjmDDbDH7yPL1t2yFj9", }, - "a_prime": "40809417934849907123261471333411809633354074436405510819719547561843004255793023387498104889708571270607131703938696756407487467873368373775514806534499374680059274765067020721416649641170535056242622419292879011504372419414431627060123535951854477609020119038446707071877530649018798857842493513975477809431501443034563297114458359206476293934461316378865994820249592804467758433904174100097026785285885805688715928578812499534293751388422584754995155726212908115142236221995953756086868367889189436621196564054394071524712971126196703085030819194540892286515361206473918715176334283198231106756804249201321110676817", - "e": "132166309846004002298968329630750626534906193461199076364226183288855464715230907038994149984215600411276690314987056469395087923423376034", - "v": "389852336354596234620050863642411241608940316153319185423050526707483503655636070718528707360249027781424214465818771183857876571898645233712049550065615437328753383559647676180932006072233802815800996667626559757294734656704881893512658110558847026240354780006408044914149694965180223127754340423475416000940696265773581100989216553579233198807834530514088943560794612627439000580021272527304012796141460444099028132444095750454921031441117671745673457339631909515144154149520136598843334638440138229207476684776682052027672414220327439299122271829090948693982983191662066627130404544959976637513561609461174550463471636750546362339385232864872096796748538286120598703640917737216094473317639418313144992206875604615452306826430748790105881684965109026881701380306409317275248915954859998470708379642658766566479932465684746033865495941061980422316943701392367332573162799073428328950386460662125690364635698421614848860", - "m": { - "time": "11896542455624181868867605459032062290636202825612483735571300567506766112289589216989585608752835036405824270689163034684130257627062069669940002269643613585904726141499206139998", - "master_secret": "11978669714570126125906674715703732098298259897696576462078203241042378591463388624826815153862705227192729264588296043944542578244619153416802465506231069348686312732305137579470", + { + "schema_name": "Person", + "issuer_did": "QEquAHkM35w4XVT3Ku5yat", }, - "m2": "5273201069177175286302918970464632772021241766353736934881903190951819578898991714048991692651562372414552361008106867369251847950990157935703897032904209115054769991615534757984", - }, - "ge_proofs": [], + { + "schema_name": "Person", + "issuer_did": "M6dhuFj5UwbhWkSLmvYSPc", + }, + ], + "non_revoked": {"from": 1720048774, "to": 1720048774}, } - } - ], - "aggregated_proof": { - "c_hash": "8135055767072243139738404741550925116429855319200452769474586673630216912237", - "c_list": [[1]], # Not complete data - }, - }, - "requested_proof": { - "revealed_attrs": {}, - "revealed_attr_groups": "invalid", # Add test revealed_attr_groups - "self_attested_attrs": {}, - "unrevealed_attrs": {}, - "predicates": {}, - }, - "identifiers": [ - { - "schema_id": "MTYqmTBoLT7KLP5RNfgK3b:2:verified-email:1.2.3", - "cred_def_id": "MTYqmTBoLT7KLP5RNfgK3b:3:CL:160342:default", + }, + "requested_predicates": {}, + "nonce": "482986012434214017125155", } - ], - }, - "verified": "true", - "state": "verified", - "presentation_request_dict": { - "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/request-presentation", - "@id": "428ab5dc-185f-40ba-8714-498c79b822f3", - "request_presentations~attach": [ - { - "@id": "libindy-request-presentation-0", - "mime-type": "application/json", - "data": { - "base64": "eyJuYW1lIjogInByb29mX3JlcXVlc3RlZCIsICJ2ZXJzaW9uIjogIjAuMC4xIiwgInJlcXVlc3RlZF9hdHRyaWJ1dGVzIjogeyJyZXFfYXR0cl8wIjogeyJuYW1lcyI6IFsiZW1haWwiXSwgInJlc3RyaWN0aW9ucyI6IFt7InNjaGVtYV9uYW1lIjogInZlcmlmaWVkLWVtYWlsIiwgImlzc3Vlcl9kaWQiOiAiTVRZcW1UQm9MVDdLTFA1Uk5mZ0szYiJ9XSwgIm5vbl9yZXZva2VkIjogeyJmcm9tIjogMTY5NDgwMDE1NiwgInRvIjogMTY5NDgwMDE1Nn19fSwgInJlcXVlc3RlZF9wcmVkaWNhdGVzIjoge30sICJub25jZSI6ICI2MzMzNjgxOTM3NzI1MTkzMTUyNTY1OTEifQ==" + }, + "pres": { + "indy": { + "proof": { + "proofs": [ + { + "primary_proof": { + "eq_proof": { + "revealed_attrs": { + "country": "86091274455216294775467369229742497264338784747007530312638607524003986429176", + "family_name": "113629974197202028031743901156327948162780316423694730740234167618518062162596", + "given_names": "76669239303478628101977841967793018579704250003747303526675562174585617552380", + }, + "a_prime": "2752222004877393821946929938073672611147357281059879521899806617641901512078292728233552312669329595632699992281211310560630119613851389226292535964139817900617656492285503361597775161415020675353717626041656018753130092707159054275841026878421955025121014248985727425739760620186724345593157325448760454610171620029895802219351364562560524767768610096400702319143737465105065636413811415077694673724042500823762662459382470421367877341306655666708482381420027692007528656203079310607577830421182592394593025201292174148668834643310063767037229675811858030672760158692729475901407331902660576426733253619929226060268", + "e": "102841862579899394748101147926225980988284317813112065230903614605314014035947304230163816238422875108941564659002477799025081687187392664", + "v": "340554867558408556086093357826919358981768688107702729186444760247624631187520933039857336704146147023355618957606880959189296705224102334205611452495756420013307641114311191009854508367863340596260590519868011111621720944151253717359212043925748482163255710293540177923671752798999157616712082760660227861699025758925900988898324491597484653513304455651295039941405670388088884398259987637322460464433200791270462104062429525936637370537045866501073856217218230952704740292007889662804702281742640484955419486408213030492343503178198133861960152857738146894637982725893571193484870299796819648297800613770619480724452314284510318543536018028785185704134724262814039371175071125393355389941351202952956698975527531149089360343307140830624326790808831939799983724667618495300675831855759210725037345661004234516784307671404917875347355735815873031905709514634573948684201415633998012744531513426767583902308555806436032654", + "m": { + "birthdate_dateint": "2317803952542234063661759293832421485652656388240237711527971094776116471559195771533088720727964442958750426288263407108699113440607014715096343620937655263988188245154992805212", + "postal_code": "13727738920755492307396073621712351905517022535067330097134309796662703430906670320426685354562424395662500231978398320009224896369971528807242516076740504982663276320285129302631", + "region": "3898195067062190478457383545815179090617918998297207199547465504224386508721201959429059369633677859144984158022759874128284753392377775929027017463835652454541255512561810292078", + "expiry_date_dateint": "1204872815564296386187685604872485470626704285162933433087178339388517259255510287682979746219846957707949686777474066074611239256716654389445948098483804962372057850528148316029", + "locality": "11597054987853203184948655530942371268298406246991558492105828772699898911736544655696849808225830742870112219397307784712358362395552936350188310170208972108005848961591911477503", + "picture": "14641000664237394077660961546055467154927331706979893334588037194402882205412243501778560547260767521200288939747477540499011291230586841366281495152240927393478170444685893793783", + "master_secret": "4252460198761928963159948081931316045352726783662126724328223445443841137604034050982338605126196822109533123917772099980836750148245507650791305835087690105765818233633128944431", + "street_address": "3560551625564482857726867909758955501827276751876742793553852459460447211837243047171871137409586429468289265675104969343100465771655497110647867735756342782358553559892513719211", + }, + "m2": "107647437624274074225577067637575889195829933774437016608705283255664821276524579359299897835225486152482167547142833677763136652802989144079919893235727063123901540099764495836537932088943437692548244061678402727930152673030538299444980914271819137106655956398015046583452950363426592988835609493966130571990449513830235169850774795253857705229121742358139926694896354254176218769873859762034144165363639892519830179053238329882658569288333230957319971991916929963871999471702250722891217519065523463036309640116959367152993038424082277570805646677169251122696449294514072097743347954889564270796690063964912492338908067695318697927901767558415960389078154393040759703813007950982125536151182482207736527997139078582782983599359567", + }, + "ge_proofs": [], + }, + "non_revoc_proof": { + "x_list": { + "rho": "0BDEBEADA4E8CFD37E3075CF4A8E8692AD979BA1E67280E022F8AC2BE7B414BC", + "r": "02E59C4AB19B82D0ECB102EED639C52520DEF0EC91C53D519847F557042A8BB5", + "r_prime": "172216BDB6A481590690AA9645545A6EB1C996A5A1F87B072E2E61D526BA2ADE", + "r_prime_prime": "05AD762C4982BB2C99DCA23CC34E49AB7C9B193B2AB980A9BF1A1F4539310563", + "r_prime_prime_prime": "21CA2C2F459339319A38D0FD0407549BD75E1983EF0527EBEF140D3B42717C57", + "o": "07F8C8DD6F6B48A181929BE32AADDCBDC455AB7326179ECBCEE62E9E7EF2EACE", + "o_prime": "00C31E4206448C7DF461E160723F4CE3E75251124C04C4B509BAA172208788CA", + "m": "1B783BDDDB0965E3290FBA267128559477A1FF4AA38B8D12DFA8A9AD59521E7C", + "m_prime": "1FED18DDA918C196FF152EDF9C8D011462716C3DD6D11F5F0CD90CFACEF608EC", + "t": "06C04F2283725F67CFACD01B02524CCB09A770A453E56661913B521D400C4DAA", + "t_prime": "1292D8603B59229E97C72BDEE0E4F7339A2B0FE7A12722B42425F7E13BF0FE40", + "s": "0D9A9993EE09B1A3FE3CA860BBEAA728527B28B270C821D9054EB1A3F93617B7", + "c": "0EC53966010589EEBFDF7CAC1C170497851FB787A0BECB7D5F72A7B495878840", + }, + "c_list": { + "e": "6 4651BA4F1C0AB1C5053D42EAB0C2E456B3B30BCD2635EC613E2C6F77D4314E09 4 2C75BD1BD839572F1A7AFDE66DF6901EEA237DAB1C894C6B2D9063DCAF8AD083 4 1D0AE756C99A31B629090EB010DF8019E8726F62A6A79ED3B0067E3B601E5129", + "d": "6 5E8ACF57AEAE922B8F9CF4338D685AFE95D3CA9E73C1D9FAC35283451431BCB2 4 38601A54F24AD2D67F2B0383D38181130F0464D6ADBF59A34C41D8F5EB65548F 4 2370840CD4539CCD8DFB57C2773506904E9F3DFFA05A1C7C50BFEABC9511DED4", + "a": "6 39BEBB2486CA80D78023106BFA5152D5FED0D4D1AF47E56C361493D92C168C7B 4 10B2508D266D226215609821D3751A09A17DC6A39BCFF99222E292820620CE0B 4 25958FF85B4500ACC02EFBE543D83CBA89B2F61E346011358E89BFCFE445C359", + "g": "6 4E19AB7AF315C9D1077824C3595C805B5D32AA208851C9DC468A226BF0923B6D 4 23AD292298AC27F8588434346C74840099E5B64CA8011306905865062A1D4CD9 4 136FD412DBCE4E88BAC53A89D950A34982452DAC9F040F5FF3626121938E202D", + "w": "21 120B428648EFEE29FC69E0480AA397E4A5656E40DCE8F895DE1F8223E3E266792 21 12D419B813F7121B34F4D8B4623AD9A4BF90AF1098364A6401FB90782B0BC14DD 6 69373B75859E60550ED0A2C2518DD702DF753BD505337F8F1BF3F1D4DECB216D 4 31BC340A04647154743FC8435DD21611FE4D5B138A115117518DBEDDC1614583 6 72D33EE28AAC3006255F0AE6A8D009E392C5B4B0E1DBE123989BE110B05316F7 4 17BF62E556E9342915F0B629454EEF7B0F7CFE4203EE340998899CF2414A1BD0", + "s": "21 13F870B79A5C3DE382C620604C9393A46B368A466A55B756DFA02C7335D474469 21 13845BAFC4CD9164134507780598652A3258CC3C573FED0F23E8ED882A95F71E0 6 5440CD8DDD96B0BE4FECE0986AD5D5E1ED837FB743D24DA47D46C35165EE2CFB 4 2B6D777402034F257672648C86A239FBF80CB13BE9D5366503799DAFE1389E6E 6 8352806A9F2A72280568AF25CF84853FB97797DD9462344F00F46804D7DA6BF0 4 257FADE0B8C4BAFE1E701A92B0A86485F87C3F39BCA32AFC79E03151CBB6899F", + "u": "21 14469DC22C807EF596E1ADDA5CE8C214BA2D8BBABFBCDE7DC004282BFC7BC5E6D 21 10DF670CD8CB13AF3B881758B58D500605D2FA12A8DD31FA9D03EC671DBE9976E 6 64C6246591AB0A440E8BF053BE303122CC033A2FCDF65F4BC99E0B70D43A97EF 4 2EA64ED893C1D01098CD57A17276FC1BB8D737D58F0A53613041218E2D6D10B5 6 7C76C90A62311399E702C95871BB3A6578F09D4DEF6FF11B31EE36A67F7AD79A 4 1A573663F8BA8693F7DB05485B415E3D6511F3F7A43674345221EE59D4829688", + }, + }, + } + ], + "aggregated_proof": { + "c_hash": "57363661658638127431038526438947214485171900767855222428637184224177462688850", + "c_list": [ + [ + 4, + 12, + 196, + 249, + 69, + 109, + 233, + 15, + 19, + 185, + 56, + 188, + 56, + 74, + 111, + 91, + 193, + 115, + 182, + 138, + 207, + 16, + 248, + 255, + 97, + 249, + 162, + 54, + 175, + 239, + 138, + 21, + 173, + 21, + 47, + 182, + 0, + 224, + 223, + 147, + 133, + 177, + 7, + 66, + 214, + 213, + 204, + 238, + 75, + 219, + 33, + 115, + 30, + 243, + 132, + 200, + 185, + 81, + 250, + 85, + 141, + 175, + 223, + 133, + 118, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 4, + 15, + 189, + 215, + 22, + 168, + 110, + 143, + 45, + 26, + 18, + 252, + 166, + 6, + 219, + 13, + 49, + 67, + 222, + 196, + 199, + 206, + 197, + 134, + 107, + 228, + 42, + 111, + 177, + 121, + 202, + 61, + 137, + 31, + 238, + 25, + 157, + 241, + 30, + 133, + 172, + 25, + 235, + 184, + 145, + 16, + 176, + 85, + 215, + 140, + 146, + 114, + 43, + 163, + 1, + 109, + 32, + 183, + 46, + 206, + 220, + 220, + 190, + 136, + 133, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 4, + 12, + 97, + 61, + 34, + 131, + 238, + 234, + 77, + 175, + 24, + 21, + 20, + 184, + 135, + 150, + 174, + 166, + 170, + 22, + 64, + 69, + 147, + 87, + 102, + 1, + 70, + 71, + 9, + 148, + 130, + 219, + 150, + 18, + 65, + 77, + 240, + 27, + 90, + 17, + 20, + 26, + 55, + 205, + 224, + 48, + 247, + 178, + 133, + 45, + 244, + 28, + 158, + 164, + 197, + 141, + 7, + 210, + 228, + 2, + 27, + 231, + 21, + 102, + 143, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 4, + 25, + 228, + 152, + 198, + 93, + 188, + 146, + 223, + 229, + 127, + 158, + 85, + 244, + 87, + 50, + 176, + 254, + 181, + 172, + 243, + 101, + 114, + 198, + 54, + 34, + 52, + 144, + 176, + 24, + 62, + 124, + 165, + 27, + 110, + 207, + 236, + 193, + 200, + 51, + 143, + 159, + 171, + 47, + 230, + 103, + 253, + 20, + 226, + 243, + 17, + 251, + 245, + 73, + 252, + 224, + 192, + 149, + 129, + 68, + 128, + 129, + 186, + 225, + 87, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 15, + 32, + 107, + 89, + 100, + 140, + 118, + 230, + 170, + 196, + 33, + 129, + 149, + 120, + 146, + 9, + 159, + 107, + 131, + 203, + 79, + 159, + 244, + 130, + 77, + 176, + 198, + 205, + 174, + 143, + 53, + 39, + 11, + 127, + 150, + 44, + 234, + 105, + 31, + 73, + 127, + 118, + 176, + 199, + 113, + 244, + 245, + 163, + 63, + 119, + 203, + 251, + 223, + 7, + 129, + 21, + 107, + 247, + 240, + 165, + 234, + 36, + 93, + 14, + 11, + 169, + 22, + 156, + 115, + 5, + 16, + 255, + 25, + 49, + 13, + 253, + 104, + 97, + 95, + 123, + 190, + 112, + 247, + 176, + 254, + 243, + 11, + 120, + 4, + 60, + 152, + 174, + 115, + 157, + 100, + 85, + 13, + 231, + 198, + 56, + 247, + 239, + 46, + 174, + 68, + 238, + 73, + 91, + 243, + 205, + 108, + 190, + 193, + 112, + 178, + 251, + 191, + 220, + 76, + 14, + 144, + 30, + 49, + 144, + 91, + 42, + 160, + 222, + ], + [ + 36, + 228, + 220, + 20, + 145, + 124, + 198, + 157, + 90, + 165, + 236, + 89, + 171, + 105, + 129, + 168, + 56, + 95, + 159, + 131, + 68, + 204, + 36, + 255, + 217, + 83, + 15, + 231, + 242, + 177, + 36, + 230, + 16, + 122, + 71, + 44, + 0, + 75, + 122, + 27, + 178, + 233, + 45, + 225, + 139, + 59, + 167, + 80, + 152, + 127, + 155, + 214, + 166, + 65, + 33, + 48, + 224, + 20, + 175, + 31, + 131, + 130, + 27, + 82, + 4, + 229, + 90, + 106, + 108, + 89, + 227, + 3, + 62, + 51, + 49, + 184, + 84, + 234, + 152, + 237, + 221, + 168, + 242, + 83, + 239, + 69, + 78, + 211, + 23, + 188, + 168, + 215, + 179, + 212, + 30, + 214, + 36, + 222, + 100, + 38, + 19, + 162, + 7, + 185, + 119, + 66, + 36, + 245, + 13, + 68, + 98, + 115, + 77, + 229, + 52, + 3, + 229, + 50, + 190, + 130, + 208, + 199, + 28, + 113, + 239, + 6, + 18, + 185, + ], + [ + 6, + 17, + 170, + 116, + 247, + 33, + 250, + 89, + 85, + 106, + 233, + 131, + 132, + 99, + 20, + 63, + 37, + 223, + 131, + 116, + 153, + 137, + 180, + 169, + 206, + 26, + 34, + 253, + 147, + 254, + 137, + 24, + 9, + 73, + 164, + 58, + 58, + 173, + 191, + 96, + 81, + 85, + 179, + 13, + 234, + 255, + 231, + 141, + 51, + 14, + 116, + 117, + 77, + 172, + 108, + 218, + 42, + 183, + 175, + 213, + 135, + 103, + 153, + 195, + 31, + 147, + 43, + 101, + 123, + 238, + 241, + 74, + 228, + 224, + 145, + 65, + 247, + 173, + 234, + 27, + 248, + 147, + 198, + 195, + 244, + 84, + 213, + 228, + 100, + 181, + 19, + 248, + 206, + 91, + 162, + 24, + 8, + 108, + 69, + 103, + 158, + 55, + 128, + 220, + 123, + 223, + 208, + 38, + 225, + 218, + 59, + 32, + 84, + 5, + 164, + 0, + 205, + 42, + 95, + 114, + 174, + 52, + 211, + 107, + 114, + 225, + 217, + 179, + ], + [ + 21, + 205, + 66, + 159, + 152, + 122, + 39, + 49, + 164, + 139, + 62, + 39, + 133, + 69, + 234, + 243, + 35, + 153, + 83, + 25, + 113, + 187, + 118, + 192, + 15, + 255, + 227, + 99, + 0, + 49, + 163, + 51, + 167, + 190, + 26, + 83, + 129, + 114, + 79, + 216, + 74, + 241, + 36, + 173, + 207, + 95, + 115, + 123, + 178, + 46, + 122, + 21, + 216, + 73, + 126, + 41, + 189, + 162, + 120, + 226, + 98, + 191, + 135, + 111, + 27, + 170, + 33, + 18, + 120, + 164, + 3, + 187, + 164, + 123, + 163, + 14, + 157, + 171, + 6, + 62, + 132, + 52, + 188, + 248, + 202, + 164, + 191, + 201, + 53, + 204, + 166, + 130, + 63, + 0, + 15, + 169, + 124, + 140, + 9, + 119, + 209, + 151, + 72, + 163, + 77, + 77, + 27, + 20, + 89, + 130, + 183, + 41, + 104, + 101, + 182, + 250, + 245, + 97, + 144, + 96, + 62, + 18, + 77, + 183, + 93, + 101, + 233, + 97, + 13, + 81, + 167, + 110, + 101, + 19, + 213, + 211, + 249, + 8, + 239, + 157, + 84, + 24, + 136, + 31, + 252, + 225, + 159, + 59, + 151, + 94, + 224, + 184, + 115, + 162, + 155, + 234, + 37, + 168, + 110, + 213, + 231, + 150, + 143, + 124, + 228, + 109, + 43, + 189, + 183, + 231, + 11, + 30, + 217, + 5, + 21, + 221, + 178, + 137, + 4, + 40, + 90, + 220, + 242, + 163, + 154, + 54, + 143, + 42, + 70, + 117, + 205, + 192, + 219, + 102, + 212, + 100, + 196, + 154, + 229, + 43, + 234, + 174, + 71, + 44, + 228, + 166, + 2, + 155, + 204, + 173, + 244, + 33, + 81, + 188, + 60, + 236, + 204, + 135, + 52, + 136, + 200, + 165, + 158, + 112, + 253, + 241, + 81, + 60, + 174, + 130, + 97, + 80, + 62, + 248, + 147, + 144, + 218, + 253, + 172, + 78, + 82, + 83, + 65, + 12, + 22, + 39, + 114, + 202, + 209, + 13, + 5, + 145, + 253, + 14, + 161, + 236, + ], + ], + }, + }, + "requested_proof": { + "revealed_attrs": {}, + "revealed_attr_groups": { + "req_attr_0": { + "sub_proof_index": 0, + "values": { + "country": { + "raw": "Canada", + "encoded": "86091274455216294775467369229742497264338784747007530312638607524003986429176", + }, + "given_names": { + "raw": "Joyce", + "encoded": "76669239303478628101977841967793018579704250003747303526675562174585617552380", + }, + "family_name": { + "raw": "Lee-Martinez", + "encoded": "113629974197202028031743901156327948162780316423694730740234167618518062162596", + }, + }, + } + }, + "self_attested_attrs": {}, + "unrevealed_attrs": {}, + "predicates": {}, }, + "identifiers": [ + { + "schema_id": "QEquAHkM35w4XVT3Ku5yat:2:Person:1.2", + "cred_def_id": "QEquAHkM35w4XVT3Ku5yat:3:CL:7174:Person", + "rev_reg_id": "QEquAHkM35w4XVT3Ku5yat:4:QEquAHkM35w4XVT3Ku5yat:3:CL:7174:Person:CL_ACCUM:8b290969-7045-4c8e-965c-ddba20c57c4d", + "timestamp": 1710972108, + } + ], } - ], + }, }, - "initiator": "self", - "updated_at": "2023-09-15T17:49:33.477755Z", - "trace": False, + "verified": "true", + "verified_msgs": [], + "auto_present": False, "auto_verify": True, - "verified_msgs": ["RMV_GLB_NRI", "RMV_RFNT_NRI::req_attr_0"], + "auto_remove": True, } auth_session = AuthSession( pres_exch_id="e444bc3e-346d-47d1-882d-39c014b8978c", expired_timestamp=datetime.now() + timedelta(seconds=3000), - ver_config_id="verified-email", + ver_config_id="showcase-person", request_parameters={ "scope": "openid vc_authn", "state": "oFLNfUyzDtWHmc61dNiQZkVZRsRUUXZ5KZIiQBeQuJQ.xfaKQBh1xfQ.T02DEr3QRTmMUfjegc9fQQ", @@ -95,6 +1335,7 @@ pyop_auth_code="str", response_url="str", proof_status="pending", + # presentation_exchange=presentation["by_format"], ) ver_config = VerificationConfig( diff --git a/oidc-controller/api/core/oidc/tests/test_issue_token_service.py b/oidc-controller/api/core/oidc/tests/test_issue_token_service.py index 601257fc..48fc9345 100644 --- a/oidc-controller/api/core/oidc/tests/test_issue_token_service.py +++ b/oidc-controller/api/core/oidc/tests/test_issue_token_service.py @@ -1,6 +1,4 @@ -import mock import pytest -from api.authSessions.models import AuthSession from api.core.oidc.issue_token_service import Token from api.core.oidc.tests.__mocks__ import auth_session, presentation, ver_config @@ -68,20 +66,20 @@ @pytest.mark.asyncio async def test_valid_proof_presentation_with_one_attribute_returns_claims(): - presentation["presentation_request"][ + presentation["by_format"]["pres_request"]["indy"][ "requested_attributes" ] = basic_valid_requested_attributes - presentation["presentation"]["requested_proof"][ + presentation["by_format"]["pres"]["indy"]["requested_proof"][ "revealed_attr_groups" ] = basic_valid_revealed_attr_groups - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - claims = Token.get_claims(auth_session, ver_config) - assert claims is not None + auth_session.presentation_exchange = presentation["by_format"] + claims = Token.get_claims(auth_session, ver_config) + assert claims is not None @pytest.mark.asyncio async def test_valid_proof_presentation_with_multiple_attributes_returns_claims(): - presentation["presentation_request"]["requested_attributes"] = { + presentation["by_format"]["pres_request"]["indy"]["requested_attributes"] = { "req_attr_0": { "names": ["email"], "restrictions": [ @@ -101,7 +99,9 @@ async def test_valid_proof_presentation_with_multiple_attributes_returns_claims( ], }, } - presentation["presentation"]["requested_proof"]["revealed_attr_groups"] = { + presentation["by_format"]["pres"]["indy"]["requested_proof"][ + "revealed_attr_groups" + ] = { "req_attr_0": { "sub_proof_index": 0, "values": { @@ -127,72 +127,72 @@ async def test_valid_proof_presentation_with_multiple_attributes_returns_claims( }, }, } - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - claims = Token.get_claims(auth_session, ver_config) - assert claims is not None + auth_session.presentation_exchange = presentation["by_format"] + claims = Token.get_claims(auth_session, ver_config) + assert claims is not None @pytest.mark.asyncio async def test_include_v1_attributes_false_does_not_add_the_named_attributes(): - presentation["presentation_request"][ + presentation["by_format"]["pres_request"]["indy"][ "requested_attributes" ] = multiple_valid_requested_attributes - presentation["presentation"]["requested_proof"][ + presentation["by_format"]["pres"]["indy"]["requested_proof"][ "revealed_attr_groups" ] = multiple_valid_revealed_attr_groups - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - ver_config.include_v1_attributes = False - claims = Token.get_claims(auth_session, ver_config) - vc_presented_attributes_obj = eval(claims["vc_presented_attributes"]) - assert claims is not None - assert vc_presented_attributes_obj["email_1"] == "test@email.com" - assert vc_presented_attributes_obj["age_1"] == "30" - assert "email_1" not in claims - assert "age_1" not in claims + auth_session.presentation_exchange = presentation["by_format"] + ver_config.include_v1_attributes = False + claims = Token.get_claims(auth_session, ver_config) + vc_presented_attributes_obj = eval(claims["vc_presented_attributes"]) + assert claims is not None + assert vc_presented_attributes_obj["email_1"] == "test@email.com" + assert vc_presented_attributes_obj["age_1"] == "30" + assert "email_1" not in claims + assert "age_1" not in claims @pytest.mark.asyncio async def test_include_v1_attributes_true_adds_the_named_attributes(): - presentation["presentation_request"][ + presentation["by_format"]["pres_request"]["indy"][ "requested_attributes" ] = multiple_valid_requested_attributes - presentation["presentation"]["requested_proof"][ + presentation["by_format"]["pres"]["indy"]["requested_proof"][ "revealed_attr_groups" ] = multiple_valid_revealed_attr_groups - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - ver_config.include_v1_attributes = True - claims = Token.get_claims(auth_session, ver_config) - vc_presented_attributes_obj = eval(claims["vc_presented_attributes"]) - assert claims is not None - assert vc_presented_attributes_obj["email_1"] == "test@email.com" - assert vc_presented_attributes_obj["age_1"] == "30" - assert claims["email_1"] == "test@email.com" - assert claims["age_1"] == "30" + auth_session.presentation_exchange = presentation["by_format"] + ver_config.include_v1_attributes = True + claims = Token.get_claims(auth_session, ver_config) + vc_presented_attributes_obj = eval(claims["vc_presented_attributes"]) + assert claims is not None + assert vc_presented_attributes_obj["email_1"] == "test@email.com" + assert vc_presented_attributes_obj["age_1"] == "30" + assert claims["email_1"] == "test@email.com" + assert claims["age_1"] == "30" @pytest.mark.asyncio async def test_include_v1_attributes_none_does_not_add_the_named_attributes(): - presentation["presentation_request"][ + presentation["by_format"]["pres_request"]["indy"][ "requested_attributes" ] = multiple_valid_requested_attributes - presentation["presentation"]["requested_proof"][ + presentation["by_format"]["pres"]["indy"]["requested_proof"][ "revealed_attr_groups" ] = multiple_valid_revealed_attr_groups - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - ver_config.include_v1_attributes = None - print(ver_config.include_v1_attributes) - claims = Token.get_claims(auth_session, ver_config) - vc_presented_attributes_obj = eval(claims["vc_presented_attributes"]) - assert claims is not None - assert vc_presented_attributes_obj["email_1"] == "test@email.com" - assert vc_presented_attributes_obj["age_1"] == "30" - assert "email_1" not in claims - assert "age_1" not in claims + auth_session.presentation_exchange = presentation["by_format"] + ver_config.include_v1_attributes = None + print(ver_config.include_v1_attributes) + claims = Token.get_claims(auth_session, ver_config) + vc_presented_attributes_obj = eval(claims["vc_presented_attributes"]) + assert claims is not None + assert vc_presented_attributes_obj["email_1"] == "test@email.com" + assert vc_presented_attributes_obj["age_1"] == "30" + assert "email_1" not in claims + assert "age_1" not in claims @pytest.mark.asyncio async def test_revealed_attrs_dont_match_requested_attributes_throws_exception(): - presentation["presentation_request"]["requested_attributes"] = { + presentation["by_format"]["pres_request"]["indy"]["requested_attributes"] = { "req_attr_0": { "names": ["email"], "restrictions": [ @@ -203,7 +203,9 @@ async def test_revealed_attrs_dont_match_requested_attributes_throws_exception() ], } } - presentation["presentation"]["requested_proof"]["revealed_attr_groups"] = { + presentation["by_format"]["pres"]["indy"]["requested_proof"][ + "revealed_attr_groups" + ] = { "req_attr_0": { "sub_proof_index": 0, "values": { @@ -217,77 +219,77 @@ async def test_revealed_attrs_dont_match_requested_attributes_throws_exception() }, } } - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - with pytest.raises(Exception): - Token.get_claims(auth_session, ver_config) + auth_session.presentation_exchange = presentation["by_format"] + with pytest.raises(Exception): + Token.get_claims(auth_session, ver_config) @pytest.mark.asyncio async def test_valid_presentation_with_matching_subject_identifier_in_claims_sub(): - presentation["presentation_request"][ + presentation["by_format"]["pres_request"]["indy"][ "requested_attributes" ] = basic_valid_requested_attributes - presentation["presentation"]["requested_proof"][ + presentation["by_format"]["pres"]["indy"]["requested_proof"][ "revealed_attr_groups" ] = basic_valid_revealed_attr_groups - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - claims = Token.get_claims(auth_session, ver_config) - print(claims) - assert claims["sub"] == "test@email.com" + auth_session.presentation_exchange = presentation["by_format"] + claims = Token.get_claims(auth_session, ver_config) + print(claims) + assert claims["sub"] == "test@email.com" @pytest.mark.asyncio async def test_valid_pres_with_non_matching_subj_id_gen_consistent_id_missing_no_sub(): - presentation["presentation_request"][ + presentation["by_format"]["pres_request"]["indy"][ "requested_attributes" ] = basic_valid_requested_attributes - presentation["presentation"]["requested_proof"][ + presentation["by_format"]["pres"]["indy"]["requested_proof"][ "revealed_attr_groups" ] = basic_valid_revealed_attr_groups - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - ver_config.subject_identifier = "not-email" - claims = Token.get_claims(auth_session, ver_config) - assert not ver_config.generate_consistent_identifier - assert "sub" not in claims + auth_session.presentation_exchange = presentation["by_format"] + ver_config.subject_identifier = "not-email" + claims = Token.get_claims(auth_session, ver_config) + assert not ver_config.generate_consistent_identifier + assert "sub" not in claims @pytest.mark.asyncio async def test_valid_pres_non_matching_subj_id_gen_consistent_id_false_has_no_sub(): - presentation["presentation_request"][ + presentation["by_format"]["pres_request"]["indy"][ "requested_attributes" ] = basic_valid_requested_attributes - presentation["presentation"]["requested_proof"][ + presentation["by_format"]["pres"]["indy"]["requested_proof"][ "revealed_attr_groups" ] = basic_valid_revealed_attr_groups - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - ver_config.subject_identifier = "not-email" - ver_config.generate_consistent_identifier = False - claims = Token.get_claims(auth_session, ver_config) - assert "sub" not in claims + auth_session.presentation_exchange = presentation["by_format"] + ver_config.subject_identifier = "not-email" + ver_config.generate_consistent_identifier = False + claims = Token.get_claims(auth_session, ver_config) + assert "sub" not in claims @pytest.mark.asyncio async def test_valid_pres_non_matching_subj_id_gen_consistent_id_true_has_sub(): - presentation["presentation_request"][ + presentation["by_format"]["pres_request"]["indy"][ "requested_attributes" ] = basic_valid_requested_attributes - presentation["presentation"]["requested_proof"][ + presentation["by_format"]["pres"]["indy"]["requested_proof"][ "revealed_attr_groups" ] = basic_valid_revealed_attr_groups - with mock.patch.object(AuthSession, "presentation_exchange", presentation): - ver_config.subject_identifier = "not-email" - ver_config.generate_consistent_identifier = True - claims = Token.get_claims(auth_session, ver_config) - assert "sub" in claims + auth_session.presentation_exchange = presentation["by_format"] + ver_config.subject_identifier = "not-email" + ver_config.generate_consistent_identifier = True + claims = Token.get_claims(auth_session, ver_config) + assert "sub" in claims - # Ensure that this sub is not using the ver_config.subject_identifier - ver_config.subject_identifier = "email" - ver_config.generate_consistent_identifier = False - claims_subject_identifier = Token.get_claims(auth_session, ver_config) - assert claims["sub"] != claims_subject_identifier["sub"] + # Ensure that this sub is not using the ver_config.subject_identifier + ver_config.subject_identifier = "email" + ver_config.generate_consistent_identifier = False + claims_subject_identifier = Token.get_claims(auth_session, ver_config) + assert claims["sub"] != claims_subject_identifier["sub"] - # Ensure that sub is consistent - ver_config.subject_identifier = "not-email" - ver_config.generate_consistent_identifier = True - claims_duplicate = Token.get_claims(auth_session, ver_config) - assert claims["sub"] == claims_duplicate["sub"] + # Ensure that sub is consistent + ver_config.subject_identifier = "not-email" + ver_config.generate_consistent_identifier = True + claims_duplicate = Token.get_claims(auth_session, ver_config) + assert claims["sub"] == claims_duplicate["sub"] diff --git a/oidc-controller/api/routers/acapy_handler.py b/oidc-controller/api/routers/acapy_handler.py index d5cc20b7..2d39e939 100644 --- a/oidc-controller/api/routers/acapy_handler.py +++ b/oidc-controller/api/routers/acapy_handler.py @@ -7,7 +7,6 @@ from ..authSessions.crud import AuthSessionCRUD from ..authSessions.models import AuthSession, AuthSessionPatch, AuthSessionState -from ..core.acapy.client import AcapyClient from ..db.session import get_db from ..core.config import settings @@ -26,17 +25,15 @@ async def _parse_webhook_body(request: Request): async def post_topic(request: Request, topic: str, db: Database = Depends(get_db)): """Called by aca-py agent.""" logger.info(f">>> post_topic : topic={topic}") + logger.info(f">>> web hook post_body : {await _parse_webhook_body(request)}") - client = AcapyClient() match topic: - case "present_proof": + case "present_proof_v2_0": webhook_body = await _parse_webhook_body(request) - logger.info( - f">>>> pres_exch_id: {webhook_body['presentation_exchange_id']}" - ) - + logger.info(f">>>> pres_exch_id: {webhook_body['pres_ex_id']}") + # logger.info(f">>>> web hook: {webhook_body}") auth_session: AuthSession = await AuthSessionCRUD(db).get_by_pres_exch_id( - webhook_body["presentation_exchange_id"] + webhook_body["pres_ex_id"] ) # Get the saved websocket session @@ -45,15 +42,14 @@ async def post_topic(request: Request, topic: str, db: Database = Depends(get_db sid = connections.get(pid) logger.debug(f"sid: {sid} found for pid: {pid}") - if webhook_body["state"] == "presentation_received": - logger.info("GOT A PRESENTATION, TIME TO VERIFY") - client.verify_presentation(auth_session.pres_exch_id) - # This state is the default on the front end.. So don't send a status + if webhook_body["state"] == "presentation-received": + logger.info("presentation-received") - if webhook_body["state"] == "verified": + if webhook_body["state"] == "done": logger.info("VERIFIED") if webhook_body["verified"] == "true": auth_session.proof_status = AuthSessionState.VERIFIED + auth_session.presentation_exchange = webhook_body["by_format"] if sid: await sio.emit("status", {"status": "verified"}, to=sid) else: diff --git a/oidc-controller/api/routers/oidc.py b/oidc-controller/api/routers/oidc.py index 08421d6a..808f8cad 100644 --- a/oidc-controller/api/routers/oidc.py +++ b/oidc-controller/api/routers/oidc.py @@ -21,7 +21,7 @@ from ..core.acapy.client import AcapyClient from ..core.aries import ( PresentationRequestMessage, - PresentProofv10Attachment, + PresentProofv20Attachment, ServiceDecorator, ) from ..core.config import settings @@ -140,14 +140,23 @@ async def get_authorize(request: Request, db: Database = Depends(get_db)): else: wallet_did = client.get_wallet_did(public=use_public_did) - byo_attachment = PresentProofv10Attachment.build( - pres_exch_dict["presentation_request"] + byo_attachment = PresentProofv20Attachment( + # As of present proof 2.0 the pres_exch_dict already + # contains a complete attachment so we only need to + # extract the base64 encoded data + data=pres_exch_dict["pres_request"]["request_presentations~attach"][0][ + "data" + ] ) + s_d = ServiceDecorator( service_endpoint=client.service_endpoint, recipient_keys=[wallet_did.verkey] ) msg = PresentationRequestMessage( id=pres_exch_dict["thread_id"], + formats=[ + {"attach_id": byo_attachment.id, "format": "hlindy/proof-req@v2.0"} + ], request=[byo_attachment], service=s_d, ) @@ -159,7 +168,7 @@ async def get_authorize(request: Request, db: Database = Depends(get_db)): pyop_auth_code=authn_response["code"], request_parameters=model.to_dict(), ver_config_id=ver_config_id, - pres_exch_id=response.presentation_exchange_id, + pres_exch_id=response.pres_ex_id, presentation_exchange=pres_exch_dict, presentation_request_msg=msg_contents.dict(by_alias=True), )