3
votes

My web application is a kind of wrapper for some 3rd party service. This 3rd party service uses the JWT Bearer authentication to access its WebAPI endpoints. The tokens are encrypted with RS256 algorithm (asymmetric).

I have a Public Key to validate tokens signature on my side. It is easy to validate signature on jwt.io site (just paste the token and public key to the text boxes). But how do I configure TokenValidationParameters to have tokens validated automatically using specified Public Key?

AddAuthentication code snippet:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters.ValidateIssuer = true;
    options.TokenValidationParameters.ValidIssuer = "iss";
    options.TokenValidationParameters.ValidateIssuerSigningKey = true;
    options.TokenValidationParameters.IssuerSigningKey = SomeCodeToGenerateSecurityKeyUsingPublicKeyOnly("-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----");
    options.TokenValidationParameters.ValidateAudience = false;
    options.TokenValidationParameters.ValidateLifetime = true;
    options.TokenValidationParameters.ClockSkew = TimeSpan.Zero;
});

services.AddAuthorization(options =>
{
    options.AddPolicy("Bearer",
        new AuthorizationPolicyBuilder(new string[] { JwtBearerDefaults.AuthenticationScheme })
            .RequireAuthenticatedUser()
            .Build()
    );
});

I can't just use SymmetricSecurityKey class like this:

options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("..."));

because of asymmetric encryption. In this case an exception occurs:

IDX10503: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey , KeyId: 
'.
Exceptions caught:
 ''.
token: '{"alg":"RS256","typ":"JWT"}....
1

1 Answers

3
votes

Okay, eventually I was succeeded with following solution. The RsaSecurityKey object do the trick I was looking for:

byte[] publicKeyBytes = Convert.FromBase64String("public_key_without_header_and_footer");
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes);
RSAParameters rsaParameters = new RSAParameters
{
    Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned(),
    Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned(),
};

......

options.TokenValidationParameters.IssuerSigningKey = new RsaSecurityKey(rsaParameters);

I'm not sure if this is the best solution, but I haven't some another one for now.