I created this as part of my previous post. Didn’t want to digress there by tacking this to the end of it, so here’s a separate post.
In the previous post I had got my Logic App to consume the Azure AD bearer token used to authenticate against it. How can I parse that though? Here’s what I did, am sure there are other more succint ways too.
First off, one has to parse the Headers. This is JSON, with the following schema:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
{ "type": "object", "properties": { "Connection": { "type": "string" }, "Accept-Encoding": { "type": "string" }, "Accept-Language": { "type": "string" }, "Authorization": { "type": "string" }, "Host": { "type": "string" }, "User-Agent": { "type": "string" }, "x-ms-workflow-id": { "type": "string" }, "x-ms-workflow-version": { "type": "string" }, "x-ms-workflow-name": { "type": "string" }, "x-ms-workflow-system-id": { "type": "string" }, "x-ms-workflow-run-id": { "type": "string" }, "x-ms-workflow-run-tracking-id": { "type": "string" }, "x-ms-workflow-operation-name": { "type": "string" }, "x-ms-execution-location": { "type": "string" }, "x-ms-workflow-subscription-id": { "type": "string" }, "x-ms-workflow-resourcegroup-name": { "type": "string" }, "x-ms-tracking-id": { "type": "string" }, "x-ms-correlation-id": { "type": "string" }, "x-ms-client-request-id": { "type": "string" }, "x-ms-client-tracking-id": { "type": "string" }, "x-ms-action-tracking-id": { "type": "string" }, "x-ms-client-keywords": { "type": "string" }, "x-ms-activity-vector": { "type": "string" }, "X-Forwarded-For": { "type": "string" }, "X-MS-APIM-Referrer": { "type": "string" }, "x-ms-client-region": { "type": "string" }, "x-ms-flavor": { "type": "string" }, "x-ms-gateway-object-id": { "type": "string" }, "X-MS-APIM-Referrer-Prefix": { "type": "string" }, "X-MS-APIM-Callback": { "type": "string" }, "Content-Length": { "type": "string" }, "Content-Type": { "type": "string" } } } |
I got this by looking at the Headers sent to a Logic App by making it return the Headers as response.
So, step 1: parse the Headers using this schema.
Capture the “Authorization” key into a variable.
Then create a new variable called “BearerToken” that has just the token. “Authorization” key is of the format “Bearer xxx
” so I split along the space and get the second element. Here’s the expression I am using: split(variables('AuthorizationHeader'),' ')[1]
Next I need to get the body from the token. The token is split up of three dot separated parts – hhhh.bbbb.ssss – the headers, body, and signature. We need the body. So split this along the dot, get the second element.
The expression is: split(variables('BearerToken'),'.')[1]
Ideally the next step would be to decode this text (which is Base64) and parse that. But I ran into an issue. Whenever I’d parse the JSON I kept getting this error: 'The template language function 'base64ToString' was invoked with a parameter that is not valid. The value cannot be decoded from base64 representation
Then I remembered an issue I had when parsing JSON from a Base64 decoded string in PowerShell. If the Base64 string isn’t a multiple of 4 PowerShell fails when decoding. Maybe it was the same issue here… so I added some logic to check if the string length is a multiple of 4 and if not add some ‘=’ characters (doesn’t matter what you add).
The expression is: mod(length(variables('BearerTokenBody')),4)
Finally I parse the token using the following schema:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
{ "type": "object", "properties": { "aud": { "type": "string" }, "iss": { "type": "string" }, "iat": { "type": "integer" }, "nbf": { "type": "integer" }, "exp": { "type": "integer" }, "_claim_names": { "type": "object", "properties": { "groups": { "type": "string" } } }, "_claim_sources": { "type": "object", "properties": { "src1": { "type": "object", "properties": { "endpoint": { "type": "string" } } } } }, "acr": { "type": "string" }, "aio": { "type": "string" }, "amr": { "type": "array", "items": { "type": "string" } }, "appid": { "type": "string" }, "appidacr": { "type": "string" }, "family_name": { "type": "string" }, "given_name": { "type": "string" }, "ipaddr": { "type": "string" }, "name": { "type": "string" }, "oid": { "type": "string" }, "onprem_sid": { "type": "string" }, "puid": { "type": "string" }, "rh": { "type": "string" }, "scp": { "type": "string" }, "sub": { "type": "string" }, "tid": { "type": "string" }, "unique_name": { "type": "string" }, "upn": { "type": "string" }, "uti": { "type": "string" }, "ver": { "type": "string" }, "wids": { "type": "array", "items": { "type": "string" } }, "xms_tcdt": { "type": "integer" } } } |
And that’s it, now I can see all the claims:
Interestingly, one of the claims is appid. I was curious what this is… turns out it is “7ab7862c-4c57-491e-8a45-d52a7e023983” in my case. Googling on that gives me the impression this is a standard id. I know, for example, Graph has an id of “00000003-0000-0000-c000-000000000000” and in the past I’ve found some more ids in a blog post, so this must be similar. That’s how I am able to authenticate in Power Automate without creating an App Registration, it must be using a well known App Id from Microsoft.
Update: See this post for what the Id is.