Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Blazor .Net 8 Microsoft.Identity.Web client for Azure clients #51374

Closed
1 task done
damienbod opened this issue Oct 14, 2023 · 12 comments
Closed
1 task done

Support Blazor .Net 8 Microsoft.Identity.Web client for Azure clients #51374

damienbod opened this issue Oct 14, 2023 · 12 comments
Assignees
Labels
area-blazor Includes: Blazor, Razor Components Docs This issue tracks updating documentation

Comments

@damienbod
Copy link
Contributor

damienbod commented Oct 14, 2023

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

I would like to implement a secure client Microsoft.Identity.Web (no ASP.NET Core Identity) using the new Blazor features.

In RC2, this does not work due to Blazor 8 State Management, required duplicate components and persisting the user state which is stored in a cookie on the client.

Would it be possible to support this for the different rendering modes

Describe the solution you'd like

The application authenticates against Microsoft Entra ID using the Web flow and requires a secret or a certificate. (Single Azure App registration)

OIDC Code flow with PKCE is used, not implicit flow which is the default using Microsoft.Identity.Web

The authentication session is stored in a HTTP only secure cookie.

All Blazor components in the different rendering modes have access to the authentication claims and the user session.

The Anti-forgery cookie is used to access APIs or any post, delete, put requests to the same site server. This can be added to the request using a html component in the form or a HTTP request header using a HttpClient.

No unsecure inline scripts are used in the client.

ASP.NET Core Identity is not used.

UI components can be displayed checking the authorized state

Logout form request uses the Anti-forgery cookie

Additional context

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Oct 14, 2023
@mkArtakMSFT mkArtakMSFT added the Docs This issue tracks updating documentation label Oct 16, 2023
@mkArtakMSFT mkArtakMSFT added this to the .NET 8: Documentation milestone Oct 16, 2023
@joseph-hungerman
Copy link

I am really struggling with this, as well. There is no good documentation to implement Azure AD in the new template. I have tried using the structure for Blazor Server in NET7 and pulling specific pieces from the NET8 Individual Account solution. I don't want individual accounts, however. I just want to protect the application using single org Entra ID. The closest I have gotten is getting the calls to operate, but now I get a persistent Correlation Error, cookie not found. The cookies exist in the browser set to Strict, even though I set up the project to put Correlation and Nonce cookies to SameSite None with Secure to Always. If the project is running localy, and I change a piece of code, hot reload is triggered, and the app reloads properly with executing the signin. If I shut down and restart, I get the correlation error again. I am posting this here since it seems to be related, but I thought about opening a new issue.

Code (HIDDEN for security):

DI Extension:

`private static void AddAuthentication(IServiceCollection services, ConfigurationManager configuration)
{
services.AddCascadingAuthenticationState();

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(opt =>
    {
        configuration.Bind("AzureAd", opt);
        opt.NonceCookie.SameSite = SameSiteMode.None;
        opt.NonceCookie.SecurePolicy = CookieSecurePolicy.Always;
        opt.CorrelationCookie.SameSite = SameSiteMode.None;
        opt.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always;
    })
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDownstreamApi("HIDDEN", opt =>
    {
        opt.BaseUrl = configuration.IsProduction()
            ? "https://HIDDEN"
            : "https://HIDDEN";
        opt.Scopes = new[] { configuration.GetSection("HIDDEN").Value }!;
    }).AddInMemoryTokenCaches();

}`

Program.cs snippets:
`builder.Services.AddControllersWithViews(opt =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();

    opt.Filters.Add(new AuthorizeFilter(policy));
})
.AddMicrosoftIdentityUI();

builder.Services.AddCascadingAuthenticationState();

builder.Services.AddMicrosoftIdentityConsentHandler();`

app.UseCookiePolicy(new()
{
MinimumSameSitePolicy = SameSiteMode.None,
Secure = CookieSecurePolicy.Always
});

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseAntiforgery();

app.UseAuthorization();

app.MapRazorComponents()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(SeeEye.App.Client._Imports).Assembly);

app.MapControllers();

app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");

app.Run();

@JeremyLikness
Copy link
Member

We just added the sample for OIDC with Microsoft Entra (Azure AD) ... does this get you what you are looking for/need?

@joseph-hungerman
Copy link

joseph-hungerman commented Dec 19, 2023 via email

@joseph-hungerman
Copy link

joseph-hungerman commented Dec 19, 2023 via email

@joseph-hungerman
Copy link

OK, so I figured out the cookie issue. The problem was in my effort to make my app secure. I set the Referrer-Policy to "strict-origin-when-cross-origin" which apparently messed everything up. I will re-test your new OIDC example with this change in mind.

@joseph-hungerman
Copy link

We just added the sample for OIDC with Microsoft Entra (Azure AD) ... does this get you what you are looking for/need?

I tested the new sample implementation, and it worked well. I think it is a big step forward, but the documentation still needs to be updated. A couple things I noticed:

  1. The sample wraps the router in a CascadingAuthenticationState component, which I thought was out of fashion with .NET8. Should AddCascadingAuthenticationState be added to the server and client projects?
  2. The documentation warns against adding an HTTP context accessor in the Program file, which the template has.

@damienbod
Copy link
Contributor Author

damienbod commented Jan 4, 2024

Hi @JeremyLikness @halter73

Thanks for the example. I tried this and it does not work for me. After the authentication is complete, the client AuthenticationStateProvider gets updated with no state (after a small delay) and the authenticated session is reset.

Greetings Damien

@halter73
Copy link
Member

halter73 commented Jan 8, 2024

Thanks for the example. I tried this and it does not work for me. After the authentication is complete, the client AuthenticationStateProvider gets updated with no state (after a small delay) and the authenticated session is reset.

Is this something you see while running the BlazorWebOidc sample without modification? Do you have a stack trace for whatever is constructing the client's PersistentAuthenticationStateProvider constructor the second time? This shouldn't hapen since it's registered as a singleton.

@damienbod
Copy link
Contributor Author

damienbod commented Jan 9, 2024

Hi @halter73 Thanks for your reply. Almost. I just switched out the OpenID Connect client to use a local STS and removed the aspire stuff.

I create the trace later.

@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 6, 2024
@wtgodbe wtgodbe removed the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 6, 2024
@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 6, 2024
@wtgodbe wtgodbe removed the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 13, 2024
@dotnet dotnet deleted a comment from dotnet-policy-service bot Feb 13, 2024
@dotnet dotnet deleted a comment from dotnet-policy-service bot Feb 13, 2024
@damienbod
Copy link
Contributor Author

@halter73 Got around to looking at this. I did not disable the Microsoft claims mappings. When the claims renaming is disabled, everything works. I will create a PR to update the docs

@danroth27
Copy link
Member

@halter73 @mikekistler Is this basically a duplicate of #51202?

@halter73
Copy link
Member

Yes. I'll close it. @damienbod let us know if you disagree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components Docs This issue tracks updating documentation
Projects
None yet
Development

No branches or pull requests

7 participants