Skip to content

Instantly share code, notes, and snippets.

@secana
Created October 4, 2020 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save secana/f91f6c89f6b850e4af84c800194862db to your computer and use it in GitHub Desktop.
Save secana/f91f6c89f6b850e4af84c800194862db to your computer and use it in GitHub Desktop.
#r "nuget: System.IdentityModel.Tokens.Jwt"
#r "nuget: Microsoft.IdentityModel.Tokens"
open System.IdentityModel.Tokens.Jwt
open System
open System.IO
open System.Text
open System.Security.Claims
open System.IdentityModel.Tokens.Jwt
open Microsoft.IdentityModel.Tokens
open System.Security.Cryptography
let pubKey =
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB"
|> Convert.FromBase64String
let token =
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJOYW1lIjoiSm9obiBEb2UiLCJBZG1pbiI6IlRydWUifQ.ma49T3npXQJVMa-afyfFgIPW5PEYhrrYvX2mUA6rmzXHXq_Wy-ij9MLc0b6UxZX8STcRrSC93meIMa4a8LI7UBe0Pxn8IQBrhXztcElMfktMQoQWb7Osx9XwmqD1CaQWwz3FX963B4fQFdxx7GpxdLPj-CSOJZ4OZbk8fWpurVX1QXMLokaJ8C-gLB026jFVJjIV1APSMOnAzx9lcZfU5m3jwVP8HMIc0yJkm4d7IJO1lQjYnUWQkY_DmwR8-vysqo3N5yY57xQUFRoyHwFofDb25fA6SkKcNHrOX0_bc7KzxzWacoPWgtUolThKasWpXgqHipR-uJ4hz6zahInCmw"
let validate (token: string) pubKey =
use rsa = RSA.Create()
let mutable bytesRead = 0
rsa.ImportSubjectPublicKeyInfo(new ReadOnlySpan<byte>(pubKey), &bytesRead)
let validationParameters =
new TokenValidationParameters(ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new RsaSecurityKey(rsa))
let handler = new JwtSecurityTokenHandler()
let mutable validatedToken: SecurityToken = upcast new JwtSecurityToken()
try
handler.ValidateToken(token, validationParameters, &validatedToken)
|> ignore
printfn "Valid"
with ex -> printfn $"{ex}"
for i in [ 1 .. 10 ] do
validate token pubKey
@secana
Copy link
Author

secana commented Oct 4, 2020

Run with: dotnet fsi --langversion:preview .\jwt.fsx

Output:

Valid
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10503: Signature validation failed. Keys tried: 'System.Text.StringBuilder'.
Exceptions caught:
 'System.Text.StringBuilder'.
token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at FSI_0002.validate(String token, Byte[] pubKey)
Valid
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10503: Signature validation failed. Keys tried: 'System.Text.StringBuilder'.
Exceptions caught:
 'System.Text.StringBuilder'.
token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at FSI_0002.validate(String token, Byte[] pubKey)
Valid
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10503: Signature validation failed. Keys tried: 'System.Text.StringBuilder'.
Exceptions caught:
 'System.Text.StringBuilder'.
token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at FSI_0002.validate(String token, Byte[] pubKey)
Valid
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10503: Signature validation failed. Keys tried: 'System.Text.StringBuilder'.
Exceptions caught:
 'System.Text.StringBuilder'.
token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at FSI_0002.validate(String token, Byte[] pubKey)
Valid
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10503: Signature validation failed. Keys tried: 'System.Text.StringBuilder'.
Exceptions caught:
 'System.Text.StringBuilder'.
token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at FSI_0002.validate(String token, Byte[] pubKey)

Problem: Every second time the validate function is called, it fails with an exception. Why?

@secana
Copy link
Author

secana commented Oct 6, 2020

C# version with the same behavior:

using System;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;

namespace JwtTest
{
    class Program
    {
        static void Main(string[] args)
        {

            var pubKey = Convert.FromBase64String("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB");
            var token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJOYW1lIjoiSm9obiBEb2UiLCJBZG1pbiI6IlRydWUifQ.ma49T3npXQJVMa-afyfFgIPW5PEYhrrYvX2mUA6rmzXHXq_Wy-ij9MLc0b6UxZX8STcRrSC93meIMa4a8LI7UBe0Pxn8IQBrhXztcElMfktMQoQWb7Osx9XwmqD1CaQWwz3FX963B4fQFdxx7GpxdLPj-CSOJZ4OZbk8fWpurVX1QXMLokaJ8C-gLB026jFVJjIV1APSMOnAzx9lcZfU5m3jwVP8HMIc0yJkm4d7IJO1lQjYnUWQkY_DmwR8-vysqo3N5yY57xQUFRoyHwFofDb25fA6SkKcNHrOX0_bc7KzxzWacoPWgtUolThKasWpXgqHipR-uJ4hz6zahInCmw";


            for (var i = 0; i < 10; i++)
            {
                Console.WriteLine(Validate(token, pubKey));
            }
        }

        static bool Validate(string token, byte[] pubKey)
        {
            using var rsa = RSA.Create();
            rsa.ImportSubjectPublicKeyInfo(new ReadOnlySpan<byte>(pubKey), out var bytesRead);

            var validationParameters = new TokenValidationParameters
            {
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateLifetime = false,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new RsaSecurityKey(rsa)
            };

            var handler = new JwtSecurityTokenHandler();

            try
            {
                handler.ValidateToken(token, validationParameters, out var validatedToken);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return false;
            }
        }
    }
}

@secana
Copy link
Author

secana commented Oct 6, 2020

Corresponding bug ticket in dotnet/runtime dotnet/runtime#43087 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment