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”));
Pingback: Web API 2 Excel File Export With OAuth2 Implicit Flow | Software Engineering
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”,
No I have never tried that – but UseOAuthBearerTokens is just an extension method – maybe have a look at the source code to find out what it is doing.
I also fixed a bug recently – maybe that affected you? Try updating the nuget.
I found the problem. Instead of using “app.UseOAuthBearerTokens(OAuthOptions)” apply “app.UseOAuthAuthorizationServer(OAuthOptions)”.
have the same problem with updated web api 2:
Sequence contains more than one element
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()
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?
Not sure I understand your question – the request gets inspected by the MW – once a token is found (on whatever location) the identity is created.
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?
In general you should avoid it and use the authorization header instead.
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 ,
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.
https://leastprivilege.com/2015/04/01/implicit-vs-explicit-authentication-in-browser-based-applications/
I don’t think I was very clear in my mind, or in my question. I was thinking more along the lines of implementing cookie authentication for a website using oath bearer tokens. Please correct me if I’m wrong, but I’m looking at the MVC Authentication sample from https://github.com/IdentityServer/IdentityServer3.Samples and that seems to be what happens. Username/password are sent to the identity server, gets a token back (same token as would be used for accessing api), but it’s stored in a cookie. Then the cookie is sent implicitly and decoded into claims for use in the app through the built in cookie authentication mechanism?
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.