Add custom claims in Access Token using actions/rules for SMART on FHIR

Hi Team,

I am working on SMART on FHIR, where I need to integrate the AUTH0 for authentication. To make it work, I need few customization in /token API response.

I was using the smart launcher and as shown in the screenshot, I need to modify the AccessToken and IdToken to send the additional data (patient and scope on the AccessToken and profile and fhirUser on IdToken)

So the expected json are:

  • Access Token Response
{
    "need_patient_banner": false,
    "smart_style_url": "https://launch.smarthealthit.org/smart-style.json",
    "patient": "87a339d0-8cae-418e-89c7-8651e6aab3c6",
    "encounter": "418e38cf-9da6-4155-b205-0be24024b1db",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb250ZXh0Ijp7Im5lZWRfcGF0aWVudF9iYW5uZXIiOmZhbHNlLCJzbWFydF9zdHlsZV91cmwiOiJodHRwczovL2xhdW5jaC5zbWFydGhlYWx0aGl0Lm9yZy9zbWFydC1zdHlsZS5qc29uIiwicGF0aWVudCI6Ijg3YTMzOWQwLThjYWUtNDE4ZS04OWM3LTg2NTFlNmFhYjNjNiIsImVuY291bnRlciI6IjQxOGUzOGNmLTlkYTYtNDE1NS1iMjA1LTBiZTI0MDI0YjFkYiJ9LCJjbGllbnRfaWQiOiJ3aGF0ZXZlciIsInNjb3BlIjoicGF0aWVudC8qLiogdXNlci8qLiogbGF1bmNoIG9wZW5pZCBmaGlyVXNlciBwcm9maWxlIG9mZmxpbmVfYWNjZXNzIiwidXNlciI6IlBhdGllbnQvODdhMzM5ZDAtOGNhZS00MThlLTg5YzctODY1MWU2YWFiM2M2IiwiaWF0IjoxNjY3MTk0MzQxLCJleHAiOjE2OTg3MzAzNDF9.EOIhOCctpm36H7iY4sJ65kscD2Htu_J17OlyXak4Jkc",
    "token_type": "bearer",
    "scope": "patient/*. user/*. launch openid fhirUser profile offline_access",
    "client_id": "whatever",
    "expires_in": 3600,
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9maWxlIjoiUGF0aWVudC84N2EzMzlkMC04Y2FlLTQxOGUtODljNy04NjUxZTZhYWIzYzYiLCJmaGlyVXNlciI6IlBhdGllbnQvODdhMzM5ZDAtOGNhZS00MThlLTg5YzctODY1MWU2YWFiM2M2IiwiYXVkIjoid2hhdGV2ZXIiLCJzdWIiOiJmNWFlZDBlODJmYzRjZmQ5NmQwMjc2YjBmMWIyOGJhNDFmY2FiNGE4NTcwNjY4OGU4NjM1M2VjMGEyMTQ3MzA1IiwiaXNzIjoiaHR0cHM6Ly9sYXVuY2guc21hcnRoZWFsdGhpdC5vcmcvdi9yNC9maGlyIiwiaWF0IjoxNjY3MTk0MzQzLCJleHAiOjE2NjcxOTc5NDN9.AEwuOrclv_wheaXBWXdHcLBseNiw00--tiIR7F5PcrSlOsLdWzEqpA2zJ5I5KGUHJLxQtdKUne26NVo7V2ooOxT8QHjYv_0ddKOEvGzitTr3Fnvk4wM3ZGh24n1ZeLr3ZeZnuhIGBNTgnOGdUa0wOlgMcaECALWMKDjBs9KoLgMkb6sySpZNRtcRJXBk9RP_gf7xpAbw6LHxwq1yr4yRRCluS1DtCP220TpXJN9rqD1EWWRs-CCs9dQBsV0McEsoB9TNQTEuzcKc88Ghp-V_r_LfcISuqd12_XD5G778J4GIpVn4A2cmyfr8CmHq3NzPW3vlI84Vcmq5T7_RpUqZMA",
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuZWVkX3BhdGllbnRfYmFubmVyIjpmYWxzZSwic21hcnRfc3R5bGVfdXJsIjoiaHR0cHM6Ly9sYXVuY2guc21hcnRoZWFsdGhpdC5vcmcvc21hcnQtc3R5bGUuanNvbiIsInBhdGllbnQiOiI4N2EzMzlkMC04Y2FlLTQxOGUtODljNy04NjUxZTZhYWIzYzYiLCJlbmNvdW50ZXIiOiI0MThlMzhjZi05ZGE2LTQxNTUtYjIwNS0wYmUyNDAyNGIxZGIiLCJyZWZyZXNoX3Rva2VuIjoiZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SmpiMjUwWlhoMElqcDdJbTVsWldSZmNHRjBhV1Z1ZEY5aVlXNXVaWElpT21aaGJITmxMQ0p6YldGeWRGOXpkSGxzWlY5MWNtd2lPaUpvZEhSd2N6b3ZMMnhoZFc1amFDNXpiV0Z5ZEdobFlXeDBhR2wwTG05eVp5OXpiV0Z5ZEMxemRIbHNaUzVxYzI5dUlpd2ljR0YwYVdWdWRDSTZJamczWVRNek9XUXdMVGhqWVdVdE5ERTRaUzA0T1dNM0xUZzJOVEZsTm1GaFlqTmpOaUlzSW1WdVkyOTFiblJsY2lJNklqUXhPR1V6T0dObUxUbGtZVFl0TkRFMU5TMWlNakExTFRCaVpUSTBNREkwWWpGa1lpSjlMQ0pqYkdsbGJuUmZhV1FpT2lKM2FHRjBaWFpsY2lJc0luTmpiM0JsSWpvaWNHRjBhV1Z1ZEM4cUxpb2dkWE5sY2k4cUxpb2diR0YxYm1Ob0lHOXdaVzVwWkNCbWFHbHlWWE5sY2lCd2NtOW1hV3hsSUc5bVpteHBibVZmWVdOalpYTnpJaXdpZFhObGNpSTZJbEJoZEdsbGJuUXZPRGRoTXpNNVpEQXRPR05oWlMwME1UaGxMVGc1WXpjdE9EWTFNV1UyWVdGaU0yTTJJaXdpYVdGMElqb3hOalkzTVRrME16UXhMQ0psZUhBaU9qRTJPVGczTXpBek5ERjkuRU9JaE9DY3RwbTM2SDdpWTRzSjY1a3NjRDJIdHVfSjE3T2x5WGFrNEprYyIsInRva2VuX3R5cGUiOiJiZWFyZXIiLCJzY29wZSI6InBhdGllbnQvKi4qIHVzZXIvKi4qIGxhdW5jaCBvcGVuaWQgZmhpclVzZXIgcHJvZmlsZSBvZmZsaW5lX2FjY2VzcyIsImNsaWVudF9pZCI6IndoYXRldmVyIiwiZXhwaXJlc19pbiI6MzYwMCwiaWRfdG9rZW4iOiJleUpoYkdjaU9pSlNVekkxTmlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKd2NtOW1hV3hsSWpvaVVHRjBhV1Z1ZEM4NE4yRXpNemxrTUMwNFkyRmxMVFF4T0dVdE9EbGpOeTA0TmpVeFpUWmhZV0l6WXpZaUxDSm1hR2x5VlhObGNpSTZJbEJoZEdsbGJuUXZPRGRoTXpNNVpEQXRPR05oWlMwME1UaGxMVGc1WXpjdE9EWTFNV1UyWVdGaU0yTTJJaXdpWVhWa0lqb2lkMmhoZEdWMlpYSWlMQ0p6ZFdJaU9pSm1OV0ZsWkRCbE9ESm1ZelJqWm1RNU5tUXdNamMyWWpCbU1XSXlPR0poTkRGbVkyRmlOR0U0TlRjd05qWTRPR1U0TmpNMU0yVmpNR0V5TVRRM016QTFJaXdpYVhOeklqb2lhSFIwY0hNNkx5OXNZWFZ1WTJndWMyMWhjblJvWldGc2RHaHBkQzV2Y21jdmRpOXlOQzltYUdseUlpd2lhV0YwSWpveE5qWTNNVGswTXpRekxDSmxlSEFpT2pFMk5qY3hPVGM1TkROOS5BRXd1T3JjbHZfd2hlYVhCV1hkSGNMQnNlTml3MDAtLXRpSVI3RjVQY3JTbE9zTGRXekVxcEEyeko1STVLR1VISkx4UXRkS1VuZTI2TlZvN1Yyb29PeFQ4UUhqWXZfMGRkS09Fdkd6aXRUcjNGbnZrNHdNM1pHaDI0bjFaZUxyM1plWm51aElHQk5UZ25PR2RVYTB3T2xnTWNhRUNBTFdNS0RqQnM5S29MZ01rYjZzeVNwWk5SdGNSSlhCazlSUF9nZjd4cEFidzZMSHh3cTF5cjR5UlJDbHVTMUR0Q1AyMjBUcFhKTjlycUQxRVdXUnMtQ0NzOWRRQnNWME1jRXNvQjlUTlFURXV6Y0tjODhHaHAtVl9yX0xmY0lTdXFkMTJfWEQ1Rzc3OEo0R0lwVm40QTJjbXlmcjhDbUhxM056UFczdmxJODRWY21xNVQ3X1JwVXFaTUEiLCJpYXQiOjE2NjcxOTQzNDMsImV4cCI6MTY2NzE5Nzk0M30.KqqnXwdtAf38AzuTIv05xSPFoYSgje5M49txoMjn2BU",
    "code": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb250ZXh0Ijp7Im5lZWRfcGF0aWVudF9iYW5uZXIiOmZhbHNlLCJzbWFydF9zdHlsZV91cmwiOiJodHRwczovL2xhdW5jaC5zbWFydGhlYWx0aGl0Lm9yZy9zbWFydC1zdHlsZS5qc29uIiwicGF0aWVudCI6Ijg3YTMzOWQwLThjYWUtNDE4ZS04OWM3LTg2NTFlNmFhYjNjNiIsImVuY291bnRlciI6IjQxOGUzOGNmLTlkYTYtNDE1NS1iMjA1LTBiZTI0MDI0YjFkYiJ9LCJjbGllbnRfaWQiOiJ3aGF0ZXZlciIsInNjb3BlIjoicGF0aWVudC8qLiogdXNlci8qLiogbGF1bmNoIG9wZW5pZCBmaGlyVXNlciBwcm9maWxlIG9mZmxpbmVfYWNjZXNzIiwidXNlciI6IlBhdGllbnQvODdhMzM5ZDAtOGNhZS00MThlLTg5YzctODY1MWU2YWFiM2M2IiwicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9sYXVuY2guc21hcnRoZWFsdGhpdC5vcmcvc2FtcGxlLWFwcC8iLCJpYXQiOjE2NjcxOTQzNDEsImV4cCI6MTY2NzE5NDY0MX0.iGDLKo-JN8jAY_5Xu30m5Jfk2AluSExG3YqMSITCFUw",
    "state": "7c1f1f9f-c8cd-46c4-abde-e172b59375ed"
}
  • ID Token
{
    "alg": "RS256",
    "typ": "JWT"
}
.
{
    "profile": "Patient/87a339d0-8cae-418e-89c7-8651e6aab3c6",
    "fhirUser": "Patient/87a339d0-8cae-418e-89c7-8651e6aab3c6",
    "aud": "whatever",
    "sub": "f5aed0e82fc4cfd96d0276b0f1b28ba41fcab4a85706688e86353ec0a2147305",
    "iss": "https://launch.smarthealthit.org/v/r4/fhir",
    "iat": 1667194343,
    "exp": 1667197943
}
.
"AEwuOrclv_wheaXBWXdHcLBseNiw00--tiIR7F5PcrSlOsLdWzEqpA2zJ5I5KGUHJLxQtdKUne26NVo7V2ooOxT8QHjYv_0ddKOEvGzitTr3Fnvk4wM3ZGh24n1ZeLr3ZeZnuhIGBNTgnOGdUa0wOlgMcaECALWMKDjBs9KoLgMkb6sySpZNRtcRJXBk9RP_gf7xpAbw6LHxwq1yr4yRRCluS1DtCP220TpXJN9rqD1EWWRs-CCs9dQBsV0McEsoB9TNQTEuzcKc88Ghp-V_r_LfcISuqd12_XD5G778J4GIpVn4A2cmyfr8CmHq3NzPW3vlI84Vcmq5T7_RpUqZMA"

But unfortunately, I am unable to add few additional data in accessToken. Here is the screenshot for my launcher.

The response I am getting is:

  • Access Token Response
{
    "access_token": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYteDJrYWNiNjJvczNwN3VkNC51cy5hdXRoMC5jb20vIn0..QDUX5F59Lv6YrBRC.uobiC9bdyCh9mCJFWviXMYKJyDUOND3ynexIBbPbW0jwO_oAGTEiSUReaIb9GfGJHYFpLkYMUvM1FZsHCmElWUsaZkikriMrsXGV6M0OHvXXVjRk_9poBbp084c2d49KMSW-UFlLzNzNhMj6Y63Pj_f7VFII8O0Mjf0kdxB003t11GlTlb2dVQvy_u7x8bBAvG0I2Iei7hHKeLbrReTFzMA-McWEBh1OdrBQ_O9tfaUmaNQJZUy5z5kcbgHlUDr5AjK2CPFJPuUrqvg0CuYA47REoarBoGCGZlk8DEgyPWV24JukGJjCPLxL4lFcgkYoW0ed0kg3IWQ_78NUFO40li_X-XsHUGxf_oguZDHRYe8zsgAHr7Cbzq8Toic84bCcxTv7T09S9jsmKieVMeu8bOjwRaahDFz1su1blLa4I7WtdYaSTgx9jrs36zAcuomRaJeDLGs02hqaTmfrKr21HWRm.P2IGxJsglqX2jR1hB1NHXw",
    "refresh_token": "v1.MVUn05-VwFVKV6aC3vmyUBqr01x_U9vbJEsBhULde5qtB--e1N4ejd85VRjt0CXVeOeMKNR4zUHWwVyl9seJjZA",
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IkJ2djVrTHNzc3BVNFZ0Ty1uRmM3dyJ9.eyJmaGlyVXNlciI6IlBhdGllbnQvMiIsIm5pY2tuYW1lIjoic2h1YmgwMiIsInByb2ZpbGUiOiJQYXRpZW50LzIiLCJuYW1lIjoic2h1YmgwMkB5b3BtYWlsLmNvbSIsInBpY3R1cmUiOiJodHRwczovL3MuZ3JhdmF0YXIuY29tL2F2YXRhci9iMDA0M2I2ZTljOTJlMWI5OGQ0Yzg4NTUxN2QxZDhmMz9zPTQ4MCZyPXBnJmQ9aHR0cHMlM0ElMkYlMkZjZG4uYXV0aDAuY29tJTJGYXZhdGFycyUyRnNoLnBuZyIsInVwZGF0ZWRfYXQiOiIyMDIyLTEwLTMxVDA1OjMxOjE2LjM5MVoiLCJpc3MiOiJodHRwczovL2Rldi14MmthY2I2Mm9zM3A3dWQ0LnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw2MzU5MWY0OTc5OGFjYzZlYzRlYWU5OWQiLCJhdWQiOiJMVHdxRU15TWF6eDFlVXZtaXBFN3liRE9ranZmdmlQYyIsImlhdCI6MTY2NzE5ODcyNiwiZXhwIjoxNjY3MjM0NzI2LCJzaWQiOiJuSWktXzFtVkpuOU0xSnB5Mlo2alhZS0R0MVdrY1B5RiJ9.OdLNr4Exge_kjt27K8ouVrVknk8MW01OGjtFifTSZAWU75v4FQg1_p8FR_c_hJOsB0jSL2MPVCyu-HtmJpxa5KQ32a4kbcU5rEeFkOwGNNAmCeazVpTzisyOqJ47hPiPaSrbLKEndY0PKCh3IjjN-22ne3aFHtVsQndw2_jNEDVpXvktDuDt-0Fp-4yrA4bjx8fbDXEG2Dl7aWymC8RsYdR768-8zKHPudSrWTcXhDomhLmvVBTu_s9NE9SfvX6Lxt2xKzEUUFqntPELTyw_IkeNxeBoQkz-7SW0YL0dh5fksdD2SEqux4UHGq-mL5BWebF0oynK0Udn58G2nooZGA",
    "scope": "patient/*. user/*. launch openid fhirUser profile offline_access",
    "expires_in": 86400,
    "token_type": "Bearer",
    "code": "DHSzT8wQPUASj81NMatqC8m8-UMzcg6df1EALv7m9BLgm",
    "state": "14475534-a1e7-ad23-796e-0e42e5b97368"
}

  • ID Token
{
    "alg": "RS256",
    "typ": "JWT",
    "kid": "Bvv5kLssspU4VtO-nFc7w"
}
.
{
    "fhirUser": "Patient/2",
    "nickname": "shubh02",
    "profile": "Patient/2",
    "name": "mailto:shubh02@yopmail.com",
    "picture": "https://s.gravatar.com/avatar/b0043b6e9c92e1b98d4c885517d1d8f3?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fsh.png",
    "updated_at": "2022-10-31T05:31:16.391Z",
    "iss": "https://dev-x2kacb62os3p7ud4.us.auth0.com/",
    "sub": "auth0|63591f49798acc6ec4eae99d",
    "aud": "LTwqEMyMazx1eUvmipE7ybDOkjvfviPc",
    "iat": 1667198726,
    "exp": 1667234726,
    "sid": "nIi-_1mVJn9M1Jpy2Z6jXYKDt1WkcPyF"
}
.
"OdLNr4Exge_kjt27K8ouVrVknk8MW01OGjtFifTSZAWU75v4FQg1_p8FR_c_hJOsB0jSL2MPVCyu-HtmJpxa5KQ32a4kbcU5rEeFkOwGNNAmCeazVpTzisyOqJ47hPiPaSrbLKEndY0PKCh3IjjN-22ne3aFHtVsQndw2_jNEDVpXvktDuDt-0Fp-4yrA4bjx8fbDXEG2Dl7aWymC8RsYdR768-8zKHPudSrWTcXhDomhLmvVBTu_s9NE9SfvX6Lxt2xKzEUUFqntPELTyw_IkeNxeBoQkz-7SW0YL0dh5fksdD2SEqux4UHGq-mL5BWebF0oynK0Udn58G2nooZGA"

Approach :

  1. Using Action : I added a custom rule, where I tried to add all the parameters without using the namespace(as we need without namespace).
  • Attempt

api.idToken.setCustomClaim(fhirUser, “Patient/2”);
api.idToken.setCustomClaim(profile, “Patient/2”);
api.accessToken.setCustomClaim(patient, “2”)

  • Issue :
    1. Unable to get the patient field in accessToken
    2. In IdToken, fhirUser & patient field should look like “Patient/:id”, but here id with integer making the idToken JWT as invalid signature.
  1. Using Rules : Using Rules as per auth0 doc for best practice guide for SMART on FHIR
  • Attempt
function (user, context, callback) {
  context.accessToken.scope = [ 
    			"patient/*.*",
                "user/*.*",
                "launch",
                "openid",
                "fhirUser",
                "profile",
                "offline_access"
  ];
  context.idToken.fhirUser = "Patient/2";
  context.idToken.profile = "Patient/2";a
  context.accessToken.patient = 2;
  callback(null, user, context);
}
  • Issue :
    1. Able to get idToken, but if id is alphanumeric then again JWT has invalid signature
    2. Able to modify the scopes but still struggling to add patient param in accessToken.

Pleas let me know how I can solve this issue as I am taking reference from your mentioned guide Best Practices Guide for SMART on FHIR

Also using the smart launcher to validate our parameters.

Thanks in advance.