Skip to content

Commit

Permalink
Add get_claims unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: jamshale <jamiehalebc@gmail.com>
  • Loading branch information
jamshale committed Sep 20, 2023
1 parent 1e3ec92 commit cfdb19e
Show file tree
Hide file tree
Showing 7 changed files with 301 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/controller_unittests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11"]
python-version: ["3.11"]

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion oidc-controller/api/core/oidc/issue_token_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Token(BaseModel):

@classmethod
def get_claims(
cls, pres_exch: Dict, auth_session: AuthSession, ver_config: VerificationConfig
cls, auth_session: AuthSession, ver_config: VerificationConfig
) -> dict[str, str]:
"""Converts vc presentation values to oidc claims"""
oidc_claims: List[Claim] = [
Expand Down
122 changes: 122 additions & 0 deletions oidc-controller/api/core/oidc/tests/__mocks__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@


from datetime import datetime, timedelta

from api.verificationConfigs.models import VerificationConfig, VerificationProofRequest
from api.authSessions.models import AuthSession

presentation = {
"thread_id": "428ab5dc-185f-40ba-8714-498c79b822f3",
"created_at": "2023-09-15T17:49:16.397954Z",
"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"
},
"a_prime": "40809417934849907123261471333411809633354074436405510819719547561843004255793023387498104889708571270607131703938696756407487467873368373775514806534499374680059274765067020721416649641170535056242622419292879011504372419414431627060123535951854477609020119038446707071877530649018798857842493513975477809431501443034563297114458359206476293934461316378865994820249592804467758433904174100097026785285885805688715928578812499534293751388422584754995155726212908115142236221995953756086868367889189436621196564054394071524712971126196703085030819194540892286515361206473918715176334283198231106756804249201321110676817",
"e": "132166309846004002298968329630750626534906193461199076364226183288855464715230907038994149984215600411276690314987056469395087923423376034",
"v": "389852336354596234620050863642411241608940316153319185423050526707483503655636070718528707360249027781424214465818771183857876571898645233712049550065615437328753383559647676180932006072233802815800996667626559757294734656704881893512658110558847026240354780006408044914149694965180223127754340423475416000940696265773581100989216553579233198807834530514088943560794612627439000580021272527304012796141460444099028132444095750454921031441117671745673457339631909515144154149520136598843334638440138229207476684776682052027672414220327439299122271829090948693982983191662066627130404544959976637513561609461174550463471636750546362339385232864872096796748538286120598703640917737216094473317639418313144992206875604615452306826430748790105881684965109026881701380306409317275248915954859998470708379642658766566479932465684746033865495941061980422316943701392367332573162799073428328950386460662125690364635698421614848860",
"m": {
"time": "11896542455624181868867605459032062290636202825612483735571300567506766112289589216989585608752835036405824270689163034684130257627062069669940002269643613585904726141499206139998",
"master_secret": "11978669714570126125906674715703732098298259897696576462078203241042378591463388624826815153862705227192729264588296043944542578244619153416802465506231069348686312732305137579470",
},
"m2": "5273201069177175286302918970464632772021241766353736934881903190951819578898991714048991692651562372414552361008106867369251847950990157935703897032904209115054769991615534757984",
},
"ge_proofs": [],
}
}
],
"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",
}
],
},
"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=="
},
}
],
},
"initiator": "self",
"updated_at": "2023-09-15T17:49:33.477755Z",
"trace": False,
"auto_verify": True,
"verified_msgs": ["RMV_GLB_NRI", "RMV_RFNT_NRI::req_attr_0"],
}

auth_session = AuthSession(
pres_exch_id="e444bc3e-346d-47d1-882d-39c014b8978c",
expired_timestamp=datetime.now() + timedelta(seconds=3000),
ver_config_id="verified-email",
request_parameters={
'scope': 'openid vc_authn',
'state': 'oFLNfUyzDtWHmc61dNiQZkVZRsRUUXZ5KZIiQBeQuJQ.xfaKQBh1xfQ.T02DEr3QRTmMUfjegc9fQQ',
'response_type': 'code',
'client_id': 'keycloak',
'redirect_uri': 'http://localhost:8880/auth/realms/vc-authn/broker/vc-authn/endpoint',
'pres_req_conf_id': 'verified-email',
'nonce': 'J2o8dDBWAZyov0ipkMPZng'
},
pyop_auth_code="str",
response_url="str",
proof_status="pending",
)

ver_config = VerificationConfig(
ver_config_id="verified-email",
subject_identifier="email",
proof_request=VerificationProofRequest(
name="BCGov Verified Email",
version="1.0",
requested_attributes=[
{
"names": ["email"],
"restrictions": [
{
"schema_name": "verified-email",
"issuer_did": "MTYqmTBoLT7KLP5RNfgK3b"
}
]
}
],
requested_predicates=[]
)
)
167 changes: 167 additions & 0 deletions oidc-controller/api/core/oidc/tests/test_get_claims.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
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
from api.test_utils import is_valid_uuid

basic_valid_requested_attributes = {
"req_attr_0": {
"names": ["email"],
"restrictions": [
{
"schema_name": "verified-email",
"issuer_did": "MTYqmTBoLT7KLP5RNfgK3b",
}
],
}
}

basic_valid_revealed_attr_groups = {
"req_attr_0": {
"sub_proof_index": 0,
"values": {
"email": {
"raw": "jamiehalebc@gmail.com",
"encoded": "73814602767252868561268261832462872577293109184327908660400248444458427915643",
}
}
}
}


@pytest.mark.asyncio
async def test_valid_proof_presentation_with_one_attribute_returns_claims():
presentation['presentation_request']['requested_attributes'] = basic_valid_requested_attributes
presentation['presentation']['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


@pytest.mark.asyncio
async def test_valid_proof_presentation_with_multiple_attributes_returns_claims():
presentation['presentation_request']['requested_attributes'] = {
"req_attr_0": {
"names": ["email"],
"restrictions": [
{
"schema_name": "verified-email",
"issuer_did": "MTYqmTBoLT7KLP5RNfgK3b",
}
],
},
"req_attr_1": {
"names": ["age"],
"restrictions": [
{
"schema_name": "verified-age",
"issuer_did": "MTYqmTBoLT7KLP5RNfgK3c",
}
],
}
}
presentation['presentation']['requested_proof']['revealed_attr_groups'] = {
"req_attr_0": {
"sub_proof_index": 0,
"values": {
"email": {
"raw": "jamiehalebc@gmail.com",
"encoded": "73814602767252868561268261832462872577293109184327908660400248444458427915643",
}
}
},
"req_attr_1": {
"sub_proof_index": 0,
"values": {
"age": {
"raw": "30",
"encoded": "73814602767252868561268261832462872577293109184327908660400248444458427915644",
}
}
}
}
with mock.patch.object(AuthSession, "presentation_exchange", presentation):
claims = Token.get_claims(auth_session, ver_config)
assert claims is not None


@pytest.mark.asyncio
async def test_valid_proof_presentation_with_one_attribute_and_multiple_values_returns_claims():
presentation['presentation_request']['requested_attributes'] = {
"req_attr_0": {
"names": ["email_1", "age_1"],
"restrictions": [
{
"schema_name": "verified-email",
"issuer_did": "MTYqmTBoLT7KLP5RNfgK3b",
}
],
},
}
presentation['presentation']['requested_proof']['revealed_attr_groups'] = {
"req_attr_0": {
"sub_proof_index": 0,
"values": {
"email_1": {
"raw": "jamiehalebc@gmail.com",
"encoded": "73814602767252868561268261832462872577293109184327908660400248444458427915643",
},
"age_1": {
"raw": "30",
"encoded": "73814602767252868561268261832462872577293109184327908660400248444458427915644",
}
}
}
}
with mock.patch.object(AuthSession, "presentation_exchange", presentation):
claims = Token.get_claims(auth_session, ver_config)
assert claims is not None


@pytest.mark.asyncio
async def test_revealed_attrs_dont_match_requested_attributes_throws_exception():
presentation['presentation_request']['requested_attributes'] = {
"req_attr_0": {
"names": ["email"],
"restrictions": [
{
"schema_name": "verified-email",
"issuer_did": "MTYqmTBoLT7KLP5RNfgK3b",
}
],
}
}
presentation['presentation']['requested_proof']['revealed_attr_groups'] = {
"req_attr_0": {
"sub_proof_index": 0,
"values": {
"email-wrong": {
"raw": "jamiehalebc@gmail.com",
"encoded": "73814602767252868561268261832462872577293109184327908660400248444458427915643",
}
}
}
}
with mock.patch.object(AuthSession, "presentation_exchange", presentation):
with pytest.raises(Exception):
Token.get_claims(auth_session, ver_config)


@pytest.mark.asyncio
async def test_valid_presentation_with_matching_subject_identifier_has_identifier_in_claims_sub():
presentation['presentation_request']['requested_attributes'] = basic_valid_requested_attributes
presentation['presentation']['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"] == "jamiehalebc@gmail.com"

@pytest.mark.asyncio
async def test_valid_presentation_with_non_matching_subject_identifier_and_has_uuid_in_claims_sub():
presentation['presentation_request']['requested_attributes'] = basic_valid_requested_attributes
presentation['presentation']['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 is_valid_uuid(claims["sub"]) is True
3 changes: 1 addition & 2 deletions oidc-controller/api/routers/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ async def post_token(request: Request, db: Database = Depends(get_db)):

auth_session = await AuthSessionCRUD(db).get_by_pyop_auth_code(model.get("code"))
ver_config = await VerificationConfigCRUD(db).get(auth_session.ver_config_id)
presentation = client.get_presentation_request(auth_session.pres_exch_id)
claims = Token.get_claims(presentation, auth_session, ver_config)
claims = Token.get_claims(auth_session, ver_config)

# modify subject identifier value to use vc-attribute as configured
new_sub = claims.pop("sub")
Expand Down
8 changes: 8 additions & 0 deletions oidc-controller/api/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import uuid

def is_valid_uuid(value: str):
try:
uuid.UUID(str(value))
return True
except ValueError:
return False
1 change: 1 addition & 0 deletions oidc-controller/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
black==23.3.0
flake8==6.0.0
mock==4.0.3
mongomock==4.1.2
pytest==7.3.1
pytest-asyncio==0.21.1

0 comments on commit cfdb19e

Please sign in to comment.