1

My client is sending the jwt token with some requests. Almost all requests is hitting a web api controller that is using the [Authorize] attribute. With this I am certain that my jwt token is properly validated, but for certain endpoints is really just want to grab the JWT token and get the sub value. I do this by using this extension method:

public static class HttpContextAccessorExtensions
{
    public static string GetUserIdFromToken(this IHttpContextAccessor httpContextAccessor)
    {
        if (httpContextAccessor == null)
        {
            throw new ArgumentNullException(nameof(httpContextAccessor));
        }

        var context = httpContextAccessor.HttpContext;

        string userId = null;
        if (httpContextAccessor != null)
        {
            if (context != null)
            {
                var request = context.Request;
                if (request != null)
                {
                    request.Headers.TryGetValue("Authorization", out var bearer);

                    if (bearer.Any())
                    {
                        string t = bearer[0].Split(" ")[1];
                        var handler = new JwtSecurityTokenHandler();
                        var token = handler.ReadToken(t) as JwtSecurityToken;

                        var utcNow = DateTime.UtcNow;

                        if (utcNow >= token.ValidFrom &&
                            utcNow <= token.ValidTo)
                        {
                            userId = token.Claims.FirstOrDefault(_ => _.Type.Equals("sub")).Value;
                        }
                        else
                        {
                            userId = String.Empty;
                        }
                    }
                }
            }
        }

        return userId;
    }
}

My only problem here is that the jwt token isn't validated, so I am guessing that a "bad person" could just mingle with the valid to datetime, and keep extending the token lifetime. Please correct me if I am wrong on this.

What i want to know is: is there a way for me to validate the token? I know the JwtSecurityTokenHandler can call "ValidateToken", but this method needs a signing key, and I really dont know how to get this. I use IdentityServer 4 to generate tokens. Is there some easy way of injecting the Key into the IoC so I can get it, or is there an easy way to validate the token, that I dont know of?

Any help is appreciated

2
  • Why this approach? Isn't it easier to read the sub claim from the context? Commented Dec 20, 2019 at 15:19
  • I didnt know that i could do a [AllowAnonymous] and [Authorize]. If it is an authorized user, i just take the sub from identity, after checking IsAuthenticated :) I couldn't see the forrest for the trees. Commented Dec 20, 2019 at 19:22

3 Answers 3

2

Since your access token is generated by IdentityServer4, then you should validate it using the IS4 Introspection Endpoint. This will give you the definitive answer as to if it is valid and whether or not it is still active.

Information about the Introspection Endpoint is in the IS4 docs at: http://docs.identityserver.io/en/latest/endpoints/introspection.html

As referenced in those docs, perhaps the easiest way to interact with the endpoint is to use the IdentityModel client library (add package via NuGet), which adds the IntrospectTokenAsync() extension method to HttpClient and returns a TokenIntrospectionResponse object that has the information you need.

IdentityModel client Introspection Endpoint docs: https://identitymodel.readthedocs.io/en/latest/client/introspection.html

Sign up to request clarification or add additional context in comments.

1 Comment

But I already have the jwt token and the api I have, that receives the jwt token can validate jwt token with the authorize attribute. Isnt there som way I can use all that info that is already present. The web api must do this somewhere when using the authorize attribute? I dont think it is a solid solution to call the identityserver, because there can potentially be a lot of calls.
2

Inside your controller you can just do this:

if(HttpContext.User.Identity.IsAuthenticated)          
{              
    var claims = HttpContext.User.Claims;          
}

and you can inspect the claims for whatever information is of interest. that authenticated user identity is already validated and is available regardless of if the Authorize attribute is applied. If the user's cookie has expired etc that will return false. .

4 Comments

T.J. is right. For some reason I was thinking that if you decorated the action with an AllowAnonymous it would not populate the IsAuthenticated property, but it does. And the claims are accessible if you just need the sub.
So I can access them just because the jwt token is set on the request? I will try this when I get to work!
This doesn't work. If I send the token with a request, the IsAuthenticated doesn't get set and the Claims isn't populated. I think the Authorize will fill this out.
mslot the nice thing is the token is still subject to validation depending on how you have configured authentication. What you are saying would suggest that the token has not been validated, you might check and make sure you are sending a valid token..
2

What i want to know is: is there a way for me to validate the token? I know the JwtSecurityTokenHandler can call "ValidateToken", but this method needs a signing key, and I really dont know how to get this. I use IdentityServer 4 to generate tokens.

When validating JWT token issued by Identity Server(using key pairs to issue/validate token) , specific for validating signature . API/resource server will pull down (and might cache) your identity providers discovery document located at OIDC endpoint : https://xxx/.well-known/openid-configuration. This document contains materials that allow the resource server to validate the token ,read available keys from jwks_uri .

Using key pairs menans the JWT token which is signed by IDS4 with private key. A JWT token is a non-encrypted digitally signed JSON payload which contains different attributes (claims) to identify the user/role. The signature is the last part of the JWT and needs to be used for verification of the payload. This signature was generated with the algorithm described in the header(RS256 for example) to prevent unauthorized access. In your api , you could use public key which published by IDS4(jwks_uri) to validate the signature of the JWT token . Please refer to this document for more details about JWT token .

You can use JwtBearerAuthentication middleware or IdentityServer.AccessTokenValidation middleware will help do that process . Code sample here is for your reference . If you want to manually validating a JWT token . Click here for code sample .

My only problem here is that the jwt token isn't validated, so I am guessing that a "bad person" could just mingle with the valid to datetime, and keep extending the token lifetime.

It's not recommended to use token without validating it . Since the signature part of JWT token is encrypted/encode use (header+payload) , even someone change the claims(expire time) , it won't pass the validation since he can't know Identity Server's private key to issue a correct signature .

6 Comments

To my defense, the data I use from the token is strictly for tagging some user releated info in a database. It is not for login or other important stuff. If a bad person changes the jwt token, it doesn't expose anything authenticated.
@mslot , then you don't need to use identity server4 ,just use jwt token authentication to issue token with SymmetricSecurityKey . And on api side , set same SymmetricSecurityKey and validate using AddJwtBearer
I use identityserver4 for all other endpoints, but for this one endpoint, I both authorized and unauthorized should have access. But when an authorized person calls it, I want the userid from the access token that is supplied. I dont know how to do this AND validate the token.
It literly just came to me that you can have [AllowAnonymous] and [Authorize]. I can then check IsAuthorized, and get the user id. This validates the token if present.
First , set the action allowanonymous , and write a middleware to get the token from request in http context , validate and decode token , get your claims as shown here
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.