1

With the help of this guide i created one IdentityServer4 on localhost:5000

https://identityserver4.readthedocs.io/en/latest/

this the discovery document:

{
"issuer": "http://localhost:5000",
"jwks_uri": "http://localhost:5000/.well-known/openid-configuration/jwks",
"authorization_endpoint": "http://localhost:5000/connect/authorize",
"token_endpoint": "http://localhost:5000/connect/token",
"userinfo_endpoint": "http://localhost:5000/connect/userinfo",
"end_session_endpoint": "http://localhost:5000/connect/endsession",
"check_session_iframe": "http://localhost:5000/connect/checksession",
"revocation_endpoint": "http://localhost:5000/connect/revocation",
"introspection_endpoint": "http://localhost:5000/connect/introspect",
"device_authorization_endpoint": "http://localhost:5000/connect/deviceauthorization",
"frontchannel_logout_supported": true,
"frontchannel_logout_session_supported": true,
"backchannel_logout_supported": true,
"backchannel_logout_session_supported": true,
"scopes_supported": [
"profile",
"openid",
"swg_entitlements",
"offline_access"
],
"claims_supported": [
"website",
"picture",
"profile",
"preferred_username",
"nickname",
"middle_name",
"given_name",
"family_name",
"name",
"gender",
"birthdate",
"zoneinfo",
"locale",
"updated_at",
"sub"
],
"grant_types_supported": [
"authorization_code",
"client_credentials",
"refresh_token",
"implicit",
"password",
"urn:ietf:params:oauth:grant-type:device_code"
],
"response_types_supported": [
"code",
"token",
"id_token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"response_modes_supported": [
"form_post",
"query",
"fragment"
],
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"subject_types_supported": [
"public"
],
"code_challenge_methods_supported": [
"plain",
"S256"
],
"request_parameter_supported": true
}

i would like to validate the access token outside the IS

based on this article https://devblogs.microsoft.com/aspnet/jwt-validation-and-authorization-in-asp-net-core/ i wrote this code into a standard .net application:

http://localhost:5000/ is the IdentityServer http://localhost:5001/ is the Api project

this is the code:

void CheckToken()
{
        string token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IlRWUFNScTNWMFZibHIyN0VoY1V2U3ciLCJ0eXAiOiJhdCtqd3QifQ.eyJuYmYiOjE1OTI0ODY3MDksImV4cCI6MTU5MjQ5MDMwOSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoic3dnX2VudGl0bGVtZW50cyIsImNsaWVudF9pZCI6Im12YyIsInN1YiI6ImZkYjEiLCJhdXRoX3RpbWUiOjE1OTI0ODY3MDcsImlkcCI6ImxvY2FsIiwicm9sZSI6WyJkYXRhRXZlbnRSZWNvcmRzLmFkbWluIiwiZGF0YUV2ZW50UmVjb3Jkcy51c2VyIl0sInVzZXJuYW1lIjoiZmRiMSIsInVzZXJJZGVudGl0eSI6InZiM3luN2dEMjRCRWxmT1BaUE1qTUM3NVFLWlJWek10ZU9PVDRHdXk5TFk9Iiwic2NvcGUiOlsicHJvZmlsZSIsIm9wZW5pZCIsInN3Z19lbnRpdGxlbWVudHMiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsicHdkIl19.TCi12FLD1oLK9A7sP9aTWqBwrdOm7HiIkCwy0OJHDQsTkKs4kMtKrZcZCOfI3FErgEEvlTAlwT9t5ERKtF1Nvr9343GfcDMNRWY6Z3KGiKgskB983uOENoZZ3Hr72OOEttwK-e3Y01LuudHVNoYaX4zwX8RXTBVGu9NVOhQpksGj8uqljyxzS5ulO3wb73TEX3Z6dAClGrme-zbvc5fN4zvzfWu43fVBIbDcaiqWephWGxyK2iyyeQpMH8Om0OhWKV68vQ5H4yoE8fFWq0LWA4uRvMoAVYL6DOfzWjIF1ZeJWtD0yFxC0h9aspWj9bJVFa4GMtUsF1hkzzs9hKXw8g";

        //read secretKey from the table ClientSecrets of the IdentityServer configuration database
        const string secretKey = "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=";
        var securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(secretKey));
        var handler = new JwtSecurityTokenHandler();
        var validationParameters = new TokenValidationParameters
        {
          ValidAudience = "http://localhost:5001/",
            ValidIssuer = "http://localhost:5000/",
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            LifetimeValidator = LifetimeValidator,
            IssuerSigningKey = securityKey
        };
        System.Security.Principal.IPrincipal userName = handler.ValidateToken(token, validationParameters, out _);
    }

this the error in ValidateToken:

Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: 'IDX10501: Signature validation failed. Unable to match key: kid: 'System.String'. Exceptions caught: 'System.Text.StringBuilder'. token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.'

FDB
  • 971
  • 16
  • 32
  • where did you get that secret key from? Anyway, the token is signed with a asymmetric key, algorithm RS256, and you get get the public key, identified by the `kid`, from the `jwks_uri`. You can find the code for it in [this Q/A](https://stackoverflow.com/questions/61395261/how-to-validate-signature-of-jwt-from-jwks-without-x5c/61397971#61397971) – jps Jun 18 '20 at 15:04
  • secret key is stored into the configuration database, for each client is configured a secret key – FDB Jun 18 '20 at 15:13
  • that string doesn't look like a RS256 public key. Have had a look into the linked Q/A? – jps Jun 18 '20 at 15:19
  • any progress here? – jps Jun 19 '20 at 09:13
  • no way, monday will try your link – FDB Jun 19 '20 at 13:03

1 Answers1

1

This sample code validates a token against your IdentiyServer. Just pass your JWT-token string (that starts with ey) to it and the clientID. Issuer is the URL to your IdentiyServer.

public string ValidateToken(string token, string clientId)
{
    try
    {
        string issuer = openIDSettings.Issuer;

        var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{issuer}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
        var openIdConfig = configurationManager.GetConfigurationAsync(CancellationToken.None).Result;

        // Configure the TokenValidationParameters. Assign the SigningKeys which were downloaded from Auth0. 
        // Also set the Issuer and Audience(s) to validate
        //https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs
        var validationParameters =
            new TokenValidationParameters
            {
                IssuerSigningKeys = openIdConfig.SigningKeys,

                ValidAudiences = new[] { clientId },
                ValidIssuer = issuer,
                ValidateLifetime = true,
                ValidateAudience = true,
                ValidateIssuer = true,
                ValidateIssuerSigningKey = true,
                ValidateTokenReplay = true
            };

        // Now validate the token. If the token is not valid for any reason, an exception will be thrown by the method
        SecurityToken validatedToken;
        JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
        var user = handler.ValidateToken(token, validationParameters, out validatedToken);

        // The ValidateToken method above will return a ClaimsPrincipal. Get the user ID from the NameIdentifier claim
        // (The sub claim from the JWT will be translated to the NameIdentifier claim)
        return $"Token is validated. User Id {user.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value}";
    }
    catch (Exception exc)
    {
        return "Invalid token: " + exc.Message;
    }
}
Tore Nestenius
  • 16,431
  • 5
  • 30
  • 40
  • whats's openIDSettings? i've to add some using. thanks – FDB Jun 24 '20 at 14:53
  • 1
    just my own settingsclass, just replace it with the URL to your identity server. – Tore Nestenius Jun 24 '20 at 15:43
  • maybe something is wrong in the identity server. get this errors 1)"InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'." 2)ArgumentException: IDX20108: The address specified 'System.String' is not valid as per HTTPS scheme. Please specify an https address for security reasons. If you want to test with http address, set the RequireHttps property on IDocumentRetriever to false. on var openIdConfig = configurationManager.GetConfigurationAsync(CancellationToken.None).Result; – FDB Jun 24 '20 at 18:25
  • Think you should enable HTTPS even in development on your own machine. – Tore Nestenius Jun 25 '20 at 05:16
  • I changed way, found Jwt.Net by Alexander Batishchev. this is working on 4.0. here is a code sample https://github.com/jwt-dotnet/jwt, i got the Parsing (decoding) and verifying token function. if i replace the code with my token and my sectret i get the Invalid signature exception, but if change var json = decoder.Decode(token, secret, verify: false) i can decode succesfully my token. maybe m$ IS use a different algoritm? – FDB Jun 25 '20 at 13:27