Skip to content

Commit 590e143

Browse files
JMouniertux3
authored andcommitted
test(oidc): add oidc authorization code tests
1 parent abaab76 commit 590e143

2 files changed

Lines changed: 143 additions & 0 deletions

File tree

tankersdk/experimental.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from _tanker import lib as tankerlib
2+
3+
from .tanker import OidcAuthorizationCodeVerification, Tanker, ffihelpers
4+
5+
6+
async def authenticate_with_idp(
7+
tanker: Tanker, provider_id: str, cookie: str
8+
) -> OidcAuthorizationCodeVerification:
9+
c_provider_id = ffihelpers.str_to_c_string(provider_id)
10+
c_cookie = ffihelpers.str_to_c_string(cookie)
11+
c_expected_verification = tankerlib.tanker_authenticate_with_idp(
12+
tanker.c_tanker, c_provider_id, c_cookie
13+
)
14+
15+
c_verification = ffihelpers.unwrap_expected(
16+
c_expected_verification, "tanker_oidc_authorization_code_verification_t*"
17+
)
18+
c_authorization_code = c_verification.authorization_code
19+
c_state = c_verification.state
20+
21+
authorization_code = ffihelpers.c_string_to_str(c_authorization_code)
22+
state = ffihelpers.c_string_to_str(c_state)
23+
return OidcAuthorizationCodeVerification(provider_id, authorization_code, state)

test/test_tanker.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
VerificationOptions,
4242
error,
4343
)
44+
from tankersdk.experimental import authenticate_with_idp
4445

4546

4647
def encode(string: str) -> str:
@@ -68,6 +69,7 @@ def read_test_config() -> Dict[str, Any]:
6869
"clientSecret": assert_env("TANKER_OIDC_CLIENT_SECRET"),
6970
"provider": assert_env("TANKER_OIDC_PROVIDER"),
7071
"issuer": assert_env("TANKER_OIDC_ISSUER"),
72+
"fakeOidcIssuerUrl": assert_env("TANKER_FAKE_OIDC_URL") + "/issuer",
7173
}
7274
res["oidc"]["users"] = {
7375
"martine": {
@@ -1546,6 +1548,22 @@ def set_up_oidc(app: Dict[str, str], admin: Admin) -> Dict[str, str]:
15461548
return cast(Dict[str, str], admin.get_app(app["id"])["oidc_providers"][0])
15471549

15481550

1551+
def set_up_fake_oidc(app: Dict[str, str], admin: Admin) -> Dict[str, str]:
1552+
fake_oidc_issuer_url = TEST_CONFIG["oidc"]["fakeOidcIssuerUrl"]
1553+
1554+
oidc_issuer = fake_oidc_issuer_url
1555+
oidc_client_id = "tanker"
1556+
oidc_provider = "fake-oidc"
1557+
admin.update_app(
1558+
app["id"],
1559+
oidc_client_id=oidc_client_id,
1560+
oidc_display_name=oidc_provider,
1561+
oidc_issuer=oidc_issuer,
1562+
)
1563+
1564+
return cast(Dict[str, str], admin.get_app(app["id"])["oidc_providers"][0])
1565+
1566+
15491567
@pytest.mark.asyncio
15501568
async def test_oidc_verification(
15511569
tmp_path: Path, app: Dict[str, str], admin: Admin
@@ -1584,6 +1602,61 @@ async def test_oidc_verification(
15841602
await martine_laptop.stop()
15851603

15861604

1605+
@pytest.mark.asyncio
1606+
async def test_oidc_authorization_code_verification(
1607+
tmp_path: Path, app: Dict[str, str], admin: Admin
1608+
) -> None:
1609+
provider_config = set_up_fake_oidc(app, admin)
1610+
provider_id = provider_config["id"]
1611+
subject_cookie = "fake_oidc_subject=martine"
1612+
1613+
phone_path = tmp_path / "phone"
1614+
phone_path.mkdir(exist_ok=True)
1615+
martine_phone = create_tanker(app["id"], persistent_path=phone_path)
1616+
identity = tankersdk_identity.create_identity(
1617+
app["id"], app["secret"], str(uuid.uuid4())
1618+
)
1619+
1620+
await martine_phone.start(identity)
1621+
1622+
verification1 = await authenticate_with_idp(
1623+
martine_phone, provider_id, subject_cookie
1624+
)
1625+
verification2 = await authenticate_with_idp(
1626+
martine_phone, provider_id, subject_cookie
1627+
)
1628+
await martine_phone.register_identity(verification1)
1629+
await martine_phone.stop()
1630+
1631+
laptop_path = tmp_path / "laptop"
1632+
laptop_path.mkdir(exist_ok=True)
1633+
martine_laptop = create_tanker(app["id"], persistent_path=laptop_path)
1634+
await martine_laptop.start(identity)
1635+
1636+
assert martine_laptop.status == TankerStatus.IDENTITY_VERIFICATION_NEEDED
1637+
await martine_laptop.verify_identity(verification2)
1638+
assert martine_laptop.status == TankerStatus.READY
1639+
1640+
actual_methods = await martine_laptop.get_verification_methods()
1641+
(actual_method,) = actual_methods
1642+
assert actual_method.method_type == VerificationMethodType.OIDC_ID_TOKEN
1643+
1644+
await martine_laptop.stop()
1645+
1646+
tablet_path = tmp_path / "tablet"
1647+
tablet_path.mkdir(exist_ok=True)
1648+
martine_tablet = create_tanker(app["id"], persistent_path=tablet_path)
1649+
await martine_tablet.start(identity)
1650+
verification3 = await authenticate_with_idp(
1651+
martine_tablet, provider_id, "fake_oidc_subject=not_martine"
1652+
)
1653+
1654+
assert martine_tablet.status == TankerStatus.IDENTITY_VERIFICATION_NEEDED
1655+
with pytest.raises(error.InvalidVerification):
1656+
await martine_tablet.verify_identity(verification3)
1657+
await martine_tablet.stop()
1658+
1659+
15871660
@pytest.mark.asyncio
15881661
async def test_register_fails_with_preverified_email(
15891662
tmp_path: Path, app: Dict[str, str], admin: Admin
@@ -1886,6 +1959,53 @@ async def test_set_verification_method_with_oidc(
18861959
await phone_tanker.stop()
18871960

18881961

1962+
@pytest.mark.asyncio
1963+
async def test_set_oidc_authorization_code_verification(
1964+
tmp_path: Path, app: Dict[str, str], admin: Admin
1965+
) -> None:
1966+
provider_config = set_up_fake_oidc(app, admin)
1967+
provider_id = provider_config["id"]
1968+
subject_cookie = "fake_oidc_subject=alice"
1969+
passphrase = "The cake is not a lie"
1970+
1971+
laptop_path = tmp_path / "laptop"
1972+
laptop_path.mkdir(exist_ok=True)
1973+
laptop_tanker = create_tanker(app["id"], persistent_path=laptop_path)
1974+
alice_identity = tankersdk_identity.create_identity(
1975+
app["id"], app["secret"], str(uuid.uuid4())
1976+
)
1977+
1978+
await laptop_tanker.start(alice_identity)
1979+
await laptop_tanker.register_identity(PassphraseVerification(passphrase))
1980+
1981+
verification2 = await authenticate_with_idp(
1982+
laptop_tanker, provider_id, subject_cookie
1983+
)
1984+
await laptop_tanker.set_verification_method(verification2)
1985+
1986+
methods = set(await laptop_tanker.get_verification_methods())
1987+
assert len(methods) == 2
1988+
oidc_methods = [x for x in methods if isinstance(x, OidcIdTokenVerificationMethod)]
1989+
assert oidc_methods[0].provider_id == provider_config["id"]
1990+
assert oidc_methods[0].provider_display_name == provider_config["display_name"]
1991+
1992+
phone_path = tmp_path.joinpath("phone")
1993+
phone_path.mkdir(exist_ok=True)
1994+
phone_tanker = create_tanker(app["id"], persistent_path=phone_path)
1995+
1996+
await phone_tanker.start(alice_identity)
1997+
assert phone_tanker.status == TankerStatus.IDENTITY_VERIFICATION_NEEDED
1998+
1999+
verification2 = await authenticate_with_idp(
2000+
laptop_tanker, provider_id, subject_cookie
2001+
)
2002+
await phone_tanker.verify_identity(verification2)
2003+
assert phone_tanker.status == TankerStatus.READY
2004+
2005+
await laptop_tanker.stop()
2006+
await phone_tanker.stop()
2007+
2008+
18892009
def test_prehash_password_empty() -> None:
18902010
with pytest.raises(error.InvalidArgument):
18912011
tankersdk.prehash_password("")

0 commit comments

Comments
 (0)