<EDIT> A few days ago they changed it again….
Instead of .AddCookieAuthentication(….
It’s now just .AddCookie();
</EDIT>
Or rather Aspnetcore 2.0.0-preview2-006497 since they changed it again….
First, download the latest bits from .NET Core 2.0 and install it.
Open a developer command prompt and check version with
dotnet –version
It should say 2.0.0-preview2-006497 for you to be sure that my instructions will work 🙂
Create a new folder for your project and create a new mvc project with
dotnet new mvc
After it is done we will add the dependencies for authentication
dotnet add package Microsoft.AspNetCore.Authentication -v “2.0.0-preview2-final”
and
dotnet add package Microsoft.AspNetCore.Http -v “2.0.0-preview2-final”
Now we add, one by one the authentication providers we want. In Startup.cs in ConfigureServices:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
services.AddAuthentication(options => | |
{ | |
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; | |
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; | |
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; | |
}) | |
.AddCookieAuthentication(CookieAuthenticationDefaults.AuthenticationScheme, option => | |
{ | |
option.LoginPath = "/home/login"; | |
}) | |
.AddTwitterAuthentication(o => | |
{ | |
o.ConsumerKey = Configuration["Authentication:Twitter:ConsumerKey"]; | |
o.ConsumerSecret = Configuration["Authentication:Twitter:ConsumerSecret"]; | |
}); |
The biggest change in this version is perhaps that you only add
app.UseAuthentication();
To the pipeline in the Configure method.
So. Done with that part. Oh, forgot the usings. Add these to the top
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Security.Claims; | |
using Microsoft.AspNetCore.Authentication.Cookies; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Authentication; | |
using Microsoft.AspNetCore.Rewrite; | |
using Microsoft.AspNetCore.Mvc; |
A few more than necessary but I will get to them. Now the project should start with
dotnet run
But it still allows for anonymous access.
Add the attribute [Authorize] to your HomeController together with a matching using like so:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Authorization; | |
namespace [namespace].Controllers | |
{ | |
[Authorize] | |
public class HomeController : Controller | |
{ |
So. Again start the project and browse to http://localhost:5000/. You will be redirected to /home/login and get an error since that page does not exist (yet).
In the HomeController.cs add this code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[AllowAnonymous] | |
public async Task<IActionResult> Login(string username, string password) | |
{ | |
if (IsValidUser(username, password)) | |
{ | |
var claims = new List<Claim>(2); | |
claims.Add(new Claim(ClaimTypes.Name, username)); | |
claims.Add(new Claim(ClaimTypes.Role, "GroupThatUserIsIn", | |
ClaimValueTypes.String, "IHaveIssuedThis")); | |
await HttpContext.SignInAsync( | |
CookieAuthenticationDefaults.AuthenticationScheme, | |
new ClaimsPrincipal(new ClaimsIdentity(claims, | |
CookieAuthenticationDefaults.AuthenticationScheme))); | |
return RedirectToAction("Index"); | |
} | |
return View(); | |
} | |
private bool IsValidUser(string username, string password) | |
{ | |
return username == "foo" && password == "bar"; | |
} |
This is used when you manage all the users and passwords yourself (please don’t).
But seriously, sometimes you have an old back-end system that you are building a new front-web for and it has all the user info.
I created a super simplistic view for this action. Create a new file in the folder Views/Home called Login.cshtml with this content
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<form action="/home/login" method="post"> | |
<input name="username" /> | |
<input name="password" type="password"/> | |
<input type="submit" value="Go"/> | |
</form> | |
<a href='/login-twitter' \">I prefer Twitter</a> | |
Told you. Simplistic. Make sure these “usings” are in place in your HomeController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Authorization; | |
using System.Security.Claims; | |
using Microsoft.AspNetCore.Authentication.Cookies; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Authentication; |
Now, go back up to the project root folder and run the application again. This time the login page is displayed. If you try to login with your hard coded username and password you will be logged in and redirected to /. If you inspect the ClaimsPrincipal when debugging you will see that your claims are visible under the Identity-property.
Great. Let the user logout as well.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public async Task<IActionResult> Logout() | |
{ | |
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); | |
return RedirectToAction("Index"); | |
} |
Add a link somewhere that redirects the user to /home/logout. Done.
So. How about Twitter?
First, add a new app at apps.twitter.com . Click “Create new app” and fill out the form. You can set callback url to localhost:5000. Go to the Keys and Access Tokens-tab and copy them to your appSettings.json file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
}, | |
"Authentication": { | |
"Twitter": { | |
"ConsumerKey": "<Your key here>", | |
"ConsumerSecret": "<Your secret here>" | |
} | |
} | |
} |
Please note that if you intend to publish the code somewhere, don’t store these credentials here. Use secrets instead.
Remember the fancy looking login page? The Twitter-link was /login-twitter. Just because it is fun I will hard-wire this url into the processing pipeline.
So. Head over to Startup.cs and paste this code into the Configure-method.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
app.Map("/login-twitter", login => | |
{ | |
login.Run(async context => | |
{ | |
await context.ChallengeAsync("Twitter", new AuthenticationProperties() { | |
RedirectUri = "/" }); | |
return; | |
}); | |
}); |
Now you redirected to a Twitter page and depending if you are already logged into Twitter or not the page either asks you to logon or only to authorize your new app to connect to Twitter.
Tip: If you want to dress the current user with more claims than Twitter sent, you can always add them. Like your internal user id of that Twitter-identified user.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public async Task<IActionResult> Index() | |
{ | |
var principal = User.Identity as ClaimsIdentity; | |
var idClaim = principal.Claims.Where(i => i.Type == "https://marcusclasson.com/claims/id") | |
.SingleOrDefault(); | |
if(idClaim == null) | |
{ | |
principal.AddClaim(new Claim("https://marcusclasson.com/claims/id", "MyCustomId")); | |
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); | |
await HttpContext.SignInAsync(User); | |
} | |
return View(); | |
} |
Done.