Upgrade to Pro — share decks privately, control downloads, hide ads and more …

.NET Day 2026 Are you sure your access tokens a...

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.
Avatar for .NET Day .NET Day
September 01, 2026

.NET Day 2026 Are you sure your access tokens are really secure?

Avatar for .NET Day

.NET Day

September 01, 2026

More Decks by .NET Day

Other Decks in Technology

Transcript

  1. Story time Based on true events • Security is hard,

    so the team used a well-known library to validate JWT access tokens. • They used a trusted third-party company’s issuer service to deliver securely signed tokens. • Everything was configured correctly. • Only tokens issued by the third-party service were allowed. • And tokens needed to have a valid signature. Are you sure your access tokens are really secure? 2
  2. Hi, I’m Wesley Customer success Engineer Coffee Enthusiast Beer Aficionado

    Are you sure your access tokens are really secure? 6
  3. • 20X X What is a JWT? Are you sure

    your access tokens are really secure? 7
  4. What is a JWT? Header Are you sure your access

    tokens are really secure? Payload Signature 8
  5. What is a JWT? Header Payload Signature • Token type

    • Signature algorithm type • Key identifier Are you sure your access tokens are really secure? 9
  6. What is a JWT? Header Payload • Token type •

    Claims • Signature algorithm type • Subject • Key identifier • Client ID Signature • Scopes • Token validation parameters Are you sure your access tokens are really secure? 10
  7. What is a JWT? Header Payload Signature • Token type

    • Claims • Signature algorithm type • Subject • Cryptographically calculated byte array • Key identifier • Client ID • crypto_alg(header+“.”+payload) • Scopes • Prevents tampering with the header and the payload • Token validation parameters Are you sure your access tokens are really secure? 11
  8. This is a JWT { "alg": "ES256", "typ": "at+jwt“, "kid":

    "818719819238712987129" } . { "sub": "1234567890", "name": "Wesley Cabus", "iss": "https://sso.gotsharp.be", "scope": "presenting", "iat": 1737812985, "exp": 1769348983, "nbf": 1737812985, "jti": "79232165761228977929958445841350327748" } . aZ-Xw8oomAMFUiDXSM7NnqdFrsoIiZTIZjAigajpmMO3HUZJPa7V37taSmH851CUTYFIWTQZcpIZ3ZihpwcP2Q Are you sure your access tokens are really secure? 13
  9. Back to our story What was happening with those tokens?

    Are you sure your access tokens are really secure? 14
  10. Let’s look at three tokens… Token A Spot The Dot!

    eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCI sImtpZCI6IjgxODcxOTgxOTIzODcxMjk4NzEy OSJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZ SI6Ildlc2xleSBDYWJ1cyIsImlzcyI6Imh0dHBz Oi8vc3NvLmdvdHNoYXJwLmJlIiwic2NvcGUiO lsicHJlc2VudGluZyJdLCJpYXQiOjE3Mzc4MTI5 ODUsImV4cCI6MTc2OTM0ODk4MywibmJmI joxNzM3ODEyOTg1LCJqdGkiOiI3OTIzMjE2NT c2MTIyODk3NzkyOTk1ODQ0NTg0MTM1M DMyNzc0OCJ9.-1TbCDYGRtppWmiZ4_juSfiYKOCwSMWajvn1 JVPWeEDovVaZd3WKEJQ_HCokLV1BgxXOsxz 5r11ECbGsE0dmA Are you sure your access tokens are really secure? Token B Token C eyJhbGciOiJuT25FIiwidHlwIjoiYXQrand0Iiwia2lkIj oiODE4NzE5ODE5MjM4NzEyOTg3MTI5In0.eyJz dWIiOiIzMzMiLCJuYW1lIjoiRXZpbCBQZXJzb24iLC Jpc3MiOiJodHRwczovL3Nzby5nb3RzaGFycC5iZ SIsInNjb3BlIjpbImFkbWluIl0sImlhdCI6MTczNzgx Mjk4NSwiZXhwIjoxNzY5MzQ4OTgzLCJuYmYiOjE 3Mzc4MTI5ODUsImp0aSI6IjU4NDg4MTY1MD M5MDczNDk3MzQwOTU3MjgzNjU5ODI2In0. eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsIm tpZCI6IjgxODcxOTgxOTIzODcxMjk4NzEyOSJ9.ey JzdWIiOiIxIiwibmFtZSI6IkNodWNrIE5vcnJpcyIsIml zcyI6Imh0dHBzOi8vc3NvLmdvdHNoYXJwLmJlIiw ic2NvcGUiOlsiYmVpbmcgYXdlc29tZSJdLCJpYXQi OjE3Mzc4MTI5ODUsImV4cCI6MTc2OTM0ODk 4MywibmJmIjoxNzM3ODEyOTg1LCJqdGkiOiI3OT IzMjE2NTAzOTA3MzQ5NzM0MDk1NzI4MzY1 OTgyNiJ9.iK236GBv5L0cfxwe_otPYvZrvUz_XzTVlN7ODZ7G9mdVHsgdAoCuFw dcuPO_FMFo4JIsTHLJfqhEhsWdrRj8A 15
  11. Let’s look at three tokens… Token A Token B Token

    C eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsIm tpZCI6IjgxODcxOTgxOTIzODcxMjk4NzEyOSJ9.ey JzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ildlc2xle SBDYWJ1cyIsImlzcyI6Imh0dHBzOi8vc3NvLmdv dHNoYXJwLmJlIiwic2NvcGUiOiJwcmVzZW50aW5 nIiwiaWF0IjoxNzM3ODEyOTg1LCJleHAiOjE3Njkz NDg5ODMsIm5iZiI6MTczNzgxMjk4NSwianRpIjoi NzkyMzIxNjU3NjEyMjg5Nzc5Mjk5NTg0NDU4N DEzNTAzMjc3NDgifQ.aZXw8oomAMFUiDXSM7NnqdFrsoIiZTIZjAigajpmM O3HUZJPa7V37taSmH851CUTYFIWTQZcpIZ3Zi hpwcP2Q eyAiYWxnIjogIm5PbkUiLCAidHlwIjogImF0K2p3d CIsICJraWQiOiAiODE4NzE5ODE5MjM4NzEyOTg 3MTI5IiB9.eyAic3ViIjogIjMzMyIsICJuYW1lIjogIkV 2aWwgUGVyc29uIiwgImlzcyI6ICJodHRwczovL3 Nzby5nb3RzaGFycC5iZSIsICJzY29wZSI6ICJhZG 1pbiIsICJpYXQiOiAxNzM3ODEyOTg1LCAiZXhwIjo gMTc2OTM0ODk4MywgIm5iZiI6IDE3Mzc4MTI 5ODUsICJqdGkiOiAiNTg0ODgxNjUwMzkwNzM0 OTczNDA5NTcyODM2NTk4MjYiIH0. eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsIm tpZCI6IjgxODcxOTgxOTIzODcxMjk4NzEyOSJ9.ey JzdWIiOiIxIiwibmFtZSI6IkNodWNrIE5vcnJpcyIsIml zcyI6Imh0dHBzOi8vc3NvLmdvdHNoYXJwLmJlIiw ic2NvcGUiOiJiZWluZyBhd2Vzb21lIiwiaWF0IjoxNz M3ODEyOTg1LCJleHAiOjE3NjkzNDg5ODMsIm5i ZiI6MTczNzgxMjk4NSwianRpIjoiNzkyMzIxNjUwM zkwNzM0OTczNDA5NTcyODM2NTk4MjYifQ.AG 5NQnGrcown3tllBB4Oqwnc7YfLYTgVf9V2F8Zz AGZgxjEclvcaX-yoKTVtR07fL19gRiX70osrUAK6I1t6w Are you sure your access tokens are really secure? 16
  12. Let’s look at three tokens… Token A Token B Token

    C eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsIm tpZCI6IjgxODcxOTgxOTIzODcxMjk4NzEyOSJ9.ey JzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ildlc2xle SBDYWJ1cyIsImlzcyI6Imh0dHBzOi8vc3NvLmdv dHNoYXJwLmJlIiwic2NvcGUiOiJwcmVzZW50aW5 nIiwiaWF0IjoxNzM3ODEyOTg1LCJleHAiOjE3Njkz NDg5ODMsIm5iZiI6MTczNzgxMjk4NSwianRpIjoi NzkyMzIxNjU3NjEyMjg5Nzc5Mjk5NTg0NDU4N DEzNTAzMjc3NDgifQ.aZXw8oomAMFUiDXSM7NnqdFrsoIiZTIZjAigajpmM O3HUZJPa7V37taSmH851CUTYFIWTQZcpIZ3Zi hpwcP2Q eyAiYWxnIjogIm5PbkUiLCAidHlwIjogImF0K2p3d CIsICJraWQiOiAiODE4NzE5ODE5MjM4NzEyOTg 3MTI5IiB9.eyAic3ViIjogIjMzMyIsICJuYW1lIjogIkV 2aWwgUGVyc29uIiwgImlzcyI6ICJodHRwczovL3 Nzby5nb3RzaGFycC5iZSIsICJzY29wZSI6ICJhZG 1pbiIsICJpYXQiOiAxNzM3ODEyOTg1LCAiZXhwIjo gMTc2OTM0ODk4MywgIm5iZiI6IDE3Mzc4MTI 5ODUsICJqdGkiOiAiNTg0ODgxNjUwMzkwNzM0 OTczNDA5NTcyODM2NTk4MjYiIH0. eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsIm tpZCI6IjgxODcxOTgxOTIzODcxMjk4NzEyOSJ9.ey JzdWIiOiIxIiwibmFtZSI6IkNodWNrIE5vcnJpcyIsIml zcyI6Imh0dHBzOi8vc3NvLmdvdHNoYXJwLmJlIiw ic2NvcGUiOiJiZWluZyBhd2Vzb21lIiwiaWF0IjoxNz M3ODEyOTg1LCJleHAiOjE3NjkzNDg5ODMsIm5i ZiI6MTczNzgxMjk4NSwianRpIjoiNzkyMzIxNjUwM zkwNzM0OTczNDA5NTcyODM2NTk4MjYifQ.AG 5NQnGrcown3tllBB4Oqwnc7YfLYTgVf9V2F8Zz AGZgxjEclvcaX-yoKTVtR07fL19gRiX70osrUAK6I1t6w Are you sure your access tokens are really secure? 17
  13. Let’s look at token B… { "alg": "nOnE", "typ": "at+jwt",

    "kid": "818719819238712987129"} . { "sub": "333", "name": "Evil Person", "iss": "https://sso.gotsharp.be", "scope": "admin", "iat": 1737812985, "exp": 1769348983, "nbf": 1737812985, "jti": "58488165039073497340957283659826" } . Are you sure your access tokens are really secure? 18
  14. alg: none What? • “alg”: “none” is a valid token.

    • The validation library did indeed reject tokens using “none”! • However… • The library allowed tokens with “alg”: “NONE”, “alg”: “nOnE”, “alg”: “nONe”, … • And the API was wide open for attack… • Luckily, this was very quickly fixed! Are you sure your access tokens are really secure? 19
  15. But wait, there’s more! Of course there is more, there’s

    always something :/ Are you sure your access tokens are really secure? 20
  16. What’s wrong with this token? eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImtpZCI6IkU0MTMwRkNDRDR FNEFBNUEiLCJrdHkiOiJFQyIsIngiOiJXVlZQMjJxUkNGdE9nTzJVWkpISDRjRllxYVk2QkJ3cG5QNUpzMWJObmpr IiwieSI6ImZHUFlwYk5LSTFGQnd2V0E1UC1iaHI2WTktdDI1S0Q1Y0dLM19NQzZwQU0ifSwia2lkIjoiRTQx MzBGQ0NENEU0QUE1QSJ9 .

    eyJzdWIiOiIzMzMiLCJuYW1lIjoiRXZpbCBQZXJzb24iLCJzY29wZSI6ImFkbWluIiwianRpIjoiOTdhMDVlM2Q1M DFkYjFkNzQ4NDY3Mzc2OTNlZGFhMzUiLCJuYmYiOjE3Mzg1MDY2NDcsImV4cCI6MTc3MDA0MjY0Nywia WF0IjoxNzM4NTA2NjQ3LCJpc3MiOiJodHRwczovL3Nzby5nb3RzaGFycC5iZSJ9 . ykqjOQU60IQpu674N-JKgPZqqSAU9VzQx_4pSSjCMlO75Deh6xJvveGsc2LzL3CXUm24Mz5Sl8mDTEfsqD_OQ Are you sure your access tokens are really secure? 21
  17. What’s wrong with this token? Header from latest token Header

    from known good token eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsImp3ayI6eyJjcn YiOiJQLTI1NiIsImtpZCI6IkU0MTMwRkNDRDRFNEFBNUEiLCJr dHkiOiJFQyIsIngiOiJXVlZQMjJxUkNGdE9nTzJVWkpISDRjRllxYVk 2QkJ3cG5QNUpzMWJObmprIiwieSI6ImZHUFlwYk5LSTFGQnd 2V0E1UC1iaHI2WTktdDI1S0Q1Y0dLM19NQzZwQU0ifSwia 2lkIjoiRTQxMzBGQ0NENEU0QUE1QSJ9 eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsImtpZCI6IjgxO DcxOTgxOTIzODcxMjk4NzEyOSJ9 Are you sure your access tokens are really secure? 22
  18. What’s wrong with this token? { "alg": "ES256", "typ": "at+jwt",

    "jwk": { "crv": "P-256", "kid": "E4130FCCD4E4AA5A", "kty": "EC", "x": "WVVP22qRCFtOgO2UZJHH4cFYqaY6BBwpnP5Js1bNnjk", "y": "fGPYpbNKI1FBwvWA5P-bhr6Y9-t25KD5cGK3_MC6pAM" }, "kid": "E4130FCCD4E4AA5A“ } Are you sure your access tokens are really secure? 23
  19. Self-signed tokens Thank you RFC 7515 jwk: integrated JSON Web

    Key for verifying the signature x5c: integrated chain of certificates for verifying the signature Are you sure your access tokens are really secure? jku: URL pointing to a set of JSON Web Keys x5u: URL pointing to the certificate chain 24
  20. Testing to the rescue! Using API integration tests to check

    for various JWT edge cases Are you sure your access tokens are really secure? 25
  21. Which JWT validation library do you use? Are you sure

    your access tokens are really secure? 26
  22. Can you trust the library? Or should you? Open source

    Are you sure your access tokens are really secure? Vendor library Updates Package feed 28
  23. Demo time! Adding integration tests to validate JWT access tokens

    Are you sure your access tokens are really secure? 30
  24. JWT Guard An open-source integration test project for .NET APIs

    https://jwtguard.net Are you sure your access tokens are really secure? 31
  25. Bonus: algorithm confusion attack Using a public key to attempt

    gaining access using HMAC-SHA algorithms Are you sure your access tokens are really secure? 32
  26. Algorithm confusion attack Shared secret Token issuer Private / Public

    Key pair Are you sure your access tokens are really secure? 33
  27. Algorithm confusion attack POST /token?grant_type=…&client_id=… { “alg”: “RS256”, …}.{ “sub”:

    1234…}.<signature> Are you sure your access tokens are really secure? 34
  28. Algorithm confusion attack Bearer eyJh… /jwks 200 OK Are you

    sure your access tokens are really secure? 35
  29. Algorithm confusion attack VerifyToken(SecurityToken token, string sharedSecretOrPublicKey) { switch (token.Header.Algorithm)

    { case “RS256”: return VerifyRsaSha256Signature(token, sharedSecretOrPublicKey); } } case “HS256”: return VerifyHmacSha256Signature(token, sharedSecretOrPublicKey); return false; Are you sure your access tokens are really secure? 36
  30. Algorithm confusion attack { “alg”: “HS256”, “kid”: “jwk-1” }. {

    “sub”: “admin” }.<signature> /jwks 200 OK Are you sure your access tokens are really secure? 38
  31. Algorithm confusion attack VerifyToken(SecurityToken token, string sharedSecretOrPublicKey) { switch (token.Header.Algorithm)

    { case “RS256”: return VerifyRsaSha256Signature(token, sharedSecretOrPublicKey); } } case “HS256”: return VerifyHmacSha256Signature(token, sharedSecretOrPublicKey); return false; Are you sure your access tokens are really secure? 39
  32. Algorithm confusion attack Only use key material relevant per algorithm

    type! • HS256 => fetch shared secret • RS256 => fetch JWK identified by “kid” Are you sure your access tokens are really secure? 40