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
34.81k stars 9.84k forks source link

Add Microsoft Identity Platform auth option to the Blazor Web App template #51202

Open danroth27 opened 9 months ago

danroth27 commented 9 months ago

We don't currently support the Microsoft Identity Platform auth option with the Blazor Web App template. We should add it.

danroth27 commented 9 months ago

@jmprieur @JeremyLikness @sayedihashimi @vijayrkn

ghost commented 9 months ago

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

AlbertoPa commented 8 months ago

Seeing this moved to .Net 9 is disappointing. Once again templates won't have a simple and functional way to have a working configuration with Azure ID/Entra, and the current status of the documentation for .Net 8 is also poor, since pages with the details shown for .Net 7 have been removed.

VladislavAntonyuk commented 8 months ago

https://vladislavantonyuk.github.io/articles/Microsoft-Identity-Platform-Authentication-in-Blazor-Web-Application

You can also find a template here: https://www.nuget.org/packages/VladislavAntonyuk.DotNetTemplates/3.0.247-pre4

peterthorpe81 commented 7 months ago

https://vladislavantonyuk.github.io/articles/Microsoft-Identity-Platform-Authentication-in-Blazor-Web-Application

You can also find a template here: https://www.nuget.org/packages/VladislavAntonyuk.DotNetTemplates/3.0.247-pre4

Unless I'm missing something this is just the server rendering solution. It doesn't support the other render modes such as Auto.

VladislavAntonyuk commented 7 months ago

For now, it is the component with InterectiveServerRenderMode only. For Auto, you need to add code to the Client project. Something like this https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/standalone-with-azure-active-directory-b2c?view=aspnetcore-7.0

AlbertoPa commented 7 months ago

I guess the question is how we cover both scenarios that may happen when using auto: the first access is server-side Blazor, the following accesses should be WASM, so the auth workflow changes depending on the render mode or am I missing anything?

Viajaz commented 7 months ago

Very disappointing not to see this in .NET 8 given it's an LTS.

leastprivilege commented 7 months ago

I guess the question is how we cover both scenarios that may happen when using auto: the first access is server-side Blazor, the following accesses should be WASM

This is the kind of guidance I am missing as well @danroth27

peterthorpe81 commented 7 months ago

I guess the question is how we cover both scenarios that may happen when using auto: the first access is server-side Blazor, the following accesses should be WASM, so the auth workflow changes depending on the render mode or am I missing anything?

That's correct although the the transfer to WASM could be at any point and in an advanced scenario it may even go back. I think it needs keeping in sync between the two modes using something like the PersistingRevalidatingAuthenticationStateProvider implemented in the template.

I did notice the HttpClient call for the Weather was also removed from the templates https://github.com/dotnet/aspnetcore/issues/51204. I suspect this was for similar reasons. The HttpClient could be called from Client (WASM) or Server (which is a little wasteful) so you need to register HttpClient on both. Then when you add Authentication and Authorization you have to keep them in sync without using the HttpContext on the server. I know there is the alternative of two implementations of a weather service one for Client and one for Server but code wise that isn't ideal if you are migrating from WASM with WebAPI backend and looking to quickly get the benefits of Auto mode.

It doesn't appear trivial to implement authentication and authorization that works in Auto mode and the templates have neglected to demonstrate it. Essentially anyone using any kind of Auth (most projects?) or HttpClient can't automatically move to Auto mode.

If the templates won't be updated soon, some example projects with Authentication and Authorization scenarios would be great. Ideally I would ideally like to see a Microsoft Identity (Entra) login that works in Auto mode and can make HttpClient calls from Client or Server to an APi using authorization. Additionally it would be great if the project demonstrated adding additional claims in code and [AllowAnonymous] attribute applied on some pages. Some changes appear to have happened around AllowAnonymous to make this work?

AlbertoPa commented 7 months ago

@peterthorpe81 if you look at what happens in the new blazor web app when auto and identity with local user accounts are used, you'll see that the server app manages all the authentication work, and the client (wasm) synchronizes the authentication state with the server app.

Following this logic, auth in auto mode with Microsoft Identity Platform may be done following a similar logic. 🤔

peterthorpe81 commented 7 months ago

@peterthorpe81 if you look at what happens in the new blazor web app when auto and identity with local user accounts are used, you'll see that the server app manages all the authentication work, and the client (wasm) synchronizes the authentication state with the server app.

Following this logic, auth in auto mode with Microsoft Identity Platform may be done following a similar logic. 🤔

Yes this is what I have been looking at but I don't seem to be able to get a config that works in both render modes. I think one of the differences is that local accounts are authenticated within your site using the scaffolded pages. Microsoft Identify Platform is going out to an external site so the redirect loses the state.

AlbertoPa commented 7 months ago

@peterthorpe81 agreed. One less than ideal way is to have the server authenticate with AD, then store the information in the cookie to pass it to the client, but that means the SPA workflow of AD is ignored entirely also when in WASM mode, which I do not think is a great solution.

moshali1 commented 7 months ago

I think if we can get a template for just Interactive Server Per Page/Component, that would be great for now.

AlbertoPa commented 7 months ago

I think if we can get a template for just Interactive Server Per Page/Component, that would be great for now.

Interactive server should have not changed (see the old template). It is just a web app. Similarly, setting up a hosted WASM web-app. The main difference is when using auto mode (but after a few tests, it seems also in this case changes may not be too deep).

shoffma1 commented 7 months ago

I think if we can get a template for just Interactive Server Per Page/Component, that would be great for now.

Interactive server should have not changed (see the old template). It is just a web app. Similarly, setting up a hosted WASM web-app. The main difference is when using auto mode (but after a few tests, it seems also in this case changes may not be too deep).

The key point from my perspective, is that the "old" template only allows choosing .NET 6/7. If one wants to remain on a "supported" version, the only option seems to be to go through the upgrade steps involved ... which is just nowhere near as simple as it has been for previous releases. Further, Visual Studio IntelliSense is breaking when using newer razor components. I've submitted a separate issue via VS for that.

sequarell commented 7 months ago

This issue really breaks Blazor quite a bit for me. In my opinion, authentication with microsoft identity is cruicial for blazor applications, which (at least in my case) are usually small webapps hostet on azure. If there is no template to use this (from an azure-architectural viewpoint) tightly coupled technologies togehter to create a minimal webapp, then this will massivley slow down development of prototypes, which will lead me to consider using other webapp frameworks to build upon. And I don't think that I am alone with this opinion. Please at least provide a timeline for such anupdated template.

mreisz7 commented 7 months ago

I agree that this is a must have. I've been struggling with this.

Mason742 commented 7 months ago

Switched from ASP.NET Identity to Microsoft Identity because of Duende debacle. Now switching back lol, hope my users don't complain too much. I watched the dotnet conf, I don't think it was made clear enough to me that Asp.net Identity no longer depends on Duende?

AlbertoPa commented 7 months ago

Is there an ETA for this for .Net 8, or is it permanently moved to .Net 9?

sundeep22 commented 6 months ago

I have no idea how this feature could have been missed? or is MS only targeting Blazor auto for Independent accounts for dotnet 8 & has a plan to expand it to Identity Platform in 9.0? I can't seem to make it work or find any reliable templates online either.

AlbertoPa commented 6 months ago

@sundeep22 take a look at this unofficial sample: https://github.com/dudley810/dotnet8identityopenid It should give you an idea on how to use AD/Entra.

sundeep22 commented 6 months ago

@sundeep22 take a look at this unofficial sample: https://github.com/dudley810/dotnet8identityopenid It should give you an idea on how to use AD/Entra.

Thanks, will give it a shot!

devonbushhub commented 6 months ago

I think as a minimum we need a page with guidance on how to manually configure the Azure Auth/Cache options to allow us to use Auto. I have been following along with @danroth27 talks with growing enthusiasm. To find out there is no MIP template option is a huge letdown. Especially, given .NET 9 is unlikely to be LTS.

davecader commented 6 months ago

This is a make or break issue for us. Our team was considering Blazor .NET 8 for a new web application, but without proper Entra ID support I can't see going this way. ASP.NET Core with React seems like a much more viable solution IMHO. We were seriously burned by Maui last year, and Blazor .NET 8 has a similarly bad smell.

ghost commented 6 months ago

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

pratt33k commented 6 months ago

Hey there! This might help some of you ( https://www.reddit.com/r/Blazor/s/hhj6PGvuJ8 )

I got to auto mode to work with Azure ad by applying the existing .Net 7 authentication in server side project. To get the client-side project to work with authentication I followed the following documentation here: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-8.0

Essentially you just need to add "builder.Services.AddCascadingAuthenticationState();" in the server project and "builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();" in client project.

"In a server-side Blazor app, services for options and authorization are already present, so no further steps are required."

AlbertoPa commented 6 months ago

Hey there! This might help some of you ( https://www.reddit.com/r/Blazor/s/hhj6PGvuJ8 )

I got to auto mode to work with Azure ad by applying the existing .Net 7 authentication in server side project. To get the client-side project to work with authentication I followed the following documentation here: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-8.0

Essentially you just need to add "builder.Services.AddCascadingAuthenticationState();" in the server project and "builder.Services.AddOptions(); builder.Services.AddAuthorizationCore();" in client project.

"In a server-side Blazor app, services for options and authorization are already present, so no further steps are required."

  • credits: hkstc305 @ reddit

If you have auto or wasm render modes or application, what you suggest is not sufficient. Your application will lose the authentication state it has acquired when working in server mode, and the client won't have consistent information. See https://github.com/dudley810/dotnet8identityopenid for a working example. The documentation you linked for .Net 8 does not provide details on this use case.

In a pure server-side Blazor situation, the app behaves just like a server app, so after registering the "web app" in AD, everything works as usual. A pure WASM application also works exactly as before: register it in AD as SPA, register the API for jwt auth, and it works. It becomes more complex when using pre-rendering of pages that need API calls.

Viajaz commented 6 months ago

I think it would be useful for those who have provided feedback, thus far, to specify if their projects were-going-to-use/are-using Server mode, WASM or Auto. It would be a shame if those with Server mode Blazor Web projects are skipping the stack completely just because of this lack of functionality in the template. I'm almost exclusively dealing with Blazor Server projects but I managed to port the Microsoft.Identity code from .NET 7 templated project to allow for EntraID authentication in a Blazor Web .NET 8 Project in Server Mode, it took a few hours but it was relatively simple.

I think, from the feedback here already, it's evident that we're going to see a whole generation of bespoke apps each with their own authentication implementation (and all the security risks associated with that) just because of this lack of functionality in this template, I think those who were investigating the Auto mode in particular will be especially impacted due to the complexity. .NET developers will be dealing with the fallout from all these bespoke issues, with smaller projects from smaller teams, for years to come and I doubt it will be start to be resolved until the next .NET LTS is released as that is what happened last time .NET Project Templates had missing functionality like this.

AlbertoPa commented 6 months ago

Could this issue be addressed before .Net 9, with an update containing updated templates, instead of stating it will be "considered" for .Net 9, one year away, considering the impact it has?

Stoffe commented 6 months ago

Bumping up this as well, this needs to be addressed in an .net 8 blazor templates update (or documentation) if MS wants to be serious about anyone using blazor. Identity is essential and that it was not introduced a template or even documentation around how to use Identity for external identities (I.e. MS Entra ID, AADB2C, External Identities) in AUTO Mode is for me unbelievable bad planning.

pratt33k commented 6 months ago

Havent tested it but I think they have released a sample recently addressing this issue (enabling Entra ID Auth in a Blazor app with Auto Render mode using OIDC protocol) https://github.com/dotnet/blazor-samples/blob/main/8.0%2FBlazorWebOidc%2FREADME.md

AlbertoPa commented 6 months ago

Thanks @pratt33k . The new template helps, but it also adds a lot of complexity with the endpoint remapping, which adds extra work in practical use cases compared to functionality that was readily available in pre .Net 8 templates. More than a demonstration of capabilities, the new Web App is trying to push one specific development pattern, which is not a one-size-fits-all.

Moreover, if one wants to implement the guidelines provided by Entra, there is nothing that works out of the box in the Auto and WASM modes within the current Web App template, and asking to remapping each endpoint does not seem viable to me.

NitroEvil commented 6 months ago

I've been banging my head against a wall for 2 weeks prior to the Xmas period. Just return to work looking into trying to get Blazor Web App with render mode auto to work and stumbled across a post linking this. I'm disappointed that they is no template for this setup as I've wasted so much time trying to get Entra to work with Blazor on dotnet 8, it's a critical part for the application we build.

I template out of the box should have exist for this, it would be great if something was published before .net 9!

Sef365 commented 6 months ago

We where on the fence of using .net 8 Blazor Auto mode for a new web app. But because of lack of proper Entra ID support we are re-evaluating the choice. Waiting for .net 9 is not an option. Hope that Microsoft reconsiders this feature to be part of an update for .net 8 instead of .net 9

Authentication using Entra ID is trivial as stated by others.

aredfox commented 5 months ago

Could this issue be addressed before .Net 9, with an update containing updated templates, instead of stating it will be "considered" for .Net 9, one year away, considering the impact it has?

This should be addressed, certainly if Blazor wants to be taken seriously as a platform. Top of mind, certainly if you want to draw in new people. I don't understand the decision to postpone this at all. It only hinders growth & acceptance for the platform; and thus hurts it.

If not this, then at least have @danroth27 or @shanselman or anyone else on the team room to give a demo about it. Because for newcomers, who start out with .NET8 and have heard all the "jazz", this will be something they get stuck on for sure!

fmmuir70 commented 5 months ago

I only build intranet web apps (Blazor Server mainly) so incorporating the Authentication type: Windows in .NET 8 Blazor Web Apps would be extremely useful.

EKCG-LouiseNewell commented 5 months ago

I have a .net7 Blazor Server app which is suffering with connectivity issues. All our apps must use Azure authentication and go through proxy servers. I was hoping an upgrade to .net8 Blazor Web App with static pages and auto stuff would help alleviate this, but am struggling to understand how to get the Azure authentication working. The app also relies heavily on Microsoft Graph API and I'm struggling to see how to pass token downstream. Microsoft documentation is a minefield, often out of date and very hard to understand. I find it easier to work from examples and templates.

ADefWebserver commented 5 months ago

I have a tutorial here for Blazor Server: Creating A Blazor Server Azure B2C App (Updated to .NET 8). See it live at: https://aistorybuilders.com/

cfob commented 3 months ago

This I would have thought was bread and butter stuff. I have read of organizations abandoning Blazor because of this issue. Basic templates are needed to support Blazor in a Microsoft Entra ID environment. Delaying the provision of a set of working project templates to .NET 9 is daft. Microsoft will loose good will and customers if this not addressed ASAP.

AlbertoPa commented 3 months ago

@cfob there now are templates for the Web App using OIDC that can be used with Entra.

See: https://github.com/dotnet/blazor-samples/tree/main/8.0

See BlazorWebAppOidc and BlazorWebAppOidcBFF. The first has a minimal API that demonstrates how to call an API. The second uses yarp as reverse proxy and aspire (not mandatory) for service discovery.

cfob commented 3 months ago

Alberto,

Thanks. I'll have a look in the morning.

Conor

⁣Get BlueMail for Android ​

On 14 Mar 2024, 01:02, at 01:02, Alberto Passalacqua @.***> wrote:

@cfob there now are templates for the Web App using OIDC that can be used with Entra.

See: https://github.com/dotnet/blazor-samples/tree/main/8.0

-- Reply to this email directly or view it on GitHub: https://github.com/dotnet/aspnetcore/issues/51202#issuecomment-1996207917 You are receiving this because you were mentioned.

Message ID: @.***>

CodeFontana commented 3 months ago

@AlbertoPa (and @cfob), these are examples, not templates built into Visual Studio.

I also think there's a glaring omission in those templates-- Blazor Server-Side without WebAssembly or Auto mode.

There should be examples and a template for Static server-side rendering, only. And another for Static + Interactive server-side rendering.

These example and templates should include no other fluff, and should be the minimal to get a developer started, i.e. no yarp, reverse proxies, etc.

I realize using Auto mode sounds like you're covering all the bases, but Auto mode is really complicated. I have a feeling most practical development will still choose Server-Side or Client-Side, especially as there are issues with crossing scoped services across render boundaries.

I suppose I will say it. As much as I'm a fan of all the changes in .NET 8-- I mean static server-side rendering is awesome, stream rendering is awesome, enhanced navigation-- all those accomplishments aside, I feel like Blazor for .NET 8 won't actually be done until .NET 9.

When you get down to it, aside from not having an Organization auth template that suits your render mode choice, there are issues crossing render boundaries with scoped services for maintaining state, and for static server-side where you want to use JS, you need a nuget package 'BlazorPageScript' to make JS work nicely with enhanced nav.

My point-- there was a lot of good work for Blazor in .NET 8, with a lot of loose ends that seemingly won't be in order until .NET 9. It has made me re-think a lot of choices. I will use Blazor for small in-house apps with a small user base, but I can't really unleash Blazor externally, even though I really, really want to.

AlbertoPa commented 3 months ago

@CodeFontana Blazor SSB does not need any different configuration compared to previous versions of .Net to use Entra. You can configure it following the Microsoft Identity Web documentation (it is a web app, the only difference is adding the Incremental consent handler, they have a sample for that too). The only case when things have become different is when using the Web App for hosted WASM/auto.

The documentation of the samples I linked is here: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/blazor-web-app-with-oidc?view=aspnetcore-8.0&pivots=without-bff-pattern by the way, so it has become part of the official guide.

Yarp and Aspire are used in one example because if you use the BFF approach, you will end up needing a reverse proxy, or you need to manually reroute API requests. As I said before, there is an example without that, which shows how to call an API.

Frankly, covering all the possible scenarios the new Blazor Web App offers in a template with "minimal" configuration is easier said than done. The samples are well documented and commented, so I think they do a better job than VS templates (which by the way almost never worked out of the box when selecting Microsoft Identity Platform).

CodeFontana commented 3 months ago

@AlbertoPa I agree, covering all possible scenarios could be endless, though I think it would be reasonable to ask for an "Organizational" template for Entra integration should be a minimum standard for the various render configurations. Blazor and Azure are indeed wonderful together.

However, I do disagree that the documentation and samples cover the scenario of Blazor server-side (Static + Interactive) with a simple example.

I recently put together this sample, which looks much different than how I would implement the same with .NET 6 or 7: https://github.com/CodeFontana/BlazorAzureAuthDemo

I do have that code running and published in Azure, where authentication and role-based authorization is at least functionally working. Perhaps you can review and let me know if any part is wrong, or if I grossly overlooked a sample that demonstrates this approach. Otherwise I think this might just be the way to do it for folks looking to do server-side only, with a mix of static and interactive components.

AlbertoPa commented 3 months ago

@CodeFontana that is close to what I did too. Here the differences:

1) You can simplify the initial call to Identity Web as:

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(
        builder.Configuration.GetSection("EntraId"));  // Change to your section name

2) Add a call to AddMicrosoftIdentityConsentHandler() to manage incremental consent. If missing, when Entra requires it, the app will throw:

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

3) Add

app.UseAuthentication();
app.UseAuthorization();

before

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

My approach was to generate the template with local accounts, see what they did and port it :-)

I hope this helps.

CodeFontana commented 3 months ago
  1. Add
app.UseAuthentication();
app.UseAuthorization();

before

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

@AlbertoPa, for this last part of your feedback, this seems to create a problem with the Antiforgery token.

On my forms, I'm receiving this error:

A valid antiforgery token was not provided with the request. Add an antiforgery token, or disable antiforgery validation for this endpoint.

I've also noticed in the default template for a Blazor Web App, selecting individual accounts, these middlewares are not present either.

Demo:

https://github.com/dotnet/aspnetcore/assets/41308769/a1624d24-0824-4f92-8354-6aceb98939eb

AlbertoPa commented 3 months ago

@CodeFontana have you added the antiforgery tag? See: https://learn.microsoft.com/en-us/aspnet/core/blazor/forms/?view=aspnetcore-8.0#antiforgery-support

This is automatic in Editform, but not on regular forms.

CodeFontana commented 3 months ago

@CodeFontana have you added the antiforgery tag? See: https://learn.microsoft.com/en-us/aspnet/core/blazor/forms/?view=aspnetcore-8.0#antiforgery-support

This is automatic in Editform, but not on regular forms.

@AlbertoPa, yes, the antiforgery tag is there.

Full demo available here: https://github.com/CodeFontana/BlazorAzureAuthDemo

With or without authentication, it's my understanding for a static-SSR page, the antiforgery tag would be required.

Otherwise, even when I commented out those middlewares in my video, I would expect the same result, but instead the Counter form worked as expected.

I should re-iterate the site works fine (locally and published to Azure), without the two middlewares-- app.UseAuthentication() and app.UseAuthorization(). Even the role-based auth is working for the Weather page.

It feels like .NET 8 supports the 'classic' ways of wiring up authentication for compatibility with existing .NET 6 and 7 apps, while also supporting a newer approach. I'll evidence that by comparing a Blazor Server template with authentication out of the box, to a Blazor Web app template with authentication out of the box.

The classic template indeed adds the two middlewares you mention, but newer template does not.

CodeFontana commented 3 months ago

@AlbertoPa, follow-up to the above.

If I organize the pipeline like this, I no longer receive the error regarding the antiforgery token:

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();    // <-- Middleware is below app.UseAuthentication() & app.UseAuthorization
app.MapGroup("/authentication").MapLoginAndLogout();
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();
app.Run();

But to be clear, the site functions with authentication and authorization, perfectly the same, with this pipeline:

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAntiforgery();
app.MapGroup("/authentication").MapLoginAndLogout();
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();
app.Run();

For reference, here is the configuration that provides the error surrounding the antiforgery token:

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAntiforgery();     // <-- Middleware is above app.UseAuthentication()
app.UseAuthentication();
app.UseAuthorization();
app.MapGroup("/authentication").MapLoginAndLogout();
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();
app.Run();