Well, I figured out the solution.
Basically the example for EmbeddedLock doesn’t include the “SaveTokens” attribute inside of the OpenIdConnectOptions connection options and the tutorials don’t tell you that you need to do this.
You will also have to add the Scope options in order to get the server to send you them.
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("name");
options.Scope.Add("email");
options.Scope.Add("picture");
Here is my final Startup.cs file in case you waste 2 days of waiting for support on this like I did…
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Security.Claims;
using System.Threading.Tasks;
namespace SampleMvcApp
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add authentication services
services.AddAuthentication(
options => options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
// Configure OIDC
services.Configure<OpenIdConnectOptions>(options =>
{
// Specify Authentication Scheme
options.AuthenticationScheme = "Auth0";
// Set the authority to your Auth0 domain
options.Authority = $"https://{Configuration"auth0:domain"]}";
// Configure the Auth0 Client ID and Client Secret
options.ClientId = Configuration"auth0:clientId"];
options.ClientSecret = Configuration"auth0:clientSecret"];
// Do not automatically authenticate and challenge
options.AutomaticAuthenticate = false;
options.AutomaticChallenge = false;
// Set response type to code
options.ResponseType = "code";
// Set the callback path, so Auth0 will call back to http://localhost:5000/signin-auth0
// Also ensure that you have added the URL as an Allowed Callback URL in your Auth0 dashboard
options.CallbackPath = new PathString("/signin-auth0");
// Configure the Claims Issuer to be Auth0
options.ClaimsIssuer = "Auth0";
options.SaveTokens = true;
options.Events = new OpenIdConnectEvents
{
// handle the logout redirection
OnRedirectToIdentityProviderForSignOut = HandleRedirectToIdentityProviderForSignOut,
OnTicketReceived = OnTicketReceived
};
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("name");
options.Scope.Add("email");
options.Scope.Add("picture");
});
// Add framework services.
services.AddMvc();
// Add functionality to inject IOptions<T>
services.AddOptions();
// Add the Auth0 Settings object so it can be injected
services.Configure<Auth0Settings>(Configuration.GetSection("Auth0"));
}
public Task OnTicketReceived(TicketReceivedContext context)
{
// Get the ClaimsIdentity
var identity = context.Principal.Identity as ClaimsIdentity;
if (identity != null)
{
// Add the Name ClaimType. This is required if we want User.Identity.Name to actually return something!
if (!context.Principal.HasClaim(c => c.Type == ClaimTypes.Name) &&
identity.HasClaim(c => c.Type == "name"))
identity.AddClaim(new Claim(ClaimTypes.Name, identity.FindFirst("name").Value));
// Check if token names are stored in Properties
if (context.Properties.Items.ContainsKey(".TokenNames"))
{
// Token names a semicolon separated
string] tokenNames = context.Properties.Items".TokenNames"].Split(';');
// Add each token value as Claim
foreach (var tokenName in tokenNames)
{
// Tokens are stored in a Dictionary with the Key ".Token.<token name>"
string tokenValue = context.Properties.Items$".Token.{tokenName}"];
identity.AddClaim(new Claim(tokenName, tokenValue));
}
}
}
return Task.CompletedTask;
}
public Task HandleRedirectToIdentityProviderForSignOut(RedirectContext context)
{
var logoutUri = $"https://{Configuration"auth0:domain"]}/v2/logout?client_id={Configuration"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;
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<OpenIdConnectOptions> oidcOptions)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
// Add the cookie middleware
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
// Add the OIDC middleware
app.UseOpenIdConnectAuthentication(oidcOptions.Value);
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
The other thing you should know is that the “Scope” is hard coded in the Embedded Lock example, instead of it being passed by the model. That means regardless if you set your scope in Code on the model options, you will also have to set it in the Javascript embed code.
<script src="https://cdn.auth0.com/js/lock/10.12.1/lock.min.js"></script>
<script>
var lock = new Auth0Lock('@Model.ClientId', '@Model.Domain', {
container: 'root',
auth: {
redirectUrl: '@Model.CallbackUrl',
responseType: 'code',
params: {
**scope: 'openid name picture email',**
state: '@Model.State' ,
nonce: '@Model.Nonce'
}
}
});
lock.show();
</script>