Joao Sousa
Joao Sousa

Reputation: 501

ASP.Net MVC 6 + WebAPI Auth - Redirect MVC to logon but 401 if WebAPI

I have a AngularJS + MVC + WebAPI where I'm trying to: - Use standard (individual accounts) for MVC authentication; - Use those same users and password for WebAPI based authentication.

Problem, from AngularJS everything works fine, the cookie exchange happens, and Web API returns the value, but when I'm trying to access the WebAPI from Postman, I get a redirect to logon page instead of a 401 Unauthorized.

What is the easiest way to achieve this? Do I have to subclass Authorize and implement the logic manually?

Thank you

Upvotes: 4

Views: 3180

Answers (3)

vzayko
vzayko

Reputation: 335

In RC1-Final (VS2015.1) I've done with the following: in Identity configuration set AutomaticChallenge to false and ApplicationCookieAuthenticationScheme = "ApplicationCookie":

services.AddIdentity<AppUser>(options =>
        {
            // cut

            options.Cookies.ApplicationCookie.AutomaticAuthenticate = true;
            options.Cookies.ApplicationCookie.AutomaticChallenge = false;
            options.Cookies.ApplicationCookieAuthenticationScheme = "ApplicationCookie";
        })
            .AddUserStore<AppUserStore<AppUser, AppDbContext>>()
            .AddDefaultTokenProviders();

Then controllers, that I want to redirect to login, I add ActiveAuthenticationSchemes = "ApplicationCookie"

[Authorize(ActiveAuthenticationSchemes = "ApplicationCookie")]
    public async Task<IActionResult> Logout()
    {
        // cut
    }

but other controllers (WebAPI in my case) I marked with parameter less Authorize attribute.

From AuthenticationOptions.cs inline help for AutomaticChallenge:

If false the authentication middleware will only alter responses when explicitly indicated by the AuthenticationScheme.

Upvotes: 2

Joao Sousa
Joao Sousa

Reputation: 501

For the ASP.Net 5 latest beta8, the answer is to add the following to ConfigureServices on Startup.cs:

         services.Configure<IdentityOptions>(config =>
        {
            options.Cookies.ApplicationCookie.LoginPath = "/Account/Login";
            options.Cookies.ApplicationCookie.CookieHttpOnly = true;
            options.Cookies.ApplicationCookie.CookieSecure = CookieSecureOption.SameAsRequest;
            options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
            {
                OnRedirect = ctx =>
                {
                    if (ctx.Request.Path.StartsWithSegments("/api") &&
                    ctx.Response.StatusCode == 200)
                    {
                        ctx.Response.StatusCode = 401;
                        return Task.FromResult<object>(null);
                    }
                    else
                    {
                        ctx.Response.Redirect(ctx.RedirectUri);
                        return Task.FromResult<object>(null);
                    }
                }
            };
        });

Upvotes: 7

Sam FarajpourGhamari
Sam FarajpourGhamari

Reputation: 14741

You could simply apply a custom action for Redirect event. On App_Start/Startup.Auth.cs file find app.UseCookieAuthentication() method and alter like this:

public void ConfigureAuth(IAppBuilder app)
{
    // some omitted configurations 

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        // some omitted configurations 

        Provider = new CookieAuthenticationProvider
        {
            // some omitted configurations 

            OnApplyRedirect = context => 
            {
                // assuming your API's url starts with /api
                if(!context.Request.Path.StartsWithSegments(new PathString("/api")))
                    context.Response.Redirect(context.RedirectUri);
            }
        }
    });
}

Upvotes: 3

Related Questions