12

I'm using the Microsoft.AspNetCore.Authentication.JwtBearer and System.IdentityModel.Tokens.Jwt packages for my .NET Core project.

There are some controller endpoints protected by the [Authorize] annotation that have to fetch the access token from the request. Currently I'm fetching the access token in my controller method this way:

string accessTokenWithBearerPrefix = Request.Headers[HeaderNames.Authorization];
string accessTokenWithoutBearerPrefix = accessTokenWithBearerPrefix.Substring("Bearer ".Length);

and I would like to know if there is a better "ready to use" solution for this because using the code above might still lead to errors while taking the substring from the bearer token.

Question3r
  • 2,166
  • 19
  • 100
  • 200

3 Answers3

37

Here is a clever way to get the header without having to go in to the headers dictionary. This will also let the framework parse the token, which is what I believe you are looking for:

[HttpGet, Route("someEndpoint")]
public IActionResult SomeEndpoint([FromHeader] string authorization)
{

    if(AuthenticationHeaderValue.TryParse(authorization, out var headerValue))
    {
        // we have a valid AuthenticationHeaderValue that has the following details:

        var scheme = headerValue.Scheme;
        var parameter = headerValue.Parameter;

        // scheme will be "Bearer"
        // parmameter will be the token itself.
    }

    return Ok();
}

You can also grab the header the old-school way:

[HttpGet, Route("someEndpoint")]
public IActionResult SomeEndpoint()
{
    var authorization = Request.Headers[HeaderNames.Authorization];

    if (AuthenticationHeaderValue.TryParse(authorization, out var headerValue))
    {
        // we have a valid AuthenticationHeaderValue that has the following details:

        var scheme = headerValue.Scheme;
        var parameter = headerValue.Parameter;

        // scheme will be "Bearer"
        // parmameter will be the token itself.
    }

    return Ok();
}

What's nice is AuthenticationHeaderValue.TryParse will cover oddball cases like if there is more than once space between the scheme and the token, or if there are spaces before the scheme, or spaces after the token... and trim it up for you.

Now, those cases should never happen, but... they may, and the execution of accessTokenWithBearerPrefix.Substring("Bearer ".Length); would fail. Which is why I believe you wanted a more concrete way of parsing the token.

Andy
  • 12,859
  • 5
  • 41
  • 56
  • 1
    Readers: Great answer, but be aware that if the string is missing a schema prefix like "Bearer" then AuthenticationHeaderValue.TryParse(string) mistakenly assigns the token to the schema property and sets the parameter property (token) to null. So it appears that the schema prefix is required and an additional check is needed. +1 – Yogi Oct 23 '21 at 15:49
7

You can set SaveToken in Startup.cs to true.

services.AddAuthentication()
    .AddJwtBearer(options =>
    {
        // your other config
        options.SaveToken = true;
    });

and get access token from HttpContext with GetTokenAsync method.

using Microsoft.AspNetCore.Authentication;

public class SampleController : Controller
{
    public void Index()
    {
        var accessToken = HttpContext.GetTokenAsync("access_token");
    }
}
Kahbazi
  • 14,331
  • 3
  • 45
  • 76
0

You can use the following code to get security token.

var stream ="[encoded jwt]";  
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(stream);
var tokenS = handler.ReadToken(stream) as JwtSecurityToken;

Also, if you want to Ignore JWT Bearer token signature, you can refer to the code as below:

public TokenValidationParameters CreateTokenValidationParameters()
{
    var result = new TokenValidationParameters
    {
    ValidateIssuer = false,
    ValidIssuer = ValidIssuer,

    ValidateAudience = false,
    ValidAudience = ValidAudience,

    ValidateIssuerSigningKey = false,
    //IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SecretKey)),
    //comment this and add this line to fool the validation logic
    SignatureValidator = delegate(string token, TokenValidationParameters parameters)
    {
        var jwt = new JwtSecurityToken(token);

        return jwt;
    },

    RequireExpirationTime = true,
    ValidateLifetime = true,

    ClockSkew = TimeSpan.Zero,
    };

    result.RequireSignedTokens = false;

    return result;
}
Joey Cai
  • 18,968
  • 1
  • 20
  • 30
  • would you mind explaining this line? `var stream ="[encoded jwt]"; ` Where does the encoded token come from? Does it come from `Request.Headers[HeaderNames.Authorization]` ? Is it the full access token without the bearer prefix? – Question3r Aug 04 '20 at 17:06
  • It is full access token without bearer prefix. – Joey Cai Aug 05 '20 at 08:31
  • from here? `Request.Headers[HeaderNames.Authorization]` ? – Question3r Aug 05 '20 at 17:48
  • Yes, remove bearer prefix. – Joey Cai Aug 07 '20 at 07:40
  • Maybe I misunderstood your solution but I'm looking for a way to remove the bearer prefix from the access token without doing it on my own. I tried your code but unfortunately I get an exception, I added it as a comment https://hatebin.com/dhkiehygvw – Question3r Aug 07 '20 at 21:04