C
C#•17mo ago
Candyroll93

asp api 7 jwt not recognizing "Staff" role but recognizes "Customer" role, verified user has staff

Stack Overflow
ASP.NET Core 7 : JWT bearer was challenged due to role
Decoded token from front-end displayed to debug: { sub: "[email protected]", jti: "fd4779c8-2637-4c75-a901-447697274dce", email: "[email protected]", ...
14 Replies
V0FBU1VM
V0FBU1VM•17mo ago
I believe the problem could be because of the way you are adding your roles to the list of claims in the jwt. Also be careful with sensitivity, UserManager might return "staff" and the token "Staff". This could also be a problem.
Candyroll93
Candyroll93OP•17mo ago
thank you for your response. i attempted to authorize "staff" but still the error "Bearer was challenged" persists when using Staff routes. I will try a foreach and manually add them.
V0FBU1VM
V0FBU1VM•17mo ago
Here is an example of how I generate my tokens
public class GenerateTokenHandler : IRequestHandler<GenerateTokenCommand, Token>, IDisposable
{
private const int TokenExpirationDays = 30;
private readonly byte[] _key = Encoding.ASCII.GetBytes(SecretSettings.JwtSigningKey);
private readonly JwtSecurityTokenHandler _tokenHandler = new();

private readonly UserManager<User> _userManager;

public GenerateTokenHandler(UserManager<User> userManager)
{
_userManager = userManager;
}

public void Dispose()
{
_userManager.Dispose();
GC.SuppressFinalize(this);
}

public async Task<Token> Handle(GenerateTokenCommand request, CancellationToken cancellationToken)
{
var expires = DateTime.UtcNow.AddDays(TokenExpirationDays);

var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, request.User.Id.ToString()),
new(ClaimTypes.Name, request.User.UserName ?? string.Empty)
};

var userRoles = await _userManager.GetRolesAsync(request.User);

claims.AddRange(userRoles.Select(role => new Claim(ClaimTypes.Role, role)));

var tokenDescriptor = new SecurityTokenDescriptor
{
Issuer = SecretSettings.JwtIssuer,
Audience = SecretSettings.JwtAudience,
Subject = new ClaimsIdentity(claims),
Expires = expires,
SigningCredentials =
new SigningCredentials(new SymmetricSecurityKey(_key), SecurityAlgorithms.HmacSha256Signature)
};

var token = _tokenHandler.CreateToken(tokenDescriptor);
var tokenString = _tokenHandler.WriteToken(token);

return new Token
{
Content = tokenString,
ExpiresAt = expires
};
}
}
public class GenerateTokenHandler : IRequestHandler<GenerateTokenCommand, Token>, IDisposable
{
private const int TokenExpirationDays = 30;
private readonly byte[] _key = Encoding.ASCII.GetBytes(SecretSettings.JwtSigningKey);
private readonly JwtSecurityTokenHandler _tokenHandler = new();

private readonly UserManager<User> _userManager;

public GenerateTokenHandler(UserManager<User> userManager)
{
_userManager = userManager;
}

public void Dispose()
{
_userManager.Dispose();
GC.SuppressFinalize(this);
}

public async Task<Token> Handle(GenerateTokenCommand request, CancellationToken cancellationToken)
{
var expires = DateTime.UtcNow.AddDays(TokenExpirationDays);

var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, request.User.Id.ToString()),
new(ClaimTypes.Name, request.User.UserName ?? string.Empty)
};

var userRoles = await _userManager.GetRolesAsync(request.User);

claims.AddRange(userRoles.Select(role => new Claim(ClaimTypes.Role, role)));

var tokenDescriptor = new SecurityTokenDescriptor
{
Issuer = SecretSettings.JwtIssuer,
Audience = SecretSettings.JwtAudience,
Subject = new ClaimsIdentity(claims),
Expires = expires,
SigningCredentials =
new SigningCredentials(new SymmetricSecurityKey(_key), SecurityAlgorithms.HmacSha256Signature)
};

var token = _tokenHandler.CreateToken(tokenDescriptor);
var tokenString = _tokenHandler.WriteToken(token);

return new Token
{
Content = tokenString,
ExpiresAt = expires
};
}
}
Candyroll93
Candyroll93OP•17mo ago
ive been seeing the addrange on stack. ill give that a shot. im just perplexed because im using the same code from the Customer token creator and that works. idk what Staff doesnt work
V0FBU1VM
V0FBU1VM•17mo ago
Here is what I get back when decoding the token:
{
"nameid": "a3d55b54-5458-416b-e506-08db88562a14",
"unique_name": "swaggerlife",
"role": "admin",
"nbf": 1689791898,
"exp": 1692383898,
"iat": 1689791898,
"iss": "",
"aud": ""
}
{
"nameid": "a3d55b54-5458-416b-e506-08db88562a14",
"unique_name": "swaggerlife",
"role": "admin",
"nbf": 1689791898,
"exp": 1692383898,
"iat": 1689791898,
"iss": "",
"aud": ""
}
Candyroll93
Candyroll93OP•17mo ago
thats from your tok
V0FBU1VM
V0FBU1VM•17mo ago
You don't really need multiple token generators. One should be enough.
Candyroll93
Candyroll93OP•17mo ago
ok
V0FBU1VM
V0FBU1VM•17mo ago
Yes The token generation method that I sent you. Will get all your tokens from UserManager and store them correctly under Claim.Role.
Candyroll93
Candyroll93OP•17mo ago
ok tyvm.
V0FBU1VM
V0FBU1VM•17mo ago
Hope you find a solution. It's a bit hard to find the issue, without debugging the code.
Candyroll93
Candyroll93OP•17mo ago
unfortunately that didn't do anything. which is weird um i even cleared cookies and cache according to microsoft, jwt roles are stored in a cookie from the api if cached hey you took time to respond earlier so i wanted to update you. Issue Fixed So this was my error. I was using a standard html form with an angular web application because I didn't have enough time to debug a file upload with formdata using reactive forms. My school project was due. The form was being submitted successfully to the api and was not being intercepted by the angular interceptor to send the jwt. It was working exactly how i programmed it to work... unfortunately 🤪
V0FBU1VM
V0FBU1VM•17mo ago
@candyroll93 Good to hear, that you found a solution mate. It's always html's fault 🤣
Accord
Accord•17mo 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.
Want results from more Discord servers?
Add your server