Skip to content

Commit

Permalink
Merge pull request #560 from bcgov/present_proof_2
Browse files Browse the repository at this point in the history
Use present-proof v2 protocol
  • Loading branch information
esune authored Jul 26, 2024
2 parents cbc44e5 + 19bd25c commit c2bbfc7
Show file tree
Hide file tree
Showing 14 changed files with 1,448 additions and 273 deletions.
2 changes: 1 addition & 1 deletion docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
2 changes: 1 addition & 1 deletion docker/manage
Original file line number Diff line number Diff line change
Expand Up @@ -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"}
Expand Down
10 changes: 3 additions & 7 deletions oidc-controller/api/authSessions/models.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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):
Expand All @@ -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
28 changes: 6 additions & 22 deletions oidc-controller/api/core/acapy/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"


Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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},
}
Expand Down
4 changes: 2 additions & 2 deletions oidc-controller/api/core/acapy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
42 changes: 0 additions & 42 deletions oidc-controller/api/core/acapy/tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion oidc-controller/api/core/aries/__init__.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
19 changes: 2 additions & 17 deletions oidc-controller/api/core/aries/present_proof_attachment.py
Original file line number Diff line number Diff line change
@@ -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")
}
)
9 changes: 5 additions & 4 deletions oidc-controller/api/core/aries/present_proof_presentation.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
15 changes: 9 additions & 6 deletions oidc-controller/api/core/oidc/issue_token_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
)
Expand Down
Loading

0 comments on commit c2bbfc7

Please sign in to comment.