-
Notifications
You must be signed in to change notification settings - Fork 75
Training: Mobile Authn
High level overview of the goals of this project: chain of custody from App Store to authz decision.
Using an SSA to obtain client credentials.
- The app distribution includes the SSA (Software Statement Assertion) generated from the Jans Auth Server, which is used for Dynamic Client Registration against the Auth Server.
- DCR attestation ensures that only legitimate and trusted clients can register with an authorization server. To use attestation in OAuth 2.0 Dynamic Client Registration, the app generates evidence in JWT format containing verifiable claims like app_id and app-checksum.
- For Android applications, the integrity verdict from the Play Integrity API can be added as a claim in the evidence JWT for attested DCR. This claim is then verified by the designated verifier to ensure the trustworthiness of both the app and the Android device. Based on this verification, the DCR is either approved or rejected.
- The public key used for signing the attested JWT must also be included in the attested Dynamic Client Registration request, so it can be verified by the Jans Auth Server. A sample DCR request on Jans Auth Server is as follows:
########
Request
########
curl -X POST -k -H ‘Content-Type: application/json' -i ‘https://your.janssen.server/jans-auth/restv1/register' — data ‘{
"software_statement": "eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlJTMjU2IiwiandrIjp7ImUiOiJBUUFCIiwia3R5IjoiUlNBIiwibi.......thMdKlqynrn9kyLXwflpMWbirWrQxIpIbkQ6srHStyDDh1zBEyYNAj-pXz9iyhHULoz0Ig",
"client_name":"DPoPAppClient-bc041d99–2c02–4622–8b6b",
"evidence":"eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlJTMjU2IiwiandrIjp7ImUiOiJBUUFCIiwia3R5IjoiUlNBIiwibi.......thMdKlqynrn9kyLXwflpMWbirWrQxIpIbkQ6srHStyDDh1zBEyYNAj-pXz9iyhHULoz0Ig",
"jwks":"{\"keys\":[{\"e\":\"AQAB\",\"kty\":\"RSA\",\"n\":\"pzVIV71wHi1fG3TEcCUJw0uolOBUryEJPy8IFpI20lAWqWw5prPn2mPqsyaOPpQtNX2_12PmZjlDq3SjInipSK_saSJ4pm-LCTOYZm55n5QbiK-iCR0DgCVlAeNj6YIenk1Tdy0KSuYoZxOL7iOdMAT9f7qvRAlSdWivOef_tDEtCIbZ3aKoNujv0xPUmOgnZ0U1QdxK3bmprV08O6dV6-_GJBeEdGZ5qZezPIxyjaxiGcoDk47QxdFz-aD38md-zQDEr9toU08j08bgeZLvbVr5e_M-fzhGY5yEISg1e-87n_v3HbdKFGuRFqYp3CYVayuYMWJsIIq8aEPZxdi8qw\"}]}",
"redirect_uris":["https://your.janssen.server"],
"response_types":["code"],
"scope":"openid"
"application_type":"native"
}'
########
Response
########
{
"allow_spontaneous_scopes": false,
"jwks": {
"keys": [{
"kty": "RSA",
"e": "AQAB",
"n": "pzVIV71wHi1fG3TEcCUJw0uolOBUryEJPy8IFpI20lAWqWw5prPn2mPqsyaOPpQtNX2_12PmZjlDq3SjInipSK_saSJ4pm-LCTOYZm55n5QbiK-iCR0DgCVlAeNj6YIenk1Tdy0KSuYoZxOL7iOdMAT9f7qvRAlSdWivOef_tDEtCIbZ3aKoNujv0xPUmOgnZ0U1QdxK3bmprV08O6dV6-_GJBeEdGZ5qZezPIxyjaxiGcoDk47QxdFz-aD38md-zQDEr9toU08j08bgeZLvbVr5e_M-fzhGY5yEISg1e-87n_v3HbdKFGuRFqYp3CYVayuYMWJsIIq8aEPZxdi8qw"
}]
},
"application_type": "web",
"rpt_as_jwt": false,
"registration_client_uri": "https://your.janssen.server/jans-auth/restv1/register?client_id=05fd2650-8478-4bca-9488-b14f7219473b",
"tls_client_auth_subject_dn": "",
"run_introspection_script_before_jwt_creation": false,
"registration_access_token": "872ab5ca-457a-4118–95cf-d699dc549967",
"client_id": "05fd2650–8478–4bca-9488-b14f7219473b",
"token_endpoint_auth_method": "client_secret_basic",
"scope": "openid",
"client_secret": "97c734ca-a729–49b7–9ec3–514e43ba530b",
"client_id_issued_at": 1693571537,
"backchannel_logout_uri": [],
"backchannel_logout_session_required": false,
"client_name": "DPoPAppClient-bc041d99–2c02–4622–8b6b",
"par_lifetime": 600,
"spontaneous_scopes": [],
"id_token_signed_response_alg": "RS256",
"access_token_as_jwt": false,
"grant_types": ["authorization_code"],
"subject_type": "pairwise",
"additional_token_endpoint_auth_methods": [],
"keep_client_authorization_after_expiration": false,
"require_par": false,
"redirect_uris": ["https://your.janssen.server"],
"redirect_uris_regex": "",
"additional_audience": [],
"frontchannel_logout_session_required": false,
"client_secret_expires_at": 0,
"access_token_signing_alg": "RS256",
"response_types": ["code"]
}
How to do a multi-step backchannel authn flow.
After successful Dynamic Client Registration (DCR), the app saves the OIDC client details in the SQLite database. Each time the user opens the app, it checks for these details and, if present, proceeds directly to the passkey enrollment page where the user submits username and password to continue with the backchannel authentication flow using the Authorization Challenge Endpoint.
The Authorization Challenge Endpoint allows a first-party native client to obtain an authorization code, which can then be exchanged for an access token, enabling a fully browserless OAuth 2.0 experience for native applications. This endpoint adheres to the OAuth 2.0 for First-Party Native Applications specifications.
########
Request
########
curl -k https://your.janssen.server/jans-auth/restv1/authorization_challenge -d 'username=admin' -d 'password=secret' -d 'state=0x74ab847000' -d 'nonce=8974ab847000' -d 'client_id=05fd2650–8478–4bca-9488-b14f7219473b' -d 'auth_method=enrol'
########
Response
########
{"authorization_code":"cdf09c4a-10f4–467e-9f6f-a697db44b108"}
Auth Server provides AuthorizationChallengeType custom script which must be used to control Authorization Challenge Endpoint behavior. During user enrollment in aap, username and password verification is expertly guided by the Authorization Challenge script. The script has been enhanced to incorporate passkey verification during the enrolled user's authentication process. Include an authMethod parameter with values enrol or authenticate in the Authorization Challenge request. This allows the custom script to decide whether to enroll the user (executing username/password verification) or authenticate the user (executing passkey verification).
How to register (new user) using passkeys or authenticate.
How to obtain a normal OAuth token, and DPoP access tokens--requires token verifier to validate htm
and htu
against request.
Build either an iOS or Android app that authenticates against a local Jans install.