✅ jwt authentication always returns 401

I'm trying to build a backend with .net & firebase, but I can not get over one specific problem. When I try to implement jwt, calling any endpoint just throws 401 error code (after logging in in swagger ofc). What am I doing wrong?
24 Replies
Scottek utek
Scottek utekOP2y ago
Startup.cs:
public void ConfigureServices(IServiceCollection services) {
...
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = _configuration["Auth:Authority"];
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = _configuration["Auth:Issuer"],
ValidateAudience = true,
ValidAudience = _configuration["Auth:Audience"],
ValidateLifetime = true,
};
});

services.AddAuthorization(options =>
{
options.AddPolicy(
"AdminOnly",
policy => policy.RequireClaim(
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
"admin"
)
);
});
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
...
app.UseStatusCodePages();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors();

app.UseEndpoints(endpoints => endpoints.MapControllers());
}
public void ConfigureServices(IServiceCollection services) {
...
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = _configuration["Auth:Authority"];
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = _configuration["Auth:Issuer"],
ValidateAudience = true,
ValidAudience = _configuration["Auth:Audience"],
ValidateLifetime = true,
};
});

services.AddAuthorization(options =>
{
options.AddPolicy(
"AdminOnly",
policy => policy.RequireClaim(
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
"admin"
)
);
});
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
...
app.UseStatusCodePages();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors();

app.UseEndpoints(endpoints => endpoints.MapControllers());
}
FirebaseAuthenticationClient.cs:
public class FirebaseAuthenticationClient : IFirebaseAuthenticationClient
{
private readonly string _appKey;
private readonly HttpClient _httpClient;

public FirebaseAuthenticationClient(IConfiguration configuration, HttpClient httpClient)
{
_appKey = configuration.GetValue<string>("FirebaseAppKey");
_httpClient = httpClient;
}
public async Task<Token> Login(string username, string password)
{
string uri = $"/identitytoolkit/v3/relyingparty/verifyPassword?key={_appKey}";
var response = await _httpClient.PostAsJsonAsync(uri, new FireBaseLoginInfo
{
email = username,
password = password,
});

var result = await response.Content.ReadAsAsync<GoogleToken>();

return new Token
{
token_type = "Bearer",
access_token = result.IdToken,
id_token = result.IdToken,
expires_in = int.Parse(result.ExpiresIn),
};
}
}
public class FirebaseAuthenticationClient : IFirebaseAuthenticationClient
{
private readonly string _appKey;
private readonly HttpClient _httpClient;

public FirebaseAuthenticationClient(IConfiguration configuration, HttpClient httpClient)
{
_appKey = configuration.GetValue<string>("FirebaseAppKey");
_httpClient = httpClient;
}
public async Task<Token> Login(string username, string password)
{
string uri = $"/identitytoolkit/v3/relyingparty/verifyPassword?key={_appKey}";
var response = await _httpClient.PostAsJsonAsync(uri, new FireBaseLoginInfo
{
email = username,
password = password,
});

var result = await response.Content.ReadAsAsync<GoogleToken>();

return new Token
{
token_type = "Bearer",
access_token = result.IdToken,
id_token = result.IdToken,
expires_in = int.Parse(result.ExpiresIn),
};
}
}
appsettings.Production.json:
...
"Auth": {
"Authority": "https://securetoken.google.com/*firebase project id here*",
"Issuer": "https://securetoken.google.com/*firebase project id here*",
"Audience": "*firebase project id here*"
},
...
...
"Auth": {
"Authority": "https://securetoken.google.com/*firebase project id here*",
"Issuer": "https://securetoken.google.com/*firebase project id here*",
"Audience": "*firebase project id here*"
},
...
Dependencies: - FirebaseAdmin (2.3.0) - Microsoft.AspNet.WebApi.Client (5.2.9) - Microsoft.AspNetCore.Authentication.JwtBearer (7.0.4) - Microsoft.AspNetCore.OpenApi (7.0.3) - Swashbuckle.AspNetCore (6.4.0)
Kouhai
Kouhai2y ago
So Login endpoint returns a valid JWT but subsequent requests return 401? Are you sure JWT is getting sent with your subsequent requests?
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
NDOT
NDOT2y ago
hi, sorry for revinving this but i'm with the same problem (i didn't want to polute and create a new Post)
Kouhai
Kouhai2y ago
What's the problem again 😅 ?
NDOT
NDOT2y ago
fine basically i did an endpoint to create the JWT at the end it returns me a ok look like JWT but when i use it, it returns 401 Unauthourized and Bearer error="invalid_token", error_description="The signature key was not found"
Kouhai
Kouhai2y ago
Okay, first what have you added a reference to Microsoft.AspNetCore.Authentication.JwtBearer
NDOT
NDOT2y ago
yes
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using SistemaDeTarefas.Models;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using SistemaDeTarefas.Models;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Authentication.JwtBearer;
mine ones
var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_configuration.GetSection("Jwt:Key").Value));

var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

var token = new JwtSecurityToken
(
claims: claims,
expires: DateTime.Now.AddSeconds(1800), signingCredentials : cred
);
var jwt = new JwtSecurityTokenHandler().WriteToken(token);
return jwt;
var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_configuration.GetSection("Jwt:Key").Value));

var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

var token = new JwtSecurityToken
(
claims: claims,
expires: DateTime.Now.AddSeconds(1800), signingCredentials : cred
);
var jwt = new JwtSecurityTokenHandler().WriteToken(token);
return jwt;
that's basically the function that creates my JWT's
Kouhai
Kouhai2y ago
How did you add your config the auth services ?
NDOT
NDOT2y ago
wdym? i mean, i did just make a simple, Login endpoint, that creates a JWT that allows you to access the other endpoints btw i'm using .NET 6 not fast api, just a common webapi
Kouhai
Kouhai2y ago
Sorry, what I meant is how did add your auth servics, like .AddJwtBearer and .AddAuthentication
NDOT
NDOT2y ago
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
Kouhai
Kouhai2y ago
No like, show the AddJwtBearer and AddAuthentication calls
NDOT
NDOT2y ago
my whole method that creates the JWT is that>
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Username)
};
var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("absca4234srhaowurha3uo"));

var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

var token = new JwtSecurityToken
(
claims: claims,
expires: DateTime.Now.AddSeconds(1800),
signingCredentials : cred
);

var jwt = new JwtSecurityTokenHandler().WriteToken(token);
return jwt;
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Username)
};
var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("absca4234srhaowurha3uo"));

var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

var token = new JwtSecurityToken
(
claims: claims,
expires: DateTime.Now.AddSeconds(1800),
signingCredentials : cred
);

var jwt = new JwtSecurityTokenHandler().WriteToken(token);
return jwt;
Kouhai
Kouhai2y ago
You aren't calling AddJwtBearer at all?
NDOT
NDOT2y ago
hmm... no ? i was just following a tutorial (and in the tutorial did work so i thought it would be something wrong in my code)
Kouhai
Kouhai2y ago
It won't work without adding JWT auth services, so the tutorial should have that.
NDOT
NDOT2y ago
where can i insert then?
Kouhai
Kouhai2y ago
Do you have startup.cs file?
NDOT
NDOT2y ago
nop .net 6 doesn't have one, it's the Program.cs, but works almost the same way i think
Kouhai
Kouhai2y ago
Yeah, it's the same, you have to add couples of things 1 - The middleware for authentication and authorization 2 - Add authentication services by calling AddAuthentication and then adding AddJwtBearer
NDOT
NDOT2y ago
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = domain;
options.Audience =builder.Configuration["Auth0:Audience"];
// If the access token does not have a `sub` claim, `User.Identity.Name` will be `null`. Map it to a different claim by setting the NameClaimType below.
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.NameIdentifier
};
});
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = domain;
options.Audience =builder.Configuration["Auth0:Audience"];
// If the access token does not have a `sub` claim, `User.Identity.Name` will be `null`. Map it to a different claim by setting the NameClaimType below.
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.NameIdentifier
};
});
i did put both, but i didn't find about how to add the middleware in .NET 6 without using the Startup.cs
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
NDOT
NDOT2y ago
update> i actually just get a read on a tutorial and find out how to make it work, and worked, thanks
Want results from more Discord servers?
Add your server