The administration for the Duende IdentityServer and Asp.Net Core Identity
The application is written in the Asp.Net Core MVC - using .NET 8.0
Install the dotnet new template:
π NOTE: The project uses the default database migrations which affect your database, therefore double check the migrations according to your database provider and create a database backup
dotnet new install Skoruba.Duende.IdentityServer.Admin.Templates::2.5.0
dotnet new skoruba.duende.isadmin --name MyProject --title MyProject --adminemail "admin@example.com" --adminpassword "Pa$$word123" --adminrole MyRole --adminclientid MyClientId --adminclientsecret MyClientSecret --dockersupport true
Project template options:
--name: [string value] for project name
--adminpassword: [string value] admin password
--adminemail: [string value] admin email
--title: [string value] for title and footer of the administration in UI
--adminrole: [string value] for name of admin role, that is used to authorize the administration
--adminclientid: [string value] for client name, that is used in the Duende IdentityServer configuration for admin client
--adminclientsecret: [string value] for client secret, that is used in the Duende IdentityServer configuration for admin client
--dockersupport: [boolean value] include docker support
git clone https://github.com/skoruba/Duende.IdentityServer.Admin
We need some resolving capabilities in order for the project to work. The domain skoruba.local
is used here to represent the domain this setup is hosted on. The domain-name needs to be FQDN (fully qualified domain name).
Thus first, we need the domain skoruba.local
to resolve to the docker-host machine. If you want this to work on your local machine only, use the first option.
Edit your hosts file:
\etc\hosts
C:\Windows\system32\drivers\etc\hosts
and add the following entries:
127.0.0.1 skoruba.local sts.skoruba.local admin.skoruba.local admin-api.skoruba.local
This way your host machine resolves skoruba.local
and its subdomains to itself.
We also need certificates in order to serve on HTTPS. We'll make our own self-signed certificates with mkcert.
If the domain is publicly available through DNS, you can use Let's Encypt. Nginx-proxy has support for that, which is left out in this setup.
Use mkcert to generate local self-signed certificates.
On windows mkcert -install
must be executed under elevated Administrator privileges. Then copy over the CA Root certificate over to the project as we want to mount this in later into the containers without using an environment variable. Use PowerShell to run the commands.
cd shared/nginx/certs
mkcert --install
copy $env:LOCALAPPDATA\mkcert\rootCA-key.pem ./cacerts.pem
copy $env:LOCALAPPDATA\mkcert\rootCA.pem ./cacerts.crt
skoruba.local
certificatesGenerate a certificate for skoruba.local
with wildcards for the subdomains. The name of the certificate files need to match with actual domain-names in order for the nginx-proxy to pick them up correctly. We want both the crt-key and the pfx version.
cd shared/nginx/certs
mkcert -cert-file skoruba.local.crt -key-file skoruba.local.key skoruba.local *.skoruba.local
mkcert -pkcs12 skoruba.local.pfx skoruba.local *.skoruba.local
docker-compose.vs.debug.yml
and docker-compose.override.yml
to enable debugging with a seeded environment.docker-compose build
docker-compose up -d
It is also possible to set as startup project the project called
docker-compose
in Visual Studio.
build/publish-docker-images.ps1
- change the profile name according to your requirements.cd src/Skoruba.Duende.IdentityServer.Admin
npm install
cd src/Skoruba.Duende.IdentityServer.STS.Identity
npm install
The following Gulp commands are available:
gulp fonts
- copy fonts to the dist
foldergulp styles
- minify CSS, compile SASS to CSSgulp scripts
- bundle and minify JSgulp clean
- remove the dist
foldergulp build
- run the styles
and scripts
tasksgulp watch
- watch all changes in all sass filesThe solution uses these DbContexts
:
AdminIdentityDbContext
: for Asp.Net Core IdentityAdminLogDbContext
: for loggingIdentityServerConfigurationDbContext
: for IdentityServer configuration storeIdentityServerPersistedGrantDbContext
: for IdentityServer operational storeAuditLoggingDbContext
: for Audit LoggingIdentityServerDataProtectionDbContext
: for dataprotectionNOTE: Initial migrations are a part of the repository.
It is possible to use powershell script in folder build/add-migrations.ps1
.
This script take two arguments:
For example:
.\add-migrations.ps1 -migration DbInit -migrationProviderName SqlServer
It is possible to switch the database provider via
appsettings.json
:
"DatabaseProviderConfiguration": {
"ProviderType": "SqlServer"
}
PostgreSQL:
Server=localhost;Port=5432;Database=DuendeIdentityServerAdmin;User Id=sa;Password=#;
MySql:
server=localhost;database=DuendeIdentityServerAdmin;user=root;password=#
Program.cs
-> Main
, uncomment DbMigrationHelpers.EnsureSeedData(host)
or use dotnet CLI dotnet run /seed
or via SeedConfiguration
in appsettings.json
Clients
and Resources
files in identityserverdata.json
(section called: IdentityServerData) - are the initial data, based on a sample from Duende IdentityServerUsers
file in identitydata.json
(section called: IdentityData) contains the default admin username and password for the first loginappsettings.json
AuthorizationConsts.AdministrationPolicy
. In the policy - AuthorizationConsts.AdministrationPolicy
is defined required role stored in - appsettings.json
- AdministrationRole
.appsettings.json
with following configuration:"AzureKeyVaultConfiguration": {
"AzureKeyVaultEndpoint": "",
"ClientId": "",
"ClientSecret": "",
"UseClientCredentials": true
}
If your application is running in Azure App Service
, you can specify AzureKeyVaultEndpoint
. For applications which are running outside of Azure environment it is possible to use the client credentials flow - so it is necesarry to go to Azure portal, register new application and connect this application to Azure Key Vault and setup the client secret.
"AzureKeyVaultConfiguration": {
"ReadConfigurationFromKeyVault": true
}
Enable Azure Key Vault for dataprotection with following configuration:
"DataProtectionConfiguration": {
"ProtectKeysWithAzureKeyVault": false
}
The you need specify the key identifier in configuration:
"AzureKeyVaultConfiguration": {
"DataProtectionKeyIdentifier": ""
}
"AzureKeyVaultConfiguration": {
"IdentityServerCertificateName": ""
}
We are using Serilog
with pre-definded following Sinks - white are available in serilog.json
:
{
"Serilog": {
"MinimumLevel": {
"Default": "Error",
"Override": {
"Skoruba": "Information"
}
},
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "log.txt",
"rollingInterval": "Day"
}
},
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "...",
"tableName": "Log",
"columnOptionsSection": {
"addStandardColumns": ["LogEvent"],
"removeStandardColumns": ["Properties"]
}
}
}
]
}
}
services.AddAuditLogging(options => { options.Source = auditLoggingConfiguration.Source; })
.AddDefaultHttpEventData(subjectOptions =>
{
subjectOptions.SubjectIdentifierClaim = auditLoggingConfiguration.SubjectIdentifierClaim;
subjectOptions.SubjectNameClaim = auditLoggingConfiguration.SubjectNameClaim;
},
actionOptions =>
{
actionOptions.IncludeFormVariables = auditLoggingConfiguration.IncludeFormVariables;
})
.AddAuditSinks<DatabaseAuditEventLoggerSink<TAuditLog>>();
// repository for library
services.AddTransient<IAuditLoggingRepository<TAuditLog>, AuditLoggingRepository<TAuditLoggingDbContext, TAuditLog>>();
// repository and service for admin
services.AddTransient<IAuditLogRepository<TAuditLog>, AuditLogRepository<TAuditLoggingDbContext, TAuditLog>>();
services.AddTransient<IAuditLogService, AuditLogService<TAuditLog>>();
Admin and STS can be customized without editing code in appsettings.json
under AdminConfiguration section
UI can be customized using themes integrated from bootswatch.
It's possible to change theme from UI. π
By default, configuration value is null to use default theme. If you want to use a theme, just fill the lowercase theme name as configuration value of Theme
key.
You can also use your custom theme by integrating it in your project or hosting css on your place to pass the url in CustomThemeCss
key. (Note that custom theme override standard theme)
appsettings.json
with thrusted domains for ressources. "AdminConfiguration": {
"PageTitle": "Skoruba Duende IdentityServer",
"HomePageLogoUri": "~/images/skoruba-icon.png",
"FaviconUri": "~/favicon.ico",
"Theme": "united",
"CustomThemeCss": null,
...
},
In appsettings.json
is following configuration:
"AuditLoggingConfiguration": {
"Source": "IdentityServer.Admin.Web",
"SubjectIdentifierClaim": "sub",
"SubjectNameClaim": "name",
"IncludeFormVariables": false
}
The Skoruba.Duende.IdentityServer.Admin.BusinessLogic
layer contains folder called Events
for audit logging. In each method in Services is called function LogEventAsync
like this:
await AuditEventLogger.LogEventAsync(new ClientDeletedEvent(client));
Final audit log is available in the table dbo.AuditLog
.
Skoruba.Duende.IdentityServer.STS.Identity
- in appsettings.json
is possible to specify which column will be used for login (Username
or Email
): "LoginConfiguration": {
"ResolutionPolicy": "Username"
}
or using Email
:
"LoginConfiguration": {
"ResolutionPolicy": "Email"
}
Skoruba.Duende.IdentityServer.STS.Identity
- in appsettings.json
is possible to disable user registration (default: true
): "RegisterConfiguration": {
"Enabled": false
}
https://localhost:44302
and swagger UI is available on url - https://localhost:44302/swagger
"AdminApiConfiguration": {
"IdentityServerBaseUrl": "https://localhost:44310",
"OidcSwaggerUIClientId": "skoruba_identity_admin_api_swaggerui",
"OidcApiName": "skoruba_identity_admin_api"
}
Skoruba.Duende.IdentityServer.STS.Identity/Helpers/StartupHelpers.cs
- is method called AddExternalProviders
which contains the example with GitHub
, AzureAD
configured in appsettings.json
:"ExternalProvidersConfiguration": {
"UseGitHubProvider": false,
"GitHubClientId": "",
"GitHubClientSecret": "",
"UseAzureAdProvider": false,
"AzureAdClientId": "",
"AzureAdTenantId": "",
"AzureInstance": "",
"AzureAdSecret": "",
"AzureAdCallbackPath": "",
"AzureDomain": ""
}
ExternalProvidersConfiguration
with another configuration properties.In STS project - in appsettings.json
:
"SendgridConfiguration": {
"ApiKey": "",
"SourceEmail": "",
"SourceName": ""
}
"SmtpConfiguration": {
"From": "",
"Host": "",
"Login": "",
"Password": ""
}
"CspTrustedDomains": [
"google.com",
"mydomain.com"
],
health
, which check databases and IdentityServer.All labels and messages are stored in the resources .resx
- locatated in /Resources
Integration tests use StartupTest class which is pre-configured with:
DbContext
contains setup for InMemory databaseAuthentication
is setup for CookieAuthentication
- with fake login url for testing purpose onlyAuthenticatedTestRequestMiddleware
- middleware for testing of authentication.STS:
Skoruba.Duende.IdentityServer.STS.Identity
- project that contains the instance of Duende.IdentityServer and combine these samples - Quickstart UI for the Duende.IdentityServer with Asp.Net Core Identitye and Quickstart UI for the Duende.IdentityServer with EF Core storage and damienbod - IdentityServer4 and Identity templateAdmin UI Api:
Skoruba.Duende.IdentityServer.Admin.Api
- project with Api for managing data of Duende.IdentityServer and Asp.Net Core Identity, with swagger support as wellAdmin UI:
Skoruba.Duende.IdentityServer.Admin.UI
- ASP.NET Core MVC application that contains Admin UI
Skoruba.Duende.IdentityServer.Admin
- ASP.NET Core MVC application that uses Admin UI package and it's only for application bootstrap
Skoruba.Duende.IdentityServer.Admin.BusinessLogic
- project that contains Dtos, Repositories, Services and Mappers for the Duende.IdentityServer
Skoruba.Duende.IdentityServer.Admin.BusinessLogic.Identity
- project that contains Dtos, Repositories, Services and Mappers for the Asp.Net Core Identity
Skoruba.Duende.IdentityServer.Admin.BusinessLogic.Shared
- project that contains shared Dtos and ExceptionHandling for the Business Logic layer of the Duende.IdentityServer and Asp.Net Core Identity
Skoruba.Duende.IdentityServer.Shared
- Shared common Identity DTOS for Admin UI, Admin UI Api and STS
Skoruba.Duende.IdentityServer.Shared.Configuration
- Shared common layer for Admin UI, Admin UI Api and STS
Skoruba.Duende.IdentityServer.Admin.EntityFramework
- EF Core data layer that contains Entities for the Duende.IdentityServer
Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration
- EF Core data layer that contains configurations
Skoruba.Duende.IdentityServer.Admin.EntityFramework.Identity
- EF Core data layer that contains Repositories for the Asp.Net Core Identity
Skoruba.Duende.IdentityServer.Admin.EntityFramework.Extensions
- project that contains extensions related to EntityFramework
Skoruba.Duende.IdentityServer.Admin.EntityFramework.Shared
- project that contains DbContexts for the Duende.IdentityServer, Logging and Asp.Net Core Identity, inluding shared Identity entities
Skoruba.Duende.IdentityServer.Admin.EntityFramework.SqlServer
- project that contains migrations for SqlServer
Skoruba.Duende.IdentityServer.Admin.EntityFramework.MySql
- project that contains migrations for MySql
Skoruba.Duende.IdentityServer.Admin.EntityFramework.PostgreSQL
- project that contains migrations for PostgreSQL
Tests:
Skoruba.Duende.IdentityServer.Admin.IntegrationTests
- xUnit project that contains the integration tests for AdminUI
Skoruba.Duende.IdentityServer.Admin.Api.IntegrationTests
- xUnit project that contains the integration tests for AdminUI Api
Skoruba.Duende.IdentityServer.Admin.UnitTests
- xUnit project that contains the unit tests for AdminUI
Skoruba.Duende.IdentityServer.STS.IntegrationTests
- xUnit project that contains the integration tests for STS
Clients
It is possible to define the configuration according the client type - by default the client types are used:
Empty
Web Application - Server side - Authorization Code Flow with PKCE
Single Page Application - Javascript - Authorization Code Flow with PKCE
Native Application - Mobile/Desktop - Hybrid flow
Machine/Robot - Client Credentials flow
TV and Limited-Input Device Application - Device flow
Actions: Add, Update, Clone, Remove
Entities:
API Resources
Identity Resources
Users
Roles
dotnet new template
[x] Role users pagination (#169)
[x] Add secure secret generation with 'secret_' prefix (#153)
[x] Increase client name prominence (#154)
[x] Added support for generation typescript client definition for API endpoints (#215)
[x] Add new endpoints to API for client, api resource, api scopes validations and lists (#213)
[x] Use named arguments in .AddIdentityServer() healthchecks (#201)
[x] Change the AdminIdentityDbContext tablenames to be derived from appsettings (#196)
[x] Raise UserLoginSuccessEvent when logging in with 2fa or recovery code (#202)
Skoruba.Duende.IdentityServer.Admin.UI.Api
to be Shipped as a NuGet Package(linux/amd64, linux/arm64)
(#194)Duende.IdentityServer
version 7.0.5
This repository is licensed under the terms of the Apache License 2.0.
Duende.IdentityServer is available under both a FOSS (RPL) and a commercial license.
For the production environment is necessary to get the specific license. For more information about licensing of Duende.IdentityServer - please check this link.
This repository uses the source code from https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI which is under the terms of the following license.
This web application is based on these projects:
Thanks to TomΓ‘Ε‘ HΓΌbelbauer for the initial code review.
Thanks to Dominick Baier and Brock Allen - the creators of Duende.IdentityServer.
Thanks goes to these wonderful people (emoji key):
Jan Ε koruba π» π¬ π π‘ π€ |
TomΓ‘Ε‘ HΓΌbelbauer π» π π π€ |
MichaΕ DrzaΕ π» π π π‘ π€ |
cerginio π» π π‘ π€ |
Sven Dummis π |
Seaear π» π |
---|---|---|---|---|---|
Rune Antonsen π |
Sindre NjΓΈsen π» |
Alevtina Brown π |
Brice π» |
TheEvilPenguin π» |
Saeed Rahmani π |
Andy Yu π |
ChrisSzabo π» |
aiscrim π» π‘ π€ |
HrDahl π |
Andrew Godfroy π |
bravecobra π» |
Sabit Igde π» |
Rico Herlt π» |
b0 π» |
DrQwertySilence π |
Carl Quirion π» |
Aegide π |
LobsterBandit π» |
Mehmet Perk π» |
tapmui π |
Saeed Rahimi π» |
Joshua Williams π» |
Shengjie Yan π» |
Anatoliy π» |
Nicholas Peterson π» |
Alec Papierniak π» |
Carl Reid π» |
ViRuSTriNiTy π» |
J. Arturo π» |
Weihan Li π» |
SaΕ‘a TanΔev π» |
cuibty π» |
Simo Paasisalo π» |
klyse π» |
Martinus Suherman π» |
Pavel Usachev π» |
LabTrans - STIGeo π |
Valentin LECERF π» |
Thomas Aunvik π |
Sebastian Gebhardt π |
This project follows the all-contributors specification. Contributions of any kind are welcome!
I am happy to share my attempt of the implementation of the administration for Duende.IdentityServer and ASP.NET Core Identity.
Any feedback is welcome - feel free to create an issue or send me an email - jan@skoruba.com. Thank you :blush:
If you like my work, you can support me by donation. π