Web API 2 OWIN Bearer Token purpose of cookie?

19,808

Solution 1

In the SPA template there are actually two separate authentication mechanisms enabled- cookie authentication and token authentication. This enables authentication of both MVC and Web API controller actions, but requires some additional setup.

If you look in the WebApiConfig.Register method you'll see this line of code:

    config.SuppressDefaultHostAuthentication();

That tells Web API to ignore cookie authentication, which avoids a host of problems which are explained in the link you posted in your question:

"...the SPA template enables application cookie middleware as active mode as well in order to enable other scenarios like MVC authentication. So Web API will still be authenticated if the request has session cookie but without a bearer token. That’s probably not what you want as you would be venerable to CSRF attacks for your APIs. Another negative impact is that if request is unauthorized, both middleware components will apply challenges to it. The cookie middleware will alter the 401 response to a 302 to redirect to the login page. That is also not what you want in a Web API request."

So now with the call to config.SuppressDefaultHostAuthentication() Web API calls that require authorization will ignore the cookie that is automatically sent along with the request and look for an Authorization header that begins with "Bearer". MVC controllers will continue to use cookie authentication and are ignorant of the token authentication mechanism as it's not a very good fit for web page authentication to begin with.

Solution 2

The existence of the cookie also left me puzzled, since it clearly is not necessary in a bearer token authentication scenario... In this post the author dissects the individual accounts template, and has the following to say about the cookie:

The method also sets an application cookie. I don’t see a good reason for that.

My guess is that the authors of the template wanted to show examples of different kinds of authentication logic, and in this particular case they wanted to show how the authentication information could be stored in both the bearer token authentication JSON payload, as well as in a standard authentication cookie.

The fact that the JSON authentication payload is set to also include an additional (unnecessary) unencrypted property (the user id), in addition to the encrypted ticket, seems to support this theory:

var properties = CreateProperties(user.UserName);
var ticket = new AuthenticationTicket(oAuthIdentity, properties);

It seems that the authors of the template wanted to provide some useful examples, rather than the bare minimum needed to achieve bearer token authentication. This is also mentioned in the linked post above.

Share:
19,808
gavin
Author by

gavin

Updated on June 06, 2022

Comments

  • gavin
    gavin almost 2 years

    I am trying to understand the new OWIN Bearer Token authentication process in the Single Page App template in MVC 5. Please correct me if I'm wrong, for the OAuth password client authentication flow, Bearer Token authentication works by checking the http authorization request header for the Bearer access token code to see if a request is authenticated, it doesn't rely on cookie to check if a particular request is authenticated.

    According to this post:

    OWIN Bearer Token Authentication with Web API Sample

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        using (IdentityManager identityManager = _identityManagerFactory.CreateStoreManager())
        {
            if (!await identityManager.Passwords.CheckPasswordAsync(context.UserName, context.Password))
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }
    
            string userId = await identityManager.Logins.GetUserIdForLocalLoginAsync(context.UserName);
            IEnumerable<Claim> claims = await GetClaimsAsync(identityManager, userId);
            ClaimsIdentity oAuthIdentity = CreateIdentity(identityManager, claims,
                context.Options.AuthenticationType);
            ClaimsIdentity cookiesIdentity = CreateIdentity(identityManager, claims,
                _cookieOptions.AuthenticationType);
            AuthenticationProperties properties = await CreatePropertiesAsync(identityManager, userId);
            AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
            context.Validated(ticket);
            context.Request.Context.Authentication.SignIn(cookiesIdentity);
        }
    }
    

    The GrantReourceOwnerCredentials function not only compose the ticket with this line: context.Validated(ticket); but it also compose a cookie identity and set it to the cookie with this line: context.Request.Context.Authentication.SignIn(cookiesIdentity);

    So my questions are, what is the exact purpose of the cookie in this function? Shouldn't the AuthenticationTicket be good enough for authentication purpose?

  • EBarr
    EBarr about 10 years
    That author (stackoverflow.com/users/672453/leastprivilege) also happens to know just a smidgen about the topic. He's the author of Thinktecture.IdentityServer and this MS paper on Claims-Based Identity (msdn.microsoft.com/en-us/library/ff423674.aspx)
  • ThisGuy
    ThisGuy over 9 years
    To add to this, there is an field in CookieAuthenticationOptions called CookieHttpOnly. If you set this to true, the browser won't send the cookie with the JavaScript generated API request at all, saving you some bandwidth and potential confusion when debugging.
  • mmarques
    mmarques over 9 years
    What you mean by "MVC controllers will continue to use cookie authentication..." ? With this line of code config.SuppressDefaultHostAuthentication() i'm able to use cookies authentication in MVC apps and Bearer Token authentication in Mobile Apps ?
  • joelmdev
    joelmdev over 9 years
    @mmarques I think you answered your own question. MVC will use cookie authentication and Web API will use bearer token authentication as configured above.
  • GFoley83
    GFoley83 over 9 years
    @ThisGuy The default is true anyway, though kudos for mentioning it.
  • Pepito Fernandez
    Pepito Fernandez over 9 years
    @joelmdev, why do you think that token authentication mechanism it is not a very good fit for web?
  • joelmdev
    joelmdev over 9 years
    @Tony because you have to manually add the bearer token header on every request. A plan old anchor tag to take you to an authenticated page wouldn't work. Cookies for a domain are sent along with the request automatically.