Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# asp.net core Bearer error="invalid_token"

Can someone please help me to solve this problem? I'm testing the API using Postman

I'm following a tutorial about asp.net core.

And I'm on its Authentication part now.

I don't really understand whats the reason for the error.

In the tutorial, it has a login and it returns token.

This is the code for login. Which is working. I know this is working because it returns a token. I also tried using an invalid login. and it returns 401 Unauthorized But when I use the correct login credentials which are found in the database. It returns token

[HttpPost("login")]
public async Task<IActionResult> Login(UserForLoginDto userForLoginDto)
    {
        var userFromRepo = await _repo.Login(userForLoginDto.Username.ToLower(), userForLoginDto.Password);

        if (userFromRepo == null)
            return Unauthorized();

        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, userFromRepo.Id.ToString()),
            new Claim(ClaimTypes.Name, userFromRepo.Username)
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config.GetSection("AppSettings:Token").Value));

        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(claims),
            Expires = DateTime.Now.AddDays(1),
            SigningCredentials = creds
        };

        var tokenHandler = new JwtSecurityTokenHandler();

        var token = tokenHandler.CreateToken(tokenDescriptor);

        return Ok(new {
            token = tokenHandler.WriteToken(token)
        });
}

Then the next part of the tutorial is to limit the access. The user should be logged in first in order to view the content.

Below is the code

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>{
                options.TokenValidationParameters = new TokenValidationParameters{
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
                    ValidateIssuer = false
                };
            });

Then enabled

app.UseAuthentication();

I also enabled the [Authorize] in the Values Controller

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

This is the screenshot of postman

enter image description here

I followed the tutorial. I paste the token I received from login. But it gives me the error

WWW-Authenticate →Bearer error="invalid_token", error_description="The audience is invalid"

Why does the error give me invalid token if the token is from the login? How do I fix this? I've been searching for a while but I can't solve this my self. Thank you.

like image 340
Ramon bihon Avatar asked Jan 28 '19 05:01

Ramon bihon


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.


2 Answers

I recently did similar thing using JWT token which is working fine with Postman. My approach for creating the JWT token is little different, In your case the problem can be due to not specifying the issuer and audience.

Can you try like following.

   var claims = new List<Claim>
    {
        new Claim(ClaimTypes.WindowsAccountName, this.User.Identity.Name)
    };
    Claim userIdClaim = new Claim("UserId", "12345");
    claims.Add(userIdClaim);
    //Avoid Replay attack
    claims.Add(new Claim(ClaimTypes.GivenName, "User GivenName"));
    claims.Add(new Claim(ClaimTypes.Surname, "UserSurname"));
    claims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));

    string[] roles = "Role1,Role2,Role23".Split(",");

    foreach (string role in roles)
    {
        claims.Add(new Claim(role, ""));
    }

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("veryVerySecretKey"));
    var key1 = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ASEFRFDDWSDRGYHF")); 
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var encryptingCreds = new EncryptingCredentials(key1, SecurityAlgorithms.Aes128KW, SecurityAlgorithms.Aes128CbcHmacSha256);
    var handler = new JwtSecurityTokenHandler();
    var t = handler.CreateJwtSecurityToken();
    var token = handler.CreateJwtSecurityToken("http://localhost:61768/", "http://localhost:61768/"
        , new ClaimsIdentity(claims)
        , expires: DateTime.Now.AddMinutes(1)
        , signingCredentials: creds
        , encryptingCredentials :encryptingCreds
        , notBefore:DateTime.Now
        ,  issuedAt:DateTime.Now);
    return new JwtSecurityTokenHandler().WriteToken(token);

And my ConfigureServices looks like

services.AddAuthentication()
            .AddJwtBearer(options =>
             {
                 options.RequireHttpsMetadata = false;
                 options.SaveToken = true;
                 options.TokenValidationParameters = new TokenValidationParameters
                 {
                     ValidateIssuer = true,
                     ValidateAudience = true,
                     ValidateLifetime = true,
                     ValidateIssuerSigningKey = true,
                     ValidIssuer = "http://localhost:61768/",
                     ValidAudience = "http://localhost:61768/",
                     TokenDecryptionKey= new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ASEFRFDDWSDRGYHF")),
                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("veryVerySecretKey")),
                     ClockSkew = TimeSpan.Zero
                 };
             });

Note: Change the issuer and the key appropriately.

like image 198
PSK Avatar answered Oct 04 '22 23:10

PSK


I had a similar problem where a .net Core 3 API would not authenticate its own tokens.

The solution for me was in Startup/Configure(), to put app.UseAuthentication() before app.UseAuthorization().

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
 {
    app.UseAuthentication();

    app.UseAuthorization();
 }
like image 30
Lancelot Lovejoy Avatar answered Oct 04 '22 22:10

Lancelot Lovejoy