Retrieving bearer tokens from alternative locations in Katana/OWIN

The Katana bearer token authentication middleware tries to retrieve tokens from the HTTP Authorization header with a scheme of Bearer by default.

You can customize this behavior by providing a so called Provider (this is a common pattern in Katana). The following provider retrieves the access token from a query string:

public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider

{

    readonly string _name;

 

    public QueryStringOAuthBearerProvider(string name)

    {

        _name = name;

    }

 

    public override Task RequestToken(OAuthRequestTokenContext context)

    {

        var value = context.Request.Query.Get(_name);

 

        if (!string.IsNullOrEmpty(value))

        {

            context.Token = value;

        }

 

        return Task.FromResult<object>(null);

    }

}

 

…or from an alternative header:

public class HeaderOAuthBearerProvider : OAuthBearerAuthenticationProvider

{

    readonly string _name;

 

    public HeaderOAuthBearerProvider(string name)

    {

        _name = name;

    }

 

    public override Task RequestToken(OAuthRequestTokenContext context)

    {

        var value = context.Request.Headers.Get(_name);

 

        if (!string.IsNullOrEmpty(value))

        {

            context.Token = value;

        }

 

        return Task.FromResult<object>(null);

    }

}

You can the pass such a provider to the middleware, e.g.:

var options = new JwtBearerAuthenticationOptions

{

    AllowedAudiences = new[] { audience },

    IssuerSecurityTokenProviders = new[]

        {

            new SymmetricKeyIssuerSecurityTokenProvider(

                issuer,

                signingKey)

        },

    Provider = new QueryStringOAuthBearerProvider(“access_token”)

};

 

..or by using the helpers from Thinktecture.IdentityModel.Owin:

app.UseJsonWebToken(

    issuer:     Constants.AS.IssuerName,

    audience:   Constants.Audience,

    signingKey: Constants.AS.SigningKey,

    location:   TokenLocation.QueryString(“access_token”));

 

This entry was posted in IdentityModel, Katana, OWIN, WebAPI. Bookmark the permalink.

16 Responses to Retrieving bearer tokens from alternative locations in Katana/OWIN

  1. Pingback: Web API 2 Excel File Export With OAuth2 Implicit Flow | Software Engineering

  2. Have you had any luck integrating this with the Webapi2 Identity stuff? I seem to be unable to mix

    // Enable the application to use bearer tokens to authenticate users
    var opts = new OAuthBearerAuthenticationOptions() {
    Provider = new QueryStringOAuthBearerProvider(“access_token”),
    };
    app.UseOAuthBearerAuthentication(opts);
    app.UseOAuthBearerTokens(OAuthOptions);

    the two options together. You get an “exceptionMessage”: “Sequence contains more than one element”,

  3. mahmoud says:

    have the same problem with updated web api 2:
    Sequence contains more than one element

    • mahmoud says:

      details of error :
      Message : An error has occurred.
      ExceptionMessage : Sequence contains more than one element
      ExceptionType : System.InvalidOperationException
      StackTrace : at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
      at Microsoft.Owin.Security.AuthenticationManager.d__8.MoveNext()
      — End of stack trace from previous location where exception was thrown —
      at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
      at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
      at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
      at System.Web.Http.HostAuthenticationFilter.d__0.MoveNext()
      — End of stack trace from previous location where exception was thrown —
      at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
      at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
      at System.Web.Http.Controllers.AuthenticationFilterResult.d__0.MoveNext()
      — End of stack trace from previous location where exception was thrown —
      at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
      at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
      at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
      at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()

  4. azure says:

    What if I need to retrieve the token from different locations(header/querystring/cookie) based on some condition? I used the default provider(http header) and tried to set the Authorization Header in a DelegatingHandler but that doesn’t have any effect. When and how does OWIN reconstruct the identity from the token?

  5. bingzer says:

    Thanks for this solution. Is there any security precautions when we’re sending Access Token in the query string? Should I encrypt the token or will it be overkill?

  6. jimmy says:

    I can’t find any information about JWT tokens in my project, it is setup to use bearer tokens using Oauth.

    Can you please help me? I need to use query string parameter to send the token but I’m confused where to put above code ,

  7. BWR says:

    Is there a problem with using this idea to pull the token from a cookie, and override somewhere to write the token as a cookie after GrantResourceOwnerCredentials. The reason would be to use the same code/settings for all authentication for both a website and an api, instead of setting up both cookie auth and oath tokens.

  8. You got the concepts wrong a bit. In OpenID Connect you get an identity token back (that’s not the token you would use to access APIs). Also this token is not stored in a cookie. The token contains claims (like username, email address etc). These claims are re-packaged as a “normal” authentication cookie.

    Cookies are a kind of bearer token. But they are a bit different in semantics to OAuth access tokens. Hence the link to my post.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s