Home > Net >  Invalid JWT token in a simple C# API
Invalid JWT token in a simple C# API

Time:07-09

I've a simple .Net Core 3.1 Web API example here:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            services.AddAuthentication(o =>
            {
                o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = Configuration["Jwt:Issuer"],
                    ValidAudience = Configuration["Jwt:Audience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.Configuration["Jwt:Key"])),
                    ClockSkew = TimeSpan.Zero
                };
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

This is the controller:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };
    private readonly IConfiguration _configuration;

    public WeatherForecastController(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    [HttpGet]
    [Route("generate-token")]
    public string GenerateToken()
    {
        var claims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(JwtRegisteredClaimNames.Sub, "admin"),
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Key"]));
        var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var token= new JwtSecurityToken(
            _configuration["JWT:Issuer"],
            _configuration["JWT:Audience"],
            claims,
            expires: DateTime.Now.AddMinutes(Convert.ToInt32(_configuration["JWT:ExpireInMinutes"])),
            signingCredentials: credentials);

        return token.EncodedPayload;
    }

    [Authorize]
    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

This is the appsettings:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "JWT": {
    "Key": "e89b7555-ef37-457e-a6a8-90d149927548",
    "Issuer": "test",
    "Audience": "https://localhost:5001/",
    "ExpireInMinutes": "60000"
  },
  "AllowedHosts": "*"
}

If you try to generate the token calling the endpoint https://localhost:5001/weatherforecast/generate-token and then use it to make a call with Postman or similar client to the [Autorize] method https://localhost:5001/weatherforecast, you'll receive a 401 invalid_token.

> GET /weatherforecast HTTP/2
> Host: localhost:5001
> user-agent: insomnia/2022.4.2
> content-type: application/json
> authorization: Bearer eyJqdGkiOiJiMDI2OWY0ZS1mODhmLTRmN...
> accept: */*


< HTTP/2 401 
< date: Fri, 08 Jul 2022 17:28:27 GMT
< server: Kestrel
< www-authenticate: Bearer error="invalid_token"
< content-length: 0

I'm stuck with this and I know I'm missing something but I cannot figure what!

Can someone give me an hint?

CodePudding user response:

You only returned the Payload of jwt whereas jwt consists of 3 parts. these are Header, Payload and Signature.

return token.EncodedPayload;

you can use WriteToken()

 var token= new JwtSecurityToken(....)
 var handler = new JwtSecurityTokenHandler();
 var jwt = handler.WriteToken(token);
 return jwt;
  • Related