C
C#14mo ago
Philémon

✅ AuthorizationHandlerContext in ASP.NET API with Auth0

Hello 😅 I am trying to implement Auth0 in my ASP.NET API consumed by Angular app. It is a personal project. For some reason that i can't find, I am not authorized to Update my Ingredient (Its an application to manage cooking recipes). I tried to follow every guides from Auth0 to implement it right, and i really can't find where i did wrong. Right now, if i call the API endpoint to update ingredient, it says I am Unauthorized (in the logs): 2023-09-24 02:40:18.414 +02:00 [INF] Authorization failed. These requirements were not met: Kitchen.Api.Tools.HasScopeRequirement When i debug my API, and i arrive at the point of this code :
public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement)
{
// If user does not have the scope claim, get out of here
if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
return Task.CompletedTask;
...
public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement)
{
// If user does not have the scope claim, get out of here
if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
return Task.CompletedTask;
...
I see that my "context" has an error in Resource. It says in the debug window : Session = '((Microsoft.AspNetCore.Http.DefaultHttpContext)context.Resource).Session' threw an exception of type 'System.InvalidOperationException' Also this context has no claims, that's why it returns out of the method and says I am Unauthorized... I guess ? I am trying to make a good auth for my app and i have no idea of where to look at to solve this problem. Thank you for reading this, i hope someone will be able to give me some direction. Peace ✌️
82 Replies
JakenVeina
JakenVeina14mo ago
that "error" is irrelevant yes, attempting to access the .Session property throws an exception, cause you're not using session state the error is pretty straightforward, both in that code, and in the error message the endpoint requires that the user has the scope claim, and it doesn't if there are no claims at all, it suggests your browser client is either not authenticated, or the authentication middleware is improperly configured, somehow, such that authentication is failing
Philémon
PhilémonOP14mo ago
Ok thanks a lot @jakenveina ! I am indeed authenticated in the browser, and in my Auth0 logs the login is succesful So the problem must lie in my authentication middleware configuration
JakenVeina
JakenVeina14mo ago
what're you using?
Philémon
PhilémonOP14mo ago
JwtBearerDefaults.AuthenticationScheme is what I am using
JakenVeina
JakenVeina14mo ago
let's see the config for it, then
Philémon
PhilémonOP14mo ago
Nice 😁 Thank you for your help, i will put the code here
JakenVeina
JakenVeina14mo ago
and let's look at what's in the request, too
Philémon
PhilémonOP14mo ago
So, for the "sensible information" i have my Domain and Audience in app settings, to start with Then i have installed the two nuget packages : System.IdentityModel.Tokens.Jwt and Microsoft.IdentityModel.Tokens. I have both because i tried first only the System one, and i had internal error in my API. Idk if it solved anything tho, because i changed my Angular code and it worked around this. Then in my Service Registration i have this :
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = domain;
options.Audience = configuration["Auth0:Audience"];
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.NameIdentifier
};
});

services.AddAuthorization(options =>
{
options.AddPolicy("update:ingredients", policy => policy.Requirements.Add(new
HasScopeRequirement("update:ingredients", domain)));
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = domain;
options.Audience = configuration["Auth0:Audience"];
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.NameIdentifier
};
});

services.AddAuthorization(options =>
{
options.AddPolicy("update:ingredients", policy => policy.Requirements.Add(new
HasScopeRequirement("update:ingredients", domain)));
});
I also have added the app.AddAuthentication before the AddAuthorization in Program I have also "made" two classes that were recommended in the Auth0 tutorial webiste, they are called HasScopeRequirement and HasScopeHandler, but i don't know if its really at the middleware level? I don't think so The HasScopeHandler inherits from AuthorizationHandler<HasScopeRequirement> Do you mean the Angular request ? Or the Update Ingredient endpoint in my API ? 😁
Philémon
PhilémonOP14mo ago
This is the request, but it is weird because i don't have any response... the Unauthorized is in the Headers Status, it seems ?
No description
JakenVeina
JakenVeina14mo ago
uhhh.... aren't those the same thing? yeah, you should be able to see the bearer token being sent in the request there
Philémon
PhilémonOP14mo ago
So the problem is my Angular?
JakenVeina
JakenVeina14mo ago
no, the section for request headers is collapsed. status is the first of the response headers if there is no Bearer header in the request, then yes, the problem is client-side
Philémon
PhilémonOP14mo ago
No bearer it seems, okay thats weird
JakenVeina
JakenVeina14mo ago
show me
Philémon
PhilémonOP14mo ago
No description
Philémon
PhilémonOP14mo ago
There is something saying Bearer tho, i missed it sorry www-authenticate But its probably not a token 🤣 I do struggle with my Angular configuration in app.module to register Auth0 There are few things that i don't understand yet If i add a scope to my Angular Auth0, then i have internal error saying it can not fetch my open id configuration endpoint But if i don't put the scope, it just says unauthorized
JakenVeina
JakenVeina14mo ago
that's in the response that's part of the 401, the server is trying to tell the client "here's the type of auth I'm expecting"
Philémon
PhilémonOP14mo ago
I can show you the error when i try with the scope ? If it can help?
JakenVeina
JakenVeina14mo ago
anyway, yeah, I tried using Angular once like 8 years ago, kinda hated it so, I really have no clue
Philémon
PhilémonOP14mo ago
Haha i can understand why The error is an asp .Net internal one tho
JakenVeina
JakenVeina14mo ago
I can link you to the JS Discord, there ought to be Angular folks there
Philémon
PhilémonOP14mo ago
But yes, its linked to angular... heavily
JakenVeina
JakenVeina14mo ago
but that definitely seems to be where the issue is roughly, what should happen here....
Philémon
PhilémonOP14mo ago
Ok thank you, i can work on my angular now because i thought the problem came from my API You helped me alot
JakenVeina
JakenVeina14mo ago
A) When you click login or whatever, angular should redirect you to the Auth0 provider, with a few bits of info in the URL
Philémon
PhilémonOP14mo ago
Eliminating possibilities is a huge deal in solving problems, and i could not do it anymore,i was stuck
JakenVeina
JakenVeina14mo ago
one of those bits should be the scope that you're asking for
Philémon
PhilémonOP14mo ago
Ok
JakenVeina
JakenVeina14mo ago
I.E. a list of things your app is requesting access to
Philémon
PhilémonOP14mo ago
Ok i see now
JakenVeina
JakenVeina14mo ago
one might just be "oidc" for "Open ID Connect"
Philémon
PhilémonOP14mo ago
or email i saw that when i logged in
JakenVeina
JakenVeina14mo ago
I.E. you don't need access to anything, you're just trying to ID who the user is yeah, "email" would be a common one the user then gets a prompt that says "this app is asking for X, Y, and Z, is that okay?"
Philémon
PhilémonOP14mo ago
Yes i had this one, but it didnt ask me for the scope i need
JakenVeina
JakenVeina14mo ago
also possible, depending on provider, is that you have to pre-register your app for what scopes you want
Philémon
PhilémonOP14mo ago
Is it possible that the API gives internal error if the scopes in the JWT given by request are not the ones expected ?
JakenVeina
JakenVeina14mo ago
assuming the user approves and then logs in successfully, the Auth0 provider redirects back to your app, with an encoded token
Philémon
PhilémonOP14mo ago
Ok nice This part works but not .. 100 % haha
JakenVeina
JakenVeina14mo ago
and inside the token would be one or more "scope" claims matching the scopes you asked for which your API leverages for its own endpoints
Philémon
PhilémonOP14mo ago
Ok i can i see them in the token
JakenVeina
JakenVeina14mo ago
I.E. if you write an endpoint that involves sending an e-mail to the user, it probably needs that "email" scope but that's 100% on you to figure out what you may or may not need on all your own endpoints
Philémon
PhilémonOP14mo ago
Ok i think the problem is that my API requires an "update:ingredients" scope but i never give it from my Angular
JakenVeina
JakenVeina14mo ago
as in "500 Internal Error"? No, it ought to be a "403 Forbidden"
Philémon
PhilémonOP14mo ago
Ah, ok
JakenVeina
JakenVeina14mo ago
as in "You are authenticated and I know what permissions (scopes) you have and the one this endpoint requires isn't one of them"
Philémon
PhilémonOP14mo ago
OK, seems logical
JakenVeina
JakenVeina14mo ago
who is the Auth0 provider here?
Philémon
PhilémonOP14mo ago
So i will deal with scopes first, and then the future interal error if it s still there Hmm sorry i don't understand... i thought that Auth0 was the provider ? identity provider?
JakenVeina
JakenVeina14mo ago
Auth0 is a protocol who is hosting your login page?
Philémon
PhilémonOP14mo ago
I will login to see
JakenVeina
JakenVeina14mo ago
generally, a protocol for using third-party authentication uhhh I mean I'm not sure how you wouldn't know when you click your "Login" button or whatever, where does it take you?
Philémon
PhilémonOP14mo ago
It is auth0 , right? And OAuth2 is the standard, no ? I use Auth0 I can login with google also i think
JakenVeina
JakenVeina14mo ago
all of those names are so ill-defined, they're damn-near useless okay so, like, when you click "Login" you go to a google login page
Philémon
PhilémonOP14mo ago
Not really
Philémon
PhilémonOP14mo ago
No description
JakenVeina
JakenVeina14mo ago
oh okay auth0.com
Philémon
PhilémonOP14mo ago
the favicon has an error tho
JakenVeina
JakenVeina14mo ago
I didn't know that was an actual company name okay my mistake
Philémon
PhilémonOP14mo ago
Yes and i thought it was not free plan but free plan exists too, i learnt it yesterday haha
JakenVeina
JakenVeina14mo ago
so, does this platform exist purely for providing authentication/authorization?
Philémon
PhilémonOP14mo ago
I was searching for free provider, for my dev project Yes i think so
JakenVeina
JakenVeina14mo ago
like, do you have a UI you go into to define your own scopes?
Philémon
PhilémonOP14mo ago
Ah
JakenVeina
JakenVeina14mo ago
and give them to certain users?
Philémon
PhilémonOP14mo ago
Yes Exactly
JakenVeina
JakenVeina14mo ago
okay
Philémon
PhilémonOP14mo ago
I created a role, and permissions
JakenVeina
JakenVeina14mo ago
biiiiiiingo so, skip the part about the user "approving" certain access, but otherwise all the same you'll define "update:ingredients" as a scope if that's what you want and you're responsible for assigning that to certain users and Auth0 will spit out tokens with that claim in it
Philémon
PhilémonOP14mo ago
But i did it already 😭
JakenVeina
JakenVeina14mo ago
right and you said you could actually see that claim in the token you got, yeah? it's just Angular not forwarding it on
Philémon
PhilémonOP14mo ago
I don't know if i saw this one in the claim, probably not but i saw claims like email
JakenVeina
JakenVeina14mo ago
should be easy enough to find out
Philémon
PhilémonOP14mo ago
YES i recall seeing my update:ingredients in claims But it didnt work at that time because of internal error i think Yes i hope so I think i don't understand basic things in angular auth0 configuration I can redo it And see the claims 😁 Maybe it will show the error i can give you, but yes, if its just angular problem I have to understand how to register my scope in Angular Because in the UI of the website Auth0 i think my role and permissions are correctly set
JakenVeina
JakenVeina14mo ago
if the scope is in the token, then yes sure sounds like it
Philémon
PhilémonOP14mo ago
"scope": "openid profile email update:ingredients", Ok nice But i have Failed Silenth Auth now 🤣 new error, that's good ! Probably 100% in my angular, since it seems the app logs me out every time i try to see my ingredients Damn I m back to square 1 i think, the initial problem is still here. I saw my bearer token, it seems really nice But i have this error in the logs : 2023-09-24 06:51:22.487 +02:00 [ERR] Exception occurred while processing message. System.InvalidOperationException: IDX20803: Unable to obtain configuration from: {myopenId configuration endpoint} at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel) at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
JakenVeina
JakenVeina14mo ago
what's myopenId configuration endpoint? the Auth0 endpoint?
Philémon
PhilémonOP14mo ago
Yes I have hidden it because i understood that its sensitive But its the same link as MyOpenId Configuration , in endpoints in the UI of Auth0 I can access it in the browser. Its a simple link to well-known .well-known/openid-configuration But somehow my API can't access it, idk why I saw someone on stackoverflow 'solve' this problem by adding in the AddJwtBearer options the line
options.Configuration = new OpenIdConnectConfiguration();
options.Configuration = new OpenIdConnectConfiguration();
I tried it, and indeed i don't have the internal error at this moment But then i have a request error like : error="invalid_token", error_description="The issuer 'https/{myissuer}' is invalid" And i feel like this is not a real solution, but that it just 'hides' the problem
JakenVeina
JakenVeina14mo ago
well, if the GetConfig call to Auth0 is failing, you need to figure out why you're probably gonna have to pull up, like, wireshark, or something similar, and inspect the request and response for yourself
Philémon
PhilémonOP14mo ago
Holy guaccamole
JakenVeina
JakenVeina14mo ago
or enable more-verbose logging
Philémon
PhilémonOP14mo ago
Why is this so hard to use a decent auth provider OK thank you for all your help @jakenveina , I will try to continue I really appreciate the time you took, its very cool 😁
Accord
Accord14mo 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