Validating an ADFS JWT

Rory Braybrook
The new control plane
2 min readJul 24, 2019

This applies to ADFS 4.0 (Server 2016) and upwards.

I ‘m often asked how to validate a JWT, particularly in the context of OpenID Connect / OAuth on ADFS.

Normally this is all part of the ADAL / MSAL stack but people are curious as to how it works and sometimes you aren’t using those stacks and need to do it manually.

Then I came across this post so I thought I would alter it so that it works with ADFS. It’s a console application.

The gist is here.

We point to the “.well-known /openid-configuration” ADFS URL. This is where the public keys are to be found. These keys are used to validate the signature.

In “ TokenValidationParameters”, we tell the routine to check the “Issuer”, “Audience” and the signature.

The routine automatically checks for things like JWT expiry.

IdentityModelEventSource.ShowPII = true;

This is for debugging as it shows the full error message when a JWT fails validation. Turn this off in Production!

Any errors are displayed e.g.

Error occurred while validating token: IDX10223: Lifetime validation failed. The token is expired. ValidTo: ‘07/24/2019 01:39:59’, Current time: ‘07/24/2019 01:50:38’.

Press ENTER to continue…

You need to get your JWT and copy it into “ testToken”.

The ADFS application group that I used to get the JWT has the custom claim rule:

c:[]
=> issue(claim = c);

i.e. issue all claims.

Running this shows:

Token is validated.

aud https://localhost:44321/
iss
http://my-adfs/adfs/services/trust
iat 1563993512
exp 1563997112
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/implicitupn user4@test.dev.com
throttled false
amp FormsAuthentication
auth_time “2019–07–24T18:38:32.006Z”
http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
anchor winaccountname
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn user4@test.dev.com
http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid S-1–5–21–987684069–589093365–2141957508–513
http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid S-1–5–21–987684069–589093365–2141957508–16101
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name TEST\user4
http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname TEST\user4
http://schemas.microsoft.com/claims/authnmethodsreferences urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid S-1–5–21–987684069–589093365–2141957508–513
http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid S-1–1–0
http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid S-1–5–32–545
http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid S-1–5–32–554
http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid S-1–5–2
http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid S-1–5–11
http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid S-1–5–15
http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid S-1–18–2
appid 74a2038e-f26f-40c2-ad4d-a0224a048ddd
apptype Public
http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-endpoint-absolute-path /adfs/oauth2/authorize
insidecorpnetwork true
clientreqid ea4738c8–928e-419c-0200–0080000000b8
http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-ip IP1.x.x.x
userip IP2.y.y.y
ver 1.0
http://schemas.microsoft.com/identity/claims/scope email

{“alg”:”RS256",”typ”:”JWT”,”x5t”:”wosG0Hf3r1NuSnPnW4ZbYUJdjWI”}.{“aud”:”https://localhost:44321/","iss":"http://my-adfs/adfs/services/trust","iat":1563993512,"exp":1563997112,"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/implicitupn":"user4@test.dev.com","throttled":"false","amp":"FormsAuthentication","auth_time":"2019-07-24T18:38:32.006Z","authmethod":"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport","anchor":"winaccountname","upn":"user4@test.dev.com","primarygroupsid":"S-1-5-21-987684069-589093365-2141957508-513","primarysid":"S-1-5-21-987684069-589093365-2141957508-16101","unique_name":"TEST\\user4","winaccountname":"TEST\\user4","amr":"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport","groupsid":["S-1-5-21-987684069-589093365-2141957508-513","S-1-1-0","S-1-5-32-545","S-1-5-32-554","S-1-5-2","S-1-5-11","S-1-5-15","S-1-18-2"],"appid":"74a2038e-f26f-40c2-ad4d-a0224a048ddd","apptype":"Public","clientuseragent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0",”endpointpath”:”/adfs/oauth2/authorize”,”insidecorpnetwork”:”true”,”clientreqid”:”ea4738c8–928e-419c-0200–0080000000b8",”clientip”:”IP1.x.x.x",”userip”:”IP2.y.y.y",”ver”:”1.0",”scp”:”email”}

Press ENTER to continue…

All good!

--

--

Rory Braybrook
The new control plane

NZ Microsoft Identity dude and MVP. Azure AD/B2C/ADFS/Auth0/identityserver. StackOverflow: https://bit.ly/2XU4yvJ Presentations: http://bit.ly/334ZPt5