Skip to content

DPoP Mobile App POC

Arnab Dutta edited this page Nov 28, 2023 · 21 revisions

Steps followed in App for DPoP Authentication

1. Fetch OpenID Provider Configuration

a. On the client registration (DCR) screen user enters the OpenID Provider Configuration URL and scope.

b. On click of the Register button the app fetches OpenID Provider configuration using URL and stores it in SQLite database table of android.

2. DCR with attestation

The app extracts registration_endpoint from OpenID Provider configuration and requests for DCR with attestation.

------------
Request
------------
curl -X POST -k -H 'Content-Type: application/json' -i 'https://admin-ui-test.gluu.org/jans-auth/restv1/register' --data '{
"application_type":"web",
"client_name":"DPoPAppClient-bc041d99-2c02-4622-8b6b",
"evidence":"eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlJTMjU2IiwiandrIjp7ImUiOiJBUUFCIiwia3R5IjoiUlNBIiwibiI6IjNwMmN1aXNjOFJ3U0VYN1dEYUxUamlQRUJ1bVZnTlIzVm96MnBobGh0aDV3Y2R4aGZ3aFpUcFRvOHJUWFBSbWozUWM5ck1jOGo5djM5MWZKbXhmSWpWM2Q0YUJVZm5aOS00VFJzdmlXVEJIN2RkODBtWTZhcnl5OTBaY0ZmTHdNektzSG1ITHJfTENJUjNKZ3F1MG1TTm9EUHFjTmNFcVVPZVZxVTV2YnRXUHJMdVNlMEJTNmxaRDQ2aXZBSWttOUJhb2xqT1NEcGJvV2gtUW5nMzBVQTJhZnhHN05JVjlwV1Y2S2hka0h1dUtDUXN1RlRpa2Z6cGlWQVRaLTlFcllUU1hOMDVqT0RJUk5Mc1FnV0NyUnBiMEdheGlick5OWTZmcWF2dkgycDJGaXlnbEFaUnBqTDhRNkVWd0Noek9uT1BySkpDZXdCdTdHVFZ4dVZuaHc0dyJ9fQ.eyJhYXBOYW1lIjoiRFBvUEFwcCIsImlhdCI6MTY5MzU2OTQ0ODUwMywic2VxIjoiYzlmMWFhOTUtNGZhNi00NGQ4LTljNTYtYzhkNDcwNGJlMTQyIiwianRpIjoiZWRlYWQxOWQtYzQ1Yy00NDVhLWFlN2ItZTM2NjRiOTBhY2ZjIn0.OQhT-lzYIUWRb4YV4tZNHHTOKAZOax8yZW3HONxLNIvUsxTeS7zB55G5M8WmdwVA4UTcRL6oBj_j-Ep_r6X1fx9ZaJ-SmGCONgC8LxHPmWJCb1eQxYq-7S-CWTtS-SCK4FW473Kg-Kk_FSlyy5tFbH5p_x_CTiPuTgWK5Ct9OwbJ9tyaaiqeXoRgBUEjjjElSYoZqutFbe1WmKrlwblVtXc47JzaZBbnDt3Goukz1HUln_xL0sT_CnxaTVLKdAT7IIfK5UuVIEiKvoqathMdKlqynrn9kyLXwflpMWbirWrQxIpIbkQ6srHStyDDh1zBEyYNAj-pXz9iyhHULoz0Ig",
"grant_types":["authorization_code"],
"jwks":"{\"keys\":[{\"e\":\"AQAB\",\"kty\":\"RSA\",\"n\":\"pzVIV71wHi1fG3TEcCUJw0uolOBUryEJPy8IFpI20lAWqWw5prPn2mPqsyaOPpQtNX2_12PmZjlDq3SjInipSK_saSJ4pm-LCTOYZm55n5QbiK-iCR0DgCVlAeNj6YIenk1Tdy0KSuYoZxOL7iOdMAT9f7qvRAlSdWivOef_tDEtCIbZ3aKoNujv0xPUmOgnZ0U1QdxK3bmprV08O6dV6-_GJBeEdGZ5qZezPIxyjaxiGcoDk47QxdFz-aD38md-zQDEr9toU08j08bgeZLvbVr5e_M-fzhGY5yEISg1e-87n_v3HbdKFGuRFqYp3CYVayuYMWJsIIq8aEPZxdi8qw\"}]}",
"redirect_uris":["https://admin-ui-test.gluu.org"],
"response_types":["code"],
"scope":"openid"
}'

------------
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://admin-ui-test.gluu.org/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://admin-ui-test.gluu.org"],
  "redirect_uris_regex": "",
  "additional_audience": [],
  "frontchannel_logout_session_required": false,
  "client_secret_expires_at": 0,
  "access_token_signing_alg": "RS256",
  "response_types": ["code"]
}

3. Execute Authorization Challenge Endpoint to get the Authorization Code

a. Once DCR is successful the app save OIDC client details in SqlLite DB. Every time the user opens the app, it check if the client details are present in DB. If yes, then it directly forwards to Login page asking for username/password.

b. On submitting username/password the app extracts authorization_challenge_endpoint from the OpenID Provider configuration and requests to get the Authorization Code.

------------
Request
------------

curl -k https://admin-ui-test.gluu.org/jans-auth/restv1/authorization_challenge -d 'grant_type=authorization_code' -d 'scope=openid' -d 'username=admin' -d 'password=secret' -d 'state=0x74ab847000' -d 'nonce=8974ab847000' -d 'client_id=05fd2650-8478-4bca-9488-b14f7219473b'

------------
Response
------------
{"authorization_code":"cdf09c4a-10f4-467e-9f6f-a697db44b108"}

4. DPop Token using Authorization Code.

The app extracts token_endpoint from the OpenID Provider configuration and requests to get the access_token.

------------
Request
------------

curl -k -u '05fd2650-8478-4bca-9488-b14f7219473b:97c734ca-a729-49b7-9ec3-514e43ba530b' -H 'DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlJTMjU2IiwiandrIjp7ImUiOiJBUUFCIiwia3R5IjoiUlNBIiwibiI6IjNwMmN1aXNjOFJ3U0VYN1dEYUxUamlQRUJ1bVZnTlIzVm96MnBobGh0aDV3Y2R4aGZ3aFpUcFRvOHJUWFBSbWozUWM5ck1jOGo5djM5MWZKbXhmSWpWM2Q0YUJVZm5aOS00VFJzdmlXVEJIN2RkODBtWTZhcnl5OTBaY0ZmTHdNektzSG1ITHJfTENJUjNKZ3F1MG1TTm9EUHFjTmNFcVVPZVZxVTV2YnRXUHJMdVNlMEJTNmxaRDQ2aXZBSWttOUJhb2xqT1NEcGJvV2gtUW5nMzBVQTJhZnhHN05JVjlwV1Y2S2hka0h1dUtDUXN1RlRpa2Z6cGlWQVRaLTlFcllUU1hOMDVqT0RJUk5Mc1FnV0NyUnBiMEdheGlick5OWTZmcWF2dkgycDJGaXlnbEFaUnBqTDhRNkVWd0Noek9uT1BySkpDZXdCdTdHVFZ4dVZuaHc0dyJ9fQ.eyJodG0iOiJQT1NUIiwiaHR1IjoiaHR0cHM6Ly9hZG1pbi11aS10ZXN0LmdsdXUub3JnIiwiaWF0IjoxNjkzNTY5NDg0NTQ0LCJqdGkiOiI1MWY0ZWRkYy00MzZjLTRjMmQtYmU1OS1mZjkzNTNiNDI0OTQifQ.MLCDkwyaWVV5kiowWJdnvT241zL0UwMrZ5Kes-uQ_12tKROC0BSZkf2PQ08PcA9nGEw5Ab4MPJOOQlLZAXqkiI7W2zx9BjLIWnRkkSkCS3ucRIfJWxvuQ4W1bfbtUvy9UTZ3UZSD4pxdsZSoGRADePH6JEJy4GkWH6qMrCHeLr2YEjeaBPzJ3Z4YazX8p7kt7_dbNz56hU78hiqu9JetM0-9_5CLqxbomsc8KzreWZ-Mazt_iJJHp_pEKZouClbieKsI_lWfko7MyzxIZNJm6FKdMtCi8SWsXRnuLUkNES0TBe61-yJjqRFqJGZ9BOmwIo8txkmuFHqd403ibaPiiw' https://admin-ui-test.gluu.org/jans-auth/restv1/token -d 'grant_type=authorization_code' -d 'scope=openid' -d 'code=c13327d9-9a1c-41f7-8d3c-06d83ee7f69f' -d 'redirect_uri=https://admin-ui-test.gluu.org/callback'

------------
Response
------------

{"access_token":"fb49e7e7-2831-4dfd-8947-30ea2c6f305e","scope":"openid","id_token":"eyJraWQiOiJjb25uZWN0X2E4MWQyZWIzLTY2YTYtNGEzOS1hN2I2LTEzODBiMzAzYTYwNl9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiTG5ocnFjR0ZiYmw1X3ZCaG1Yanc1ZyIsInN1YiI6IkxVS0RHR0Q3aXQtb3lqUFE3akV6RV90WF9IZVVvcVRjeU1weTNNZ0ZIa0EiLCJhbXIiOltdLCJpc3MiOiJodHRwczovL2FkbWluLXVpLXRlc3QuZ2x1dS5vcmciLCJub25jZSI6Ijg5NzRhYjg0NzAwMCIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiMDVmZDI2NTAtODQ3OC00YmNhLTk0ODgtYjE0ZjcyMTk0NzNiIiwicmFuZG9tIjoiMDg4ZmQ5MTUtNDA5NC00NDgxLTlkODEtZTllZDdhMTY3MGE3IiwiYWNyIjoiZGVmYXVsdF9jaGFsbGVuZ2UiLCJjX2hhc2giOiJjZmJ0d0ZWek51QzhpVDFFQWtJdGlnIiwiYXV0aF90aW1lIjoxNjkzNTc0Mzg0LCJleHAiOjE2OTM1NzgwMTgsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjkzNTc0NDE4fQ.ODhYZTdC0IJjidUAMyVbRKKoovyW1-2AdzVPtn6tx232Vjx6Mxs-Sng57YV6lUdjFLbYfmUjn5JM90Zg3buJHpu6gZKaLs_44j-1i9NbJrAFhe_6libXO0Bib4v5vacYx_0zllXO5FklDdvctahxFc9-xG8pTolkqEGJGjILyNI70NOjodZxBTPPZDBSER9MnD0V_CmRM0izonroV_HyvWDCbTJm9sjBufoY2UkpKCYpyKytu5zSUFq6gq3DEX661Vx_ANgpzy_0BkJgfQ4-juvVPoBdcQnqK7akpwgqyf82NK-pFSZXdduO1Z343L_uYyzzurEkMHf6s_8jre4EXw","token_type":"DPoP","expires_in":299}

5. Get User Info

The app extracts userinfo_endpoint from the OpenID Provider configuration and requests to user-info.

------------
Request
------------

curl -k  -H 'Authorization=Bearer fb49e7e7-2831-4dfd-8947-30ea2c6f305e' https://admin-ui-test.gluu.org/jans-auth/restv1/userinfo -d 'access_token=fb49e7e7-2831-4dfd-8947-30ea2c6f305e'

------------
Response
------------

{"sub":"LUKDGGD7it-oyjPQ7jEzE_tX_HeUoqTcyMpy3MgFHkA"}

6. Logout

The access token is revoked in the logout process.

**References: ** https://github.com/JanssenProject/jans/wiki/Mobile-DPoP-FIDO-Authn

FIDO Registration and Authentication

  1. Using BiometricPrompt which provides a consistent user interface to fingerprint registration/authentication.

App reference: https://github.com/duo-labs/android-webauthn-authenticator

Webauthn Registration

**Reference: ** https://developers.yubico.com/WebAuthn/WebAuthn_Developer_Guide/WebAuthn_Client_Authentication.html https://webauthn.guide/#registration

image

title WebAuthn Registration Flow for Native App

actor User

User->Android App: submit username, displayName
Android App->jans-fido: POST attestation/options \n { "username": "admin",\n "displayName": "admin",\n  "attestation": "none"}
jans-fido->Android App: PublicKeyCredentialCreationOptions:\n {"attestation": "none",\n "authenticatorSelection": {},\n "challenge": "vr27LUiJZF2CN4AncVTsAWlJzAVNsofcr8zM3Ej2Dk8",\n "pubKeyCredParams": [...],\n "rp": {...},\n "user": {...}}
Android App->Android App:Authenticator code will do following:\n 1. create a new asymmetric key pair and safely store the private key\n 2. The public key becomes part of the attestation, which the authenticator signs over with the attestation private key.\n 3. public key, a credential id, and other attestation data are returned to the browser where they become the attestationObject
Android App->jans-fido: POST /attestation/result\n {  "id": "X9FrwMfmzj...",\n "response": { "attestationObject": "o2NmbXRoZmlk...",\n "clientDataJSON": "eyJjaGFsbGVuZ..."},\n  "clientExtensionResults": {}}
jans-fido->jans-fido: 1. Verify the signature over the clientDataHash and the attestation\n 2. verify registration data
Android App->jans-fido: created credentials response

Webauthn Authentication

Wiki WIP (It will use /assertion/options and /assertion/result of jans-fido)

Clone this wiki locally