How do we use a bearer token with ASP.NET 5 using a username and password flow? For our scenario, we want to let a user register and login using AJAX calls without needing to use an external login.
To do this, we need to have an authorization server endpoint. In the previous versions of ASP.NET we would do the following and then login at the ourdomain.com/Token
URL.
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14)
};
In the current version of ASP.NET, though, the above doesn't work. We've been trying to figure out the new approach. aspnet/identity example on GitHub, for instance, configures Facebook, Google, and Twitter authentication but does not appear to configure a non-external OAuth authorization server endpoint, unless that's what AddDefaultTokenProviders()
does, in which case we're wondering what the URL to the provider would be.
We've learned from reading the source here that we can add "bearer authentication middleware" to the HTTP pipeline by calling IAppBuilder.UseOAuthBearerAuthentication
in our Startup
class. This is a good start though we're still not sure of how to set its token endpoint. This didn't work:
public void Configure(IApplicationBuilder app)
{
app.UseOAuthBearerAuthentication(options =>
{
options.MetadataAddress = "meta";
});
// if this isn't here, we just get a 404
app.Run(async context =>
{
await context.Response.WriteAsync("Hello World.");
});
}
On going to ourdomain.com/meta
we just receive our hello world page.
Further research showed that we can also use the IAppBuilder.UseOAuthAuthentication
extension method, and that it takes a OAuthAuthenticationOptions
parameter. That parameter has a TokenEndpoint
property. So though we're not sure what we're doing, we tried this, which of course didn't work.
public void Configure(IApplicationBuilder app)
{
app.UseOAuthAuthentication("What is this?", options =>
{
options.TokenEndpoint = "/token";
options.AuthorizationEndpoint = "/oauth";
options.ClientId = "What is this?";
options.ClientSecret = "What is this?";
options.SignInScheme = "What is this?";
options.AutomaticAuthentication = true;
});
// if this isn't here, we just get a 404
app.Run(async context =>
{
await context.Response.WriteAsync("Hello World.");
});
}
In other words, in going to ourdomain.com/token
, there is no error there is just again our hello world page.
Okay, let's recap the different OAuth2 middleware (and their respective IAppBuilder
extensions) that were offered by OWIN/Katana 3 and the ones that will be ported to ASP.NET Core:
app.UseOAuthBearerAuthentication
/OAuthBearerAuthenticationMiddleware
: its name was not terribly obvious, but it was (and still is, as it has been ported to ASP.NET Core) responsible for validating access tokens issued by the OAuth2 server middleware. It's basically the token counterpart of the cookies middleware and is used to protect your APIs. In ASP.NET Core, it has been enriched with optional OpenID Connect features (it is now able to automatically retrieve the signing certificate from the OpenID Connect server that issued the tokens).Note: starting with ASP.NET Core beta8, it is now namedapp.UseJwtBearerAuthentication
/JwtBearerAuthenticationMiddleware
.
app.UseOAuthAuthorizationServer
/OAuthAuthorizationServerMiddleware
: as the name suggests, OAuthAuthorizationServerMiddleware
was an OAuth2 authorization server middleware and was used to create and issue access tokens. This middleware won't be ported to ASP.NET Core: OAuth Authorization Service in ASP.NET Core.
app.UseOAuthBearerTokens
: this extension didn't really correspond to a middleware and was simply a wrapper around app.UseOAuthAuthorizationServer
and app.UseOAuthBearerAuthentication
. It was part of the ASP.NET Identity package and was just a convenient way to configure both the OAuth2 authorization server and the OAuth2 bearer middleware used to validate access tokens in a single call. It won't be ported to ASP.NET Core.
ASP.NET Core will offer a whole new middleware (and I'm proud to say I designed it):
app.UseOAuthAuthentication
/OAuthAuthenticationMiddleware
: this new middleware is a generic OAuth2 interactive client that behaves exactly like app.UseFacebookAuthentication
or app.UseGoogleAuthentication
but that supports virtually any standard OAuth2 provider, including yours. Google, Facebook and Microsoft providers have all been updated to inherit from this new base middleware.So, the middleware you're actually looking for is the OAuth2 authorization server middleware, aka OAuthAuthorizationServerMiddleware
.
Though it is considered as an essential component by a large part of the community, it won't be ported to ASP.NET Core.
Luckily, there's already a direct replacement: AspNet.Security.OpenIdConnect.Server (https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server)
This middleware is an advanced fork of the OAuth2 authorization server middleware that comes with Katana 3 but that targets OpenID Connect (which is itself based on OAuth2). It uses the same low-level approach that offers a fine-grained control (via various notifications) and allows you to use your own framework (Nancy, ASP.NET Core MVC) to serve your authorization pages like you could with the OAuth2 server middleware. Configuring it is easy:
ASP.NET Core 1.x:
// Add a new middleware validating access tokens issued by the server.
app.UseOAuthValidation();
// Add a new middleware issuing tokens.
app.UseOpenIdConnectServer(options =>
{
options.TokenEndpointPath = "/connect/token";
// Create your own `OpenIdConnectServerProvider` and override
// ValidateTokenRequest/HandleTokenRequest to support the resource
// owner password flow exactly like you did with the OAuth2 middleware.
options.Provider = new AuthorizationProvider();
});
ASP.NET Core 2.x:
// Add a new middleware validating access tokens issued by the server.
services.AddAuthentication()
.AddOAuthValidation()
// Add a new middleware issuing tokens.
.AddOpenIdConnectServer(options =>
{
options.TokenEndpointPath = "/connect/token";
// Create your own `OpenIdConnectServerProvider` and override
// ValidateTokenRequest/HandleTokenRequest to support the resource
// owner password flow exactly like you did with the OAuth2 middleware.
options.Provider = new AuthorizationProvider();
});
There's an OWIN/Katana 3 version, and an ASP.NET Core version that supports both .NET Desktop and .NET Core.
Don't hesitate to give the Postman sample a try to understand how it works. I'd recommend reading the associated blog post, that explains how you can implement the resource owner password flow.
Feel free to ping me if you still need help. Good luck!