Chapter 0 - jayharris/workshop-oidc GitHub Wiki
Chapter 0: Prologue
0.1: Create an empty solution
mkdir IdentityServerWorkshop
cd IdentityServerWorkshop
CLI Directory Reference
Within this document, each CLI example will include a starting path. For the purpose of this document, the path
./
will represent the root Identity Server Workshop directory, and all paths will be relative to this root directory.
# From ./
mkdir src
dotnet new sln
dotnet tool install -g dotnet-aspnet-codegenerator
0.2: Create the initial project
# From ./
dotnet new mvc --name IdentityProvider --auth Individual --output ./src/IdentityProvider/
dotnet sln add ./src/IdentityProvider/IdentityProvider.csproj
cd ./src/IdentityProvider/
dotnet ef database update
0.3: Install IdentityModel NuGet Packages
# From ./src/IdentityProvider
dotnet add package IdentityModel
0.4: Turn off HTTPS
Do not do this for production. Because this is a workshop about Identity Server and not SSL configuration, we will disable HTTPS and leave that for another workshop.
IdentityProvider\Startup.cs
within the Configure
method
//app.UseHttpsRedirection();
0.5: Add a Seed User
IdentityProvider\SeedData.cs
using System;
using System.Linq;
using System.Security.Claims;
using IdentityModel;
using IdentityProvider.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace IdentityProvider
{
public class SeedData
{
public static void EnsureSeedData(string connectionString)
{
var services = new ServiceCollection();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
using (var serviceProvider = services.BuildServiceProvider())
using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = scope.ServiceProvider.GetService<ApplicationDbContext>();
context.Database.Migrate();
var userMgr = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
var adminUser = userMgr.FindByNameAsync("[email protected]").Result;
if (adminUser != null)
{
Console.WriteLine("admin already exists");
return;
}
adminUser = new IdentityUser
{
UserName = "[email protected]"
};
var result = userMgr.CreateAsync(adminUser, "AwesomePassword4U!").Result;
if (!result.Succeeded)
{
throw new Exception(result.Errors.First().Description);
}
result = userMgr.AddClaimsAsync(adminUser, new Claim[]{
new Claim(JwtClaimTypes.Name, "Admin User"),
new Claim(JwtClaimTypes.GivenName, "Admin"),
new Claim(JwtClaimTypes.FamilyName, "User"),
new Claim(JwtClaimTypes.Email, "[email protected]"),
new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.WebSite, "http://example.com"),
new Claim(JwtClaimTypes.Address, @"{ 'street_address': '350 Fifth Avenue', 'locality': 'New York', 'postal_code': 10118, 'country': 'United States' }", "json")
}).Result;
if (!result.Succeeded)
{
throw new Exception(result.Errors.First().Description);
}
Console.WriteLine("admin created");
}
}
}
}
IdentityProvider\Program.cs
add using Microsoft.Extensions.DependencyInjection;
and replace Main
method contents
using Microsoft.Extensions.DependencyInjection;
var seed = args.Any(x => x == "/seed");
if (seed) args = args.Except(new[] { "/seed" }).ToArray();
var host = CreateWebHostBuilder(args).Build();
if (seed)
{
var config = host.Services.GetRequiredService<IConfiguration>();
var connectionString = config.GetConnectionString("DefaultConnection");
SeedData.EnsureSeedData(connectionString);
return;
}
host.Run();
0.6: Seed the Administrative User
# From ./src/IdentityProvider
dotnet run /seed
0.7: Run the Site
# From ./src/IdentityProvider
dotnet run
Be sure to log in as [email protected]
with AwesomePassword4U!
. A successful login will ensure that Entity Framework and ASP.NET Identity are propertly configured before proceeding into Identity Server.