Aspnetcore.docs: How to add Authentication to the SPA

Created on 16 Jul 2018  Â·  11Comments  Â·  Source: dotnet/AspNetCore.Docs

Any documentation on how to Add Authentication to the SPA template on ASP.NET Core 2.1? I have been unable to find any.
To clarify, I am not asking how to add ("implicit" flow) authentication to the react client app, but I want the backend (dotnet) to handle authentication via an OIDC Identity Provider, using the "hybrid" flow. I am adding the following to the services pipeline:

services.AddAuthentication(o =>
    {
        o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>;
    {
        o.SlidingExpiration = bool.Parse(Configuration["SessionCookieSlidingEnabled"]);
        o.ExpireTimeSpan = TimeSpan.FromMinutes(int.Parse(Configuration["SessionCookieLifeTimeInMinutes"]));
        o.Cookie = new CookieBuilder { HttpOnly = true };
    })
    .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, o =>
    {
        o.Authority = Configuration["Authority"];
        o.ClientId = Configuration["OpenIdConnectOptions:ClientId"];
        o.ClientSecret = Configuration["OpenIdConnectOptions:ClientSecret"];
        o.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        o.GetClaimsFromUserInfoEndpoint = Convert.ToBoolean(Configuration["OpenIdConnectOptions:GetClaimsFromUserInfoEndpoint"]);
        o.RequireHttpsMetadata = Convert.ToBoolean(Configuration["OpenIdConnectOptions:RequireHttpsMetadata"]);
        o.ResponseType = Configuration["OpenIdConnectOptions:ResponseType"];
        o.SaveTokens = Convert.ToBoolean(Configuration["OpenIdConnectOptions:SaveTokens"]);
        o.UseTokenLifetime = false;
    }

And then the corresponding app.UseAuthentication(); to the configure method. Additionally, I've tried to configure a global filter on the MVC service, like so:

services.AddMvc(options =>
{
        var policy = new AuthorizationPolicyBuilder(OpenIdConnectDefaults.AuthenticationScheme)
                                 .RequireAuthenticatedUser()
                                 .Build();
        options.Filters.Add(new AuthorizeFilter(policy));
})

In the past, I would append the [Authorize] filter to the home controller to trigger the flow, but now the framework uses the SPA middleware to load from the ClientApp folder as the entry point for my application, so how do I trigger the authorization process? Again, I don't want to use the OIDC implicit flow client-side, not secure enough for our customers.


Document Details

⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

P2 Source - Docs.ms doc-enhancement

Most helpful comment

I do have a working token server implemented with IdentityServer4, with apps on other stacks using it. Stack overflow helped me find the answer that I was looking for. Basically instead of using the [Authorize] attribute in the controller actions you just add a middleware to the chain before Spa and Mvc. Like so:

app.Use(async (context, next) =>
{
    if (!context.User.Identity.IsAuthenticated)
    {
        await context.ChallengeAsync();
    }
    else
    {
        await next();
    }
});

Hope that helps.

All 11 comments

@SteveSandersonMS do you want to schedule a doc on this?

Hello, Rick. On the meantime, could you please point me into the right direction to get this to work? I think that I'm on the right track, but missing a piece. I still want to use ASP.NET Core for the back-end, but this is kind of a show-stopper. I'd greatly appreciate it.

@SteveSandersonMS @Tratcher can you suggest an approach?

The only guidance we provide in our docs is a link to IdentityServer4 https://identityserver4.readthedocs.io/

In general OpenIdConnect and Cookies are not appropriate for SPA scenarios, you need a token server (IdentityServer4), JwtBearer, and Web Api auth.

Steve provided some high-level authentication guidance in an older issue. See https://github.com/aspnet/Docs/issues/6101#issuecomment-389878502.

I do have a working token server implemented with IdentityServer4, with apps on other stacks using it. Stack overflow helped me find the answer that I was looking for. Basically instead of using the [Authorize] attribute in the controller actions you just add a middleware to the chain before Spa and Mvc. Like so:

app.Use(async (context, next) =>
{
    if (!context.User.Identity.IsAuthenticated)
    {
        await context.ChallengeAsync();
    }
    else
    {
        await next();
    }
});

Hope that helps.

@regul4rj0hn that was such a good snippet to stumble on. Thank you for sharing.

@regul4rj0hn Which one is the file where you define configuration parameters such as ClientId and ClientSecret?

Up to you to decide that. We usually do that on appsettings.json, or if it is sensitive information on a secrets.json that we encrypt at rest. You can load those configuration files on Startup.cs, and then use them with Configuration["SomeSetting"].

Thanks @regul4rj0hn

Moved to #16209

Was this page helpful?
0 / 5 - 0 ratings