I'm working with ASP.NET Core application. I'm trying to implement Token Based Authentication but can not figure out how to use new Security System for my case. I went through examples but they didn't help me much, they are using either cookie authentication or external authentication (GitHub, Microsoft, Twitter).
What my scenario is: angularjs application should request /token
url passing username and password. WebApi should authorize user and return access_token
which will be used by angularjs app in following requests.
I've found great article about implementing exactly what I need in current version of ASP.NET - Token Based Authentication using ASP.NET Web API 2, Owin, and Identity. But it is not obvious for me how to do the same thing in ASP.NET Core.
My question is: how to configure ASP.NET Core WebApi application to work with token based authentication?
Have a look at OpenIddict - it's a new project (at the time of writing) that makes it easy to configure the creation of JWT tokens and refresh tokens in ASP.NET 5. The validation of the tokens is handled by other software.
Assuming you use
Identity
withEntity Framework
, the last line is what you'd add to yourConfigureServices
method:In
Configure
, you set up OpenIddict to serve JWT tokens:You also configure the validation of tokens in
Configure
:There are one or two other minor things, such as your DbContext needs to derive from OpenIddictContext.
You can see a full length explanation on this blog post: http://capesean.co.za/blog/asp-net-5-jwt-tokens/
A functioning demo is available at: https://github.com/capesean/openiddict-test
Updated for .Net Core 2:
Previous versions of this answer used RSA; it's really not necessary if your same code that is generating the tokens is also verifying the tokens. However, if you're distributing the responsibility, you probably still want to do this using an instance of
Microsoft.IdentityModel.Tokens.RsaSecurityKey
.Create a few constants that we'll be using later; here's what I did:
Add this to your Startup.cs's
ConfigureServices
. We'll use dependency injection later to access these settings. I'm assuming that yourauthenticationConfiguration
is aConfigurationSection
orConfiguration
object such that you can have a different config for debug and production. Make sure you store your key securely! It can be any string.I've seen other answers change other settings, such as
ClockSkew
; the defaults are set such that it should work for distributed environments whose clocks aren't exactly in sync. These are the only settings you need to change.Set up Authentication. You should have this line before any middleware that requires your
User
info, such asapp.UseMvc()
.Note that this will not cause your token to be emitted with the
SignInManager
or anything else. You will need to provide your own mechanism for outputting your JWT - see below.You may want to specify an
AuthorizationPolicy
. This will allow you to specify controllers and actions that only allow Bearer tokens as authentication using[Authorize("Bearer")]
.Here comes the tricky part: building the token.
Then, in your controller where you want your token, something like the following:
Here, I'm assuming you already have a principal. If you are using Identity, you can use
IUserClaimsPrincipalFactory<>
to transform yourUser
into aClaimsPrincipal
.To test it: Get a token, put it into the form at jwt.io. The instructions I provided above also allow you to use the secret from your config to validate the signature!
If you were rendering this in a partial view on your HTML page in combination with the bearer-only authentication in .Net 4.5, you can now use a
ViewComponent
to do the same. It's mostly the same as the Controller Action code above.You can have a look at the OpenId connect samples which illustrate how to deal with different authentication mechanisms, including JWT Tokens:
https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Samples
If you look at the Cordova Backend project, the configuration for the API is like so:
The logic in /Providers/AuthorizationProvider.cs and the RessourceController of that project are also worth having a look at ;).
Alternatively you can also use the following code to validate tokens (there is also a snippet to make it work with signalR):
For issuing token you can use the openId Connect server packages like so:
EDIT: I have implemented a single page application with token based authentication implementation using the Aurelia front end framework and ASP.NET core. There is also a signal R persistent connection. However I have not done any DB implementation. Code can be seen here: https://github.com/alexandre-spieser/AureliaAspNetCoreAuth
Hope this helps,
Best,
Alex
Working from Matt Dekrey's fabulous answer, I've created a fully working example of token-based authentication, working against ASP.NET Core (1.0.1). You can find the full code in this repository on GitHub (alternative branches for 1.0.0-rc1, beta8, beta7), but in brief, the important steps are:
Generate a key for your application
In my example, I generate a random key each time the app starts, you'll need to generate one and store it somewhere and provide it to your application. See this file for how I'm generating a random key and how you might import it from a .json file. As suggested in the comments by @kspearrin, the Data Protection API seems like an ideal candidate for managing the keys "correctly", but I've not worked out if that's possible yet. Please submit a pull request if you work it out!
Startup.cs - ConfigureServices
Here, we need to load a private key for our tokens to be signed with, which we will also use to verify tokens as they are presented. We're storing the key in a class-level variable
key
which we'll re-use in the Configure method below. TokenAuthOptions is a simple class which holds the signing identity, audience and issuer that we'll need in the TokenController to create our keys.We've also set up an authorization policy to allow us to use
[Authorize("Bearer")]
on the endpoints and classes we wish to protect.Startup.cs - Configure
Here, we need to configure the JwtBearerAuthentication:
TokenController
In the token controller, you need to have a method to generate signed keys using the key that was loaded in Startup.cs. We've registered a TokenAuthOptions instance in Startup, so we need to inject that in the constructor for TokenController:
Then you'll need to generate the token in your handler for the login endpoint, in my example I'm taking a username and password and validating those using an if statement, but the key thing you need to do is create or load a claims-based identity and generate the token for that:
And that should be it. Just add
[Authorize("Bearer")]
to any method or class you want to protect, and you should get an error if you attempt to access it without a token present. If you want to return a 401 instead of a 500 error, you'll need to register a custom exception handler as I have in my example here.