Using Auth0 to control Authentication in .Net Core 2.2
Auth0 provides universal authentication and authorization for your application, you can see more about them here.
I've used Auth0 a few times and always found it a really good fit for authentication. There can be a lot of coding to make your app connect to all the different providers but Auth0 takes a good chunk of the work out of it.
I wanted to get into using Auth0 with a new .net core 2.2 web app I have been working on.
This post is part of a series where I will add Auth0 to a .net core 2.2 application. Wire it into my user management and look at how to customise Auth0 interface and the options they provide. So lets get going.
Auth0 Setup
I am assuming you are already up and running on Auth0 and have setup an account.
Once your in and running on Auth0 you need to create an "Application" This will give you the details and the settings you need to connect and authenticate.
More docs from Auth0 are here
In the Application Settings you need to set the Callback URL : for me it's https://localhost:44309/callback
Adding to .Net Core 2.2
Source Code can be found here
To make Auth0 with with .net Core we need the packages for cookies and option Id Connect from nuget.
Install-Package Microsoft.AspNetCore.Authentication.Cookies
Install-Package Microsoft.AspNetCore.Authentication.OpenIdConnect
We start in the Startup.cs file
Our configureservices will look something like this
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// Add authentication services
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect("Auth0", options =>
{
// Set the authority to your Auth0 domain
options.Authority = $"AUTH0 - Domain";
// Configure the Auth0 Client ID and Client Secret
options.ClientId = "AUTH0 - ClientID";
options.ClientSecret = "AUTH0 - Client Secret";
// Set response type to code
options.ResponseType = "code";
// Configure the scope
options.Scope.Clear();
options.Scope.Add("openid");
// Set the callback path, so Auth0 will call back to http://localhost:3000/callback
// Also ensure that you have added the URL as an Allowed Callback URL in your Auth0 dashboard
options.CallbackPath = new PathString("/callback");
// Configure the Claims Issuer to be Auth0
options.ClaimsIssuer = "Auth0";
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.SetParameter("audience", "AUTH0 - API ID");
return Task.FromResult(0);
}
};
options.Events = new OpenIdConnectEvents
{
// handle the logout redirection
OnRedirectToIdentityProviderForSignOut = (context) =>
{
var logoutUri =
$"https://AUTH0-DOMAIN/v2/logout?client_id=AUTH0CLIENTID";
var postLogoutUri = context.Properties.RedirectUri;
if (!string.IsNullOrEmpty(postLogoutUri))
{
if (postLogoutUri.StartsWith("/"))
{
// transform to absolute
var request = context.Request;
postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
}
logoutUri += $"&returnTo={Uri.EscapeDataString(postLogoutUri)}";
}
context.Response.Redirect(logoutUri);
context.HandleResponse();
return Task.CompletedTask;
}
};
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
Yep that's a whole lot of code so lets look at what it is doing.
The code in here for Auth0
// Add authentication services
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect("Auth0", options =>
{
// Set the authority to your Auth0 domain
options.Authority = $"AUTH0 - Domain";
// Configure the Auth0 Client ID and Client Secret
options.ClientId = "AUTH0 - ClientID";
options.ClientSecret = "AUTH0 - Client Secret";
// Set response type to code
options.ResponseType = "code";
// Configure the scope
options.Scope.Clear();
options.Scope.Add("openid");
// Set the callback path, so Auth0 will call back to http://localhost:3000/callback
// Also ensure that you have added the URL as an Allowed Callback URL in your Auth0 dashboard
options.CallbackPath = new PathString("/callback");
// Configure the Claims Issuer to be Auth0
options.ClaimsIssuer = "Auth0";
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.SetParameter("audience", "AUTH0 - API ID");
return Task.FromResult(0);
}
};
options.Events = new OpenIdConnectEvents
{
// handle the logout redirection
OnRedirectToIdentityProviderForSignOut = (context) =>
{
var logoutUri =
$"https://AUTH0-DOMAIN/v2/logout?client_id=AUTH0-CLIENTID";
var postLogoutUri = context.Properties.RedirectUri;
if (!string.IsNullOrEmpty(postLogoutUri))
{
if (postLogoutUri.StartsWith("/"))
{
// transform to absolute
var request = context.Request;
postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
}
logoutUri += $"&returnTo={Uri.EscapeDataString(postLogoutUri)}";
}
context.Response.Redirect(logoutUri);
context.HandleResponse();
return Task.CompletedTask;
}
};
});
Between the CookiePolicyOptions and the
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
ConfigureServices
Lets get into the code for Auth0
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect("Auth0", options =>
{
Now we're starting to add Auth0 to our project, we start off by setting the Authentication and sign in options. These are telling what openID can use in our project.
We set it to using the Cookie. And then we add OpenID with Auth0 and get into the setup of Auth0.
.AddOpenIdConnect("Auth0", options =>
{
// Set the authority to your Auth0 domain
options.Authority = $"https://AUTH0 - Domain";
// Configure the Auth0 Client ID and Client Secret
options.ClientId = "AUTH0 - ClientID";
options.ClientSecret = "AUTH0 - Client Secret";
// Set response type to code
options.ResponseType = "code";
// Configure the scope
options.Scope.Clear();
options.Scope.Add("openid");
options.CallbackPath = new PathString("/callback");
// Configure the Claims Issuer to be Auth0
options.ClaimsIssuer = "Auth0";
- AUTH0 - Domain - This is the Domain you setup in Auth0
- AUTH0 - ClientID - This is the client ID of your application in Auth0
- AUTH0 - Client Secret - This is the Client Secret from your application in Auth0
The above code configures Auth0 and OpenID to work.
Now we need to setup our events.
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.SetParameter("audience", "AUTH0 - API ID");
return Task.FromResult(0);
}
};
Next we set up our events. These events decide how our app will work. This is for the connect event we can get information back from Auth0 and the provider the user used.
- AUTH0 - API ID - This comes from in Auth0 the API options.
options.Events = new OpenIdConnectEvents
{
// handle the logout redirection
OnRedirectToIdentityProviderForSignOut = (context) =>
{
var logoutUri =
$"https://AUTH0-DOMAIN/v2/logout?client_id=AUTH0-CLIENTID";
var postLogoutUri = context.Properties.RedirectUri;
if (!string.IsNullOrEmpty(postLogoutUri))
{
if (postLogoutUri.StartsWith("/"))
{
// transform to absolute
var request = context.Request;
postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
}
logoutUri += $"&returnTo={Uri.EscapeDataString(postLogoutUri)}";
}
context.Response.Redirect(logoutUri);
context.HandleResponse();
return Task.CompletedTask;
}
};
Our Logout event. These handles the log out and ending of the user session in the application. Release and clear and then redirect back to our default logout page.
Configure
Next we move to the configure method of our Startup.cs and add the
app.UseAuthentication();
This will tell our applcation we are to use some form of Authentication.
Login / Logout
Now that we have configured our application to use authentication and to use open ID we need to add our login option. We can do this anywhere I've created a new controller called "AccountController" added two methods Login and logout to the controller.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
public class AccountController : Controller
{
public async Task Login(string returnUrl = "/")
{
await HttpContext.ChallengeAsync("Auth0", new AuthenticationProperties() { RedirectUri = returnUrl });
}
[Authorize]
public async Task Logout()
{
await HttpContext.SignOutAsync("Auth0", new AuthenticationProperties
{
// Indicate here where Auth0 should redirect the user after a logout.
// Note that the resulting absolute Uri must be whitelisted in the
// **Allowed Logout URLs** settings for the app.
RedirectUri = Url.Action("Index", "Home")
});
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
}
Then I just add a button to the home page with "~/account/login" and when I click Login I get the Auth0 Login page.
Summary
It can always feel a bit intimidating trying to work with Authentication in any application. Even Auth0 can feel abit heavy but once you start into it. It's very simple and powerful and gives us a real great way to expand and grow our application.
I've covered the basic setup in this post. It's part of a series. My goal is to create a .net core 2.2 web application that uses Auth0 to handle the login and signup of users. In other posts in this series I'll go into more detail on different parts.