dotnet / AspNetCore.Docs

Documentation for ASP.NET Core
https://docs.microsoft.com/aspnet/core
Creative Commons Attribution 4.0 International
12.56k stars 25.3k forks source link

Cannot use Bearer Token in new asp.net core identity API #31727

Closed SandroRiz closed 7 months ago

SandroRiz commented 9 months ago

Is there an existing issue for this?

Describe the bug

Following the sample published here: https://github.com/dotnet/blazor-samples/tree/main/8.0/BlazorWebAssemblyStandaloneWithIdentity

And the documentation published here: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/standalone-with-identity?view=aspnetcore-8.0

I tried to setup the backend and the front end to use Bearer Token instead cookie but the WASM client doesn't login (but the Register endpoint works)

cc: @guardrex https://github.com/dotnet/AspNetCore.Docs/issues/31194

Expected Behavior

Change the Sample and /or the Documentation indicating

Steps To Reproduce

Change line 9 of backend program.cs adding .AddBearerToken() instead to .AddIdentityCookies() Change line 123 of frontend CookieAuthenticationStateProvider.cs putting false instead true

Exceptions (if any)

No response

.NET Version

8.0.0

Anything else?

I was able to call from Postman the new API with bearer token NOT including the

.AddAuthentication() but only the .AddAuthorization()

basically I copied what you obtain from the new Blazor 8 web app template when you choose to include identity... see attach

Program.zip

guardrex commented 9 months ago

Thanks @SandroRiz.

I can repro the failure following our guidance at ...

https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/standalone-with-identity?view=aspnetcore-8.0#token-authentication

I see ...

System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action configureOptions).

If I try to set the default authentication and challenge schemes with AuthenticationOptions, the error is still thrown.

SandroRiz commented 9 months ago

I had another exception using AddBearerToken calling the Login endpoint

System.InvalidOperationException: No sign-in authentication handler is registered for the scheme 'Identity.Bearer'. The registered sign-in schemes are: BearerToken. Did you forget to call AddAuthentication().AddCookie("Identity.Bearer",...)? at Microsoft.AspNetCore.Authentication.AuthenticationService.SignInAsync(HttpContext context, String scheme, ClaimsPrincipal principal, AuthenticationProperties properties)

guardrex commented 9 months ago

I fixed that (I think) by changing to bearer (IdentityConstants.BearerScheme). For that and the challenge scheme error, I ended up with the non-working code ...

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = IdentityConstants.BearerScheme;
    options.DefaultChallengeScheme = IdentityConstants.BearerScheme;
}).AddBearerToken();
guardrex commented 9 months ago

BTW @SandroRiz ... Oh, nevermind. That's a different section. We have that covered per the Logout component, LogoutAsync method, and app.MapPost("/Logout" ...); of the backend. We're good on that point.

PU: Ignore this comment. I had to go look at the sample app to see how the logout was implemented. We're good on that point.

halter73 commented 9 months ago

We recommend using cookies for browser-based scenarios, because it's usually easier. Cookies are effectively a bearer token the browser automatically manages for you.

If you do want to use bearer tokens instead of cookies (which we recommended more for native and mobile scenarios), you should change _httpClient.PostAsJsonAsync("login?useCookies=true", ...) to just _httpClient.PostAsJsonAsync("login, ...) without the query string here:

https://github.com/dotnet/blazor-samples/blob/0ecc2bc297549b620c74efeb0b42b6ad638982c7/8.0/BlazorWebAssemblyStandaloneWithIdentity/BlazorWasmAuth/Identity/CookieAuthenticationStateProvider.cs#L123

And naturally, since the login response no longer sets a cookie automatically, you then need to parse the AccessTokenResponse on the client and manage the access and refresh tokens yourself.

guardrex commented 9 months ago

Thanks @halter73 ... Between your remarks and Jeremy's remarks earlier, I'll be able to update the token guidance in the Blazor article. I'll ping both of you on the PR when it goes up.

dotnet-policy-service[bot] commented 7 months ago

Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime. To make sure no conflicting changes have occurred, please rerun validation before merging. You can do this by leaving an /azp run comment here (requires commit rights), or by simply closing and reopening.

dotnet-policy-service[bot] commented 7 months ago

Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime. To make sure no conflicting changes have occurred, please rerun validation before merging. You can do this by leaving an /azp run comment here (requires commit rights), or by simply closing and reopening.

guardrex commented 7 months ago

My current understanding is that we aren't going to carry all of the code to implement this scenario per ...

you then need to parse the AccessTokenResponse on the client and manage the access and refresh tokens yourself.

We've left language in the doc to that effect at ...

https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/standalone-with-identity?view=aspnetcore-8.0#token-authentication

@halter73 ... You can re-open this if you (and/or Jeremy) plan to provide additional guidance on this.

lcetinapta commented 7 months ago

Ok, how to parse the AccessTokenResponse.AccessToken? In the .net 7.0 blazor wasm, I used JWT tokens, and they are easy to parse. But the Bearer token is not. First is encrypted, second it is not only base64 encoded but as i see in code it is in binary format. (I saw the code in BearerTokenOptions.Unprotect() method. So I have the problem of using BearerTokens in my wasm blazor app where i need to create claims from it to be able to uze cleint side authorization on pages with the [Authorize] attribute.