dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.44k stars 10.02k forks source link

Clarify auth plan for Blazor web project template #48772

Closed SteveSandersonMS closed 1 year ago

SteveSandersonMS commented 1 year ago

In recent discussions, it was unclear what is committed for delivery here. Will the new Blazor web project template have auth options? If so, which ones?

Is any other integration needed between Blazor fullstack with ASP.NET Core auth? Is there an IAuthenticationStateProvider in place that just works? Is this meant to have any integration with interactive server/WebAssembly components?

JeremyLikness commented 1 year ago

Tagging @javiercn and @halter73 who have been working on planning for this. The goal is to have auth options. I believe Stephen will be looking at this after he completes some template and API changes.

We need to design what makes sense for the new project given the flexibility for server and client-side rendering. Here's what we currently propose:

I'll post updates here as we design the right solution for the new template.

JeremyLikness commented 1 year ago

This is our current server-scaffolded Identity UI for reference.

graph LR

A[Register] --> B[Login]
B --> C[Confirm Email]
C --> D[Forgot Password]
D --> E[Reset Password]
B --> F[External Login]
F --> G[External Provider]
G --> B
B --> H[Two-Factor Authentication]
H --> I[Recovery Code]
I --> J[Verify Phone]
H --> K[Setup Authenticator]
K --> L[QR Code]
K --> M[Manual Entry]
H --> N[Reset Authenticator]
N --> O[New Authenticator]
O --> K
B --> P[Lockout]
P --> Q[Unlock Account]
B --> R[Remember Me]
B --> S[Logout]
S --> T[Post Logout]
T --> B
danroth27 commented 1 year ago

When you have a Blazor Web App and you're using WebAssembly hosted components, we need some way to flow the authentication state to the browser. We could either, 1. Use the new Identity endpoints, or 2. Persist the authentication state into the page so that it can be extracted. @halter73 @javiercn What are your thoughts on this?

danroth27 commented 1 year ago

We also want to have tooling support for scaffolding a default identity UI based on Blazor into an app and to setup authentication with the Microsoft Identity Platform via Add Connected Services. We should work with @vijayrkn and @sayedihashimi on this.

danroth27 commented 1 year ago

We should consider renaming the "Individual user accounts" option on the Blazor WebAssembly (standalone) template as it won't be related to ASP.NET Core identity at all. Maybe "External identity provider"?

damienbod commented 1 year ago

@danroth27 "When you have a Blazor Web App and you're using WebAssembly hosted components, we need some way to flow the authentication state to the browser. We could either, 1. Use the new Identity endpoints, or 2. Persist the authentication state into the page so that it can be extracted. @halter73 @javiercn What are your thoughts on this?"

Please do not use Identity endpoints for this as it cannot be reused then. Most Web Apps will be or should be using an OIDC client in the server part of the application and not identity unless rolling out your own auth. The UI should work independently of the auth used in the server part, it would need a simple way of getting the claims from the session, some type of common session endpoint API (cookie auth) to get the claims as the UI part cannot read the cookie directly.

Greetings Damien

javiercn commented 1 year ago

@danroth27 @JeremyLikness Adding my suggestions here on how this can be done, although I think we've already talked about this.

The new Blazor template would work like the old Blazor template when it comes to auth. It will pick up the user that is identified on the request. That will work for Server and Server interactive. It does not necessarily need to be tied up to cookies.

For webassembly, it should be transparent, and if the authentication state is needed for some reason, it can be transferred down to the browser via the mechanism we have to persist prerendered state.

halter73 commented 1 year ago

The UI should work independently of the auth used in the server part, it would need a simple way of getting the claims from the session, some type of common session endpoint API (cookie auth) to get the claims as the UI part cannot read the cookie directly.

@damienbod Agreed. The Identity user info endpoint will not rely on a particular authentication scheme like cookies. It will work for any authenticated request. However, it probably will rely on using Identity and having a UserManager available, but that doesn't force you to use local auth. See https://github.com/aspnet/Identity/issues/1824#issuecomment-396280861 for how to disable the default Identity UI.

it can be transferred down to the browser via the mechanism we have to persist prerendered state.

@javiercn What mechanism is this? Is there an issue or PR I can look at to see the current design/implementation?

javiercn commented 1 year ago

@halter73 https://learn.microsoft.com/en-us/aspnet/core/blazor/components/prerendering-and-integration?view=aspnetcore-7.0&pivots=server#persist-prerendered-state

It also works on services.

damienbod commented 1 year ago

@halter73 Thanks for your feedback. I still think Identity is maybe not needed, it provides much more than required. All you need is a user endpoint, a login/logout, maybe some CSP logic for the nonce stuff through a proxy and small changes for the PWA support.

The user endpoint could be really simple:

https://github.com/damienbod/Blazor.BFF.OpenIDConnect.Template/blob/main/BlazorBffOpenIdConnect/Server/Controllers/UserController.cs

The login, logout:

https://github.com/damienbod/Blazor.BFF.OpenIDConnect.Template/blob/main/BlazorBffOpenIdConnect/Server/Controllers/AccountController.cs

plus CSP nonce support and the PWA support.

Maybe identity is too much?

Greetings Damien

markushaslinger commented 1 year ago

I'd like to +1 that working basic auth with a transparent transition between server and wasm is needed and I very much hope you'll manage to get it in for 8.

markushaslinger commented 1 year ago

EDIT: In case anyone else finds this - I got a response from @danroth27 who clarified that the whole auth story is scheduled for rc1 now, which answers my question below.

@mkArtakMSFT is the delay only for the template part or the required packages as well? I don't mind manually cobbling it together, so having it in the template right away is not that important.

But having the parts and being able to integrate auth is pretty essential since its integrated everywhere, from the beginning. We are planning to start implementing with preview 6 or 7 the latest - I know that's a little early, but it's so close to RC and I really don't want to lock in on the old model for this new project. If you won't be able to ship the auth packages before the RC (😭), is there at least a recommendation how to implement it (based on Blazor server style, the only thing that kind-of works at the moment) to have a somewhat manageable upgrade path? What I mean: is there a PR, branch or proposal somewhere how it's going to look?

darena-pjindal commented 1 year ago

Hello - we have a large Blazor Server application and an MVC application deployed in our organization. We are trying to merge the components of Blazor Server Application into the MVC application and leverage .net 8 SSR. We are using OIDC authentication in our MVC. Could you please share some guidance on how to implement authentication in the blazor components. Can we use httpcontext and other features available through MVC or do we need to have a separate authentication state provider? We do not plan to use Blazor Server at all. Thanks so much.

danroth27 commented 1 year ago

Hello - we have a large Blazor Server application and an MVC application deployed in our organization. We are trying to merge the components of Blazor Server Application into the MVC application and leverage .net 8 SSR. We are using OIDC authentication in our MVC. Could you please share some guidance on how to implement authentication in the blazor components. Can we use httpcontext and other features available through MVC or do we need to have a separate authentication state provider? We do not plan to use Blazor Server at all. Thanks so much.

@darena-pjindal You should be able to use the same authentication state provider that we setup in the Blazor Server template when authentication is enabled. Let me know if you're having issues with that.

darena-pjindal commented 1 year ago

Hi @danroth27 - thanks for your reply. Our scenario is very simple. We don't want to do any client interaction, just leverage all the blazor goodness in a RazorPage/MVC application. It seems that we can create a very simple AuthenticationStateProvider that just leverages the asp.net core framework. I have created a sample here where I started with an MVC application and then added Blazor goodness to it step by step. It seems to work as expected. It seems too easy, so I just want to confirm that I am not missing anything :). Can you please confirm that it is ok to use the httpcontext in in an authenticationstateprovider like this if we don't plan to use any client (server or wasm) in our blazor . https://github.com/darena-pjindal/MvcToBlazor/blob/main/MVCToBlazor/MVCToBlazor/MvcAuthenticationStateProvider.cs

mrpmorris commented 1 year ago

Hi @danroth27

I've copied the approach on github.com/danroth27/Net8BlazorServer where the Host.razor has the line <App @rendermode="RenderMode.Server"/>

But I really want to decide on a per-page basis, so I have removed the @rendermode part, and instead put the following on all of my .razor files (except the layout) @attribute [RenderModeServer]

The problem I have with this is, when I run the application I get the following error in the browser console. Error: System.InvalidOperationException: Authorization requires a cascading parameter of type Task. Consider using CascadingAuthenticationState to supply this.

I do use CascadingAuthenticationStateProvider as the root of my App.razor. I have discovered that we can mitigate the error with the following...

builder.Services.AddScoped<AuthenticationStateProvider, MyServerAuthenticationStateProvider>();

public class MyServerAuthenticationStateProvider : AuthenticationStateProvider
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyServerAuthenticationStateProvider(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        bool isAuthenticated = _httpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated == true;
        var state = isAuthenticated
            ? new AuthenticationState(_httpContextAccessor.HttpContext.User)
            : new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
        return Task.FromResult(state);
    }
}

But I believe it is bad practice to use IHttpContextAccessor in this way. What can you recommend I do instead?

danroth27 commented 1 year ago

@mrpmorris Can you open a separate issue for this and share your project so we can take a look at what you are doing?

johnpeeke commented 1 year ago

@mrpmorris @danroth27 I don't know if this helps. But playing with the new blazor ssr, there is no AuthenticationStateProvider registered by default so CascadingAuthenticationState won't work. I had to do this, which registers the blazor server scenario which includes a default provider.

builder.Services.AddRazorComponents() .AddServerComponents();

Are we ok with not using the .AddServerComponents() and just implementing and registering our own CustomAuthenticationStateProvider and using the IHttpContextAccessor as you show?

johnpeeke commented 1 year ago

@mrpmorris @danroth27 I don't know if this helps. But playing with the new blazor ssr, there is no AuthenticationStateProvider registered by default so CascadingAuthenticationState won't work. I had to do this, which registers the blazor server scenario which includes a default provider.

builder.Services.AddRazorComponents() .AddServerComponents();

Are we ok with not using the .AddServerComponents() and just implementing and registering our own CustomAuthenticationStateProvider and using the IHttpContextAccessor as you show?

Actually looks like a parameter for the http context is coming down the pipe to get off the dependency of IHttpContextAccessor. https://github.com/dotnet/aspnetcore/issues/48769. Maybe RC2?

halter73 commented 1 year ago

Actually looks like a parameter for the http context is coming down the pipe to get off the dependency of IHttpContextAccessor. https://github.com/dotnet/aspnetcore/issues/48769. Maybe RC2?

Yes. https://github.com/dotnet/aspnetcore/pull/50253 addresses this and will be available in RC2.

The current plan is to register an AuthenticationStateProvider in the Blazor Web template using PersistentComponentState.RegisterOnPersisting similar to https://github.com/dotnet/aspnetcore/blob/2de2276c384ff14d77985835a46d7573352fb664/src/Components/Shared/src/DefaultAntiforgeryStateProvider.cs. That work is being tracked by https://github.com/dotnet/aspnetcore/issues/48786.

@javiercn Mentioned we may need a way to disable enhanced navigation for sign in and sign out since PersistentComponentState will not retrigger during enhanced navigation which could cause problems when the authentication state changes which is being tracked by https://github.com/dotnet/aspnetcore/issues/50290.

JohnGalt1717 commented 1 year ago

Ok, so RC1 shipped and the documentation isn't updated on how to make this work. We have created a new project with --use-wasm and then tried to add oidc to the wasm project to no avail and can't figure out how this is intended to work (if it indeed works at all)

And dotnet new has no option for adding authentication for just "blazor" and of course in the Wasm project there is no index.html anymore either.

Is there documentation on doing this now somewhere that I can't find?

ChristianWeyer commented 1 year ago

Ok, so RC1 shipped and the documentation isn't updated on how to make this work. We have created a new project with --use-wasm and then tried to add oidc to the wasm project to no avail and can't figure out how this is intended to work (if it indeed works at all)

And dotnet new has no option for adding authentication for just "blazor" and of course in the Wasm project there is no index.html anymore either.

Is there documentation on doing this now somewhere that I can't find?

Do we have any docs or sample for authN with WASM in RC1 @danroth27 .cc @guardrex ? Thanks!

guardrex commented 1 year ago

If you mean for standalone WASM, the current articles should work πŸ€žπŸ€, but I haven't validated the guidance for 8.0 yet. I hope to reach it in the RC2 timeframe. For BWAs, I'm not even sure that the paint is dry on security features for RC2 yet. The current plan is to work on the guidance after RC2 comes out next month. There's usually too much churn when security features are churning during a preview release for me to write docs before that preview releases.

If you try the standalone WASM guidance as it stands with RC1 and hit anything interesting, good or bad. Open a docs issue using the This Page feedback button/form at the bottom of the topic to let me know. I'll note your issue(s) on my .NET 8 tracking issue for the upcoming work.

JohnGalt1717 commented 1 year ago

I don't know about full standalone, but Blazor + Blazor.Client scenarios are completely broken as it stands. And given that Blazor.Client will be used primarily in an authenticated environment, it means that it's functionally not very useful (to say the least) as it stands today.

danroth27 commented 1 year ago

@JeremyLikness

JohnGalt1717 commented 1 year ago

I should also note that your .net 8 token authentication implementation has the same security issue as implicit flow with OIDC which has been depreciated for PKCE, so please don't just enable this only for that scenario, make sureit works with PKCE auth flow on OIDC.

I'd argue that this is blocker for .net 8 release because the primary use case is blocked until such time as it works.

JeremyLikness commented 1 year ago

To clarify: this was an intentional custom implementation that is not intended to be considered an OIDC flow. There is a separate OIDC handler (not part of these changes) and third-party solutions that support scenarios like code flow with PKCE. The implementation as is has been and will be reviewed by our security team. We are working to ensure the documentation is clear on these points and security trade-offs compared with other approaches. Implicit flow is less secure than code flow for a variety of documented reasons that as far as I'm aware of can be mitigated.

Pinging @halter73 in case he has additional thoughts.

JohnGalt1717 commented 1 year ago

The issue is that the current OIDC implementation from .NET 7 according to the documentation doesn't support code flow and only the depreciated implicit flow. Thus, it shouldn't be used in a production environment and using Microsoft ADAL is not an option for the majority of users and locks .net users into Azure if using Blazor.

This is the blocker for release as the primary use case of WASM will be authenticated apps. (and Blazor in general still needs fully functioning OIDC client of which I'm not aware of any 3rd party doing a fully compliant OIDC open-source client, please feel free to suggest alternatives to the built in Blazor authentication provider if there is one, the standard one (OIDC-Client) for Maui/WPF/WinForms/Xamarin/WinUI has no samples and doesn't appear to support Blazor.)


Secondarily, the token auth that is in .net 8 is VERY similar to impicit flow of OIDC. While the endpoints aren't the same, even the payloads are almost identical. Out of the box it is susceptible to exactly the same weaknesses (that the login requests returns the tokens directly as an example).


Given that most enterprise customers have OpenIDConnect through either azure or 3rd parties like Ping etc. it's vital that this works, or it will be a blocker to adoption of blazor even in enterprises to say nothing of smaller shops that want to authenticate with say Google or others.

JeremyLikness commented 1 year ago

Can you clarify what client you are referring to and what documentation states it doesn't support code flow? Microsoft.AspNetCore.Components.WebAssembly.Authentication has a .NET 8 version. What's the scenario it's not supporting? The only thing I'm aware of is no flows that require storing client secrets, which is guidance for all browser-based apps and not just Blazor.

For Blazor server, same story with Microsoft.AspNetCore.Authentication.OpenIdConnect.

What am I missing?

JohnGalt1717 commented 1 year ago

https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/?view=aspnetcore-7.0

Under "Use The Authorization Code flow with PKCE. It states that MSAL supports it with links on how to use MSAL with Blazor. After the entire rest of the document being about the Authentication provider for OIDC based on oidc.js which supports code flow out of the box and the samples for the Authentication library all being implicit flow, not code flow despite it saying in this very section that Microsoft doesn't recommend implicit flow.

I'd suggest that the documentation be updated to show the use of Authorization Code flow with PKCE with the authorization library if it indeed does work without MSAL and that it be explicit about it, how to set the flows, and what is preferred.

This should also be updated for MAUI hybrid, because in that scenario it needs to do interop to the Maui client and OS and should use OIDCClient (for C#) or similar to accomplish the same as apps will get rejected from both stores for not using the protected authentication clients available for iOS and Android and instead doing it in the browser frame of Blazor embedded.

PS: Even this page: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/standalone-with-authentication-library?view=aspnetcore-7.0&tabs=visual-studio doesn't address flows at all or how to set which to use etc. in the code or why. And the .NET 8 version of the page appears to have 0 changes.

guardrex commented 1 year ago

@JohnGalt1717 ... That's a documentation bug. Yes! on updating it. I'll take care of it today/tomorrow on ...

https://github.com/dotnet/AspNetCore.Docs/issues/30418

And the .NET 8 version of the page appears to have 0 changes.

The guidance hasn't been reached for .NET 8 updates. We plan to reach it after RC2 lands next month and before 8.0 RTM in November.

guardrex commented 1 year ago

@JohnGalt1717 ... It looks like there was one particularly offensive line that slipped through the MSAL updates. I'm fixing it on https://github.com/dotnet/AspNetCore.Docs/pull/30421.

I'm not aware of any problems with the OIDC process remarks further down the article, BUT we will be reviewing/updating everything in the RC2 timeframe, when new Blazor Web App security guidance will be added to the docs.

If you found anything in addition to that one line that refered to the OIDC Client Library (instead of MSAL), could you let me know on the PR? I'll fix whatever else we can find and get that merged today.

davidfowl commented 1 year ago

@JohnGalt1717 This flow isn't equivalent to the implicit flow, it's equivalent to the ROPC (Resource Owner Password Credential) flow, which is something you would never do if you were doing delegated authentication (you don't want to give my application your google credentials), but for 1st party auth, it's just fine. AFAIK PKCE isn't relevant to this discussion.

JohnGalt1717 commented 1 year ago

@JohnGalt1717 This flow isn't equivalent to the implicit flow, it's equivalent to the ROPC (Resource Owner Password Credential) flow, which is something you would never do if you were doing delegated authentication (you don't want to give my application your google credentials), but for 1st party auth, it's just fine. AFAIK PKCE isn't relevant to this discussion.

Indeed. It's even more ancient than implicit flow which based itself originally on ROPC on oauth2.

And as one of the leading experts in the field that literally wrote the book on the subject for .NET @kevinchalet said on the comments for the article by @andrewlock just the other day: It's ok, as long as you don't let anyone else use your (auth) system.

Of course, the client_id can't be used to do that, because it's in the clear in the browser. Nor can the source URL because it's trivial, especially with SPAs to just spoof the request domain with your HOSTS file. And that's before you move to anything even remotely more complex.

But this is specifically about the blazor template with automatic rendering using dual projects for which Auth doesn't work at all, and the documentation imply(ed) that The Auth provider that doesn't use MSAL and instead Oidc.js doesn't support PKCE code flow and you had to use MSAL to get code flow which is incorrect so I requested the documentation be updated to make that clarification (which I believe is now in pull request) and to carefully consider messaging for the .NET 8 version of this stuff once security in the RenderMode.Auto is figured out making sure to not dump OpenIdConnect with Auth Code Flow (without MSAL) as the default since any serious user, including the Enterprises that drive most of what goes on in MS will be using because Andrew Lock is correct. As is Kevin: .NET had an opportunity to follow THE standard for auth which everywhere else in Microsoft also follows and contributes to on the steering committee and at the very least provide the one baseline flows correctly implemented with a single line of code, and provide extensibility endpoints for others like Kevin to implement.

That didn't happen. Now it's about making sure that Blazor doesn't go backwards given that as it stands right now Auth is broken entirely in the new template and thus has to be fixed before release. I just don't want it "fixed" to only work with the ancient oauth2 implementation only or some mess around MSAL lock in. It needs to support OIDC authorization code flow with PKCE as it does with WASM only. I fully realize that VIPs have made their decision on authentication in .NET and literally thousands of voices screaming at you to stop isn't going to matter especially at RC1. (See also the thousands of people screaming to stop and rethink before MAUI came out for similar reasons.)

halter73 commented 1 year ago

But this is specifically about the blazor template with automatic rendering using dual projects for which Auth doesn't work at all

This will be partially addressed in RC2 by the new Identity Components we're adding to the Blazor template with https://github.com/dotnet/aspnetcore/pull/50722.

I understand there are people that do not want to use Identity, but we also plan to document approaches like implementing an AuthenticationStateProvider in the server and client projects that use PersistentComponentState to flow server authentication state to the WebAssembly renderer like PersistingServerAuthenticationStateProvider and PersistentAuthenticationStateProvider do.

If you do use the local Identity template option with RenderMode.Auto, the server implementation will implement a RevalidatingServerAuthenticationStateProvider so it will close any open circuits if the security stamp in the DB changes like the Blazor Server only template did previously. Even this approach isn't specific to Identity and could be used with AddOpenIdConnect or other authentication schemes.

jonhilt commented 1 year ago

I understand there are people that do not want to use Identity, but we also plan to document approaches like implementing an AuthenticationStateProvider in the server and client projects that use PersistentComponentState to flow server authentication state to the WebAssembly renderer like PersistingServerAuthenticationStateProvider and PersistentAuthenticationStateProvider do.

I think this is important. The Auth picture at this stage still feels quite confusing, especially if not using Identity.

It seems people will want to know, if starting with SSR and enabling interactivity for select components using Server/WASM, how the auth pieces all fit together.

For example, if I used a third party auth provider (like Auth0) with .NET 8 SSR, how would I go about setting that up in a way that I can use all of Blazor's auth features in both SSR and interactive modes.

(appreciate that's more of a documentation/guidance question and probably not directly relevant to this thread)

TrieBr commented 1 year ago

Is there as bug tracking documentation being written around this, or can this bug be re-opened until then? As of right now there doesn't seem to be any documentation on setting up authentication in Blazor "united". Should we follow Blazor Server or Blazor WASM?

It still even has language like "Security scenarios differ between server-side and client-side Blazor apps.". I thought Blazor united was supposed to transparently support wasm/pre-rendered.

Edit: 8.0RC2 solved the issue. Thanks for adding the Identity template!

CrahunGit commented 1 year ago

I let you my Auth0 sample with client authentication. It's based on RC2 bits with Individual accounts but removing everythging related to identity. If you would like to see it in action.

https://github.com/CrahunGit/Auth0BlazorWebAppSample

JeremyLikness commented 1 year ago

Hi, we are working to deliver many of these samples for you along with related documentation. We are tracking it in issue #49668 in this repo and issue #29452 in the docs repo. Please feel free to add your comments to our existing issues if you have requests for specific scenarios to cover or other feedback. Thanks!

JohnGalt1717 commented 1 year ago

I can tell you that adding this to _Imports.razor per the docs doesn't work:

@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]

It goes to the authorization/login but never executes the external login process.

CrahunGit commented 1 year ago

For me with auth0 works fine. But it’s better solution to wait for the docs

cculver commented 1 year ago

I let you my Auth0 sample with client authentication. It's based on RC2 bits with Individual accounts but removing everythging related to identity. If you would like to see it in action.

https://github.com/CrahunGit/Auth0BlazorWebAppSample

Thanks for making this available, but I can't seem to access it. Is it public?

CrahunGit commented 1 year ago

Sorry, It's now public.

CrahunGit commented 1 year ago

I've updated it to allow send request from client side with auth0 cookie.

jongio commented 12 months ago

I let you my Auth0 sample with client authentication. It's based on RC2 bits with Individual accounts but removing everythging related to identity. If you would like to see it in action.

Thanks @CrahunGit, this was helpful.

DenisSikic commented 11 months ago

Hey guys,

I spent the weekend migrating my Auth0 based project to .net8 Blazor Web App template. I created a new project and client one as well. Everything except sso works for me. I'm not use WASM yet, just trying to get Server side stuff working for now.

EDIT: I moved everything over from my old project, obviously.

I don't get a login page, I just end up on "/sso/login?ReturnUrl=%2F" with a white page. Tried incognito and wiping out cookies, I don't ever get a login page. If I implement auto-login in my program.cs the rest of the app works fine.

EDIT: Status code is 404 not found.

Curious if there's a .net8 sample project somewhere? Anything special I have to do when migrating from .net 6/7 to .net8?

Does this mean anything? image

jaydeboer commented 11 months ago

@DenisSikic I am in a similar boat. I am moving my .net7 Blazor server with Azure ADB2C authentication to the new Blazor web template. I have everything still rendering on the server, but I am getting 404s looking for /MicrosoftIdentity/Account/SignIn Seems similar to what you were seeing. Have you happened to have made any progress on this? In my case, it is like the

builder.Services.AddControllersWithViews()
    .AddMicrosoftIdentityUI();

lines are not working like they did in .net 7.

DenisSikic commented 11 months ago

Hi @jaydeboer . I used a fresh Blazor Web App template and realized I was missing stuff in Program.cs that is new. Also, I was missing MapRazorPages to activate old cshtml pages which is how my logon/logoff pages were implemented. Look at:

builder.Services.AddCascadingAuthenticationState(); builder.Services.AddScoped<AuthenticationStateProvider, PersistingRevalidatingAuthenticationStateProvider>();

jaydeboer commented 11 months ago

@DenisSikic Thanks for the suggestions. I really thought that was going to be the ticket but it doesn't have appeared to have changed anything. I was using the default UI from

builder.Services.AddControllersWithViews()
    .AddMicrosoftIdentityUI();

I am wondering if that Identity UI is no longer compatible or something.

Here is my Program.cs with my own services removed.

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddMudServices();

// Add services to the container.

#region Auth

builder.Services.AddCascadingAuthenticationState();
//builder.Services.AddScoped<AuthenticationStateProvider, PersistingRevalidatingAuthenticationStateProvider>();
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAdB2C"));
builder.Services.AddControllersWithViews()
    .AddMicrosoftIdentityUI();
builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{

    options.Events.OnRedirectToIdentityProvider = context =>
    {
        // set the redirect URI to the current url
        if (context.Request.Query.ContainsKey("redirectUri"))
            context.Properties.RedirectUri = context.Request.Query["redirectUri"].ToString();
        return Task.CompletedTask;
    };
    // Stolen from https://github.com/dotnet/aspnetcore/issues/18865
    options.Events.OnSignedOutCallbackRedirect = context =>
    {
        context.HttpContext.Response.Redirect(context.Options.SignedOutRedirectUri);
        context.HandleResponse();
        return Task.CompletedTask;
    };
});

builder.Services.AddAuthorization(options =>
{
    // By default, all incoming requests will be authorized according to the default policy
    //options.FallbackPolicy = options.DefaultPolicy;
});

builder.Services.AddRazorPages();

#endregion

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddMicrosoftIdentityConsentHandler()
    ;

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();
app.UseAuthorization();

app.UseAntiforgery();
app.MapRazorPages();
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();
jaydeboer commented 11 months ago

@DenisSikic Good Grief! I kept missing app.MapControllers(); I don't want to know how many times I overlooked that. Sorry for the hassle.