README.md 36.2 KB
Newer Older
1
![Logo](docs/Images/Skoruba.IdentityServer4.Admin-Logo-ReadMe.png)
2

3
4
# Skoruba.IdentityServer4.Admin

5
> The administration of the IdentityServer4 and Asp.Net Core Identity
6

7
## Project Status
8

Jan Škoruba's avatar
Jan Škoruba committed
9
[![Build status](https://ci.appveyor.com/api/projects/status/5yg59bn70399hn6s/branch/master?svg=true)](https://ci.appveyor.com/project/JanSkoruba/identityserver4-admin/branch/master)
10
[![Build Status](https://dev.azure.com/skoruba/IdentityServer4.Admin/_apis/build/status/IdentityServer4.Admin-CI?branchName=master)](https://dev.azure.com/skoruba/IdentityServer4.Admin/_build/latest?definitionId=2?branchName=master)
Jan Škoruba's avatar
Jan Škoruba committed
11
[![Join the chat at https://gitter.im/skoruba/IdentityServer4.Admin](https://badges.gitter.im/skoruba/IdentityServer4.Admin.svg)](https://gitter.im/skoruba/IdentityServer4.Admin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
12

Jan Škoruba's avatar
Jan Škoruba committed
13
The application is written in the **Asp.Net Core MVC - using .NET 5**
14

Jan Škoruba's avatar
Jan Škoruba committed
15
## Requirements
16

Jan Škoruba's avatar
Jan Škoruba committed
17
- [Install](https://www.microsoft.com/net/download/windows#/current) the latest .NET 5 SDK (using older versions may lead to 502.5 errors when hosted on IIS or application exiting immediately after starting when self-hosted)
18

19
20
21
22
## Installation via dotnet new template

- Install the dotnet new template:

Jan Škoruba's avatar
Jan Škoruba committed
23
### Version 2.0.0 works with **IdentityServer4 version 4** 🚀
Jan Škoruba's avatar
Jan Škoruba committed
24
25

- 🔒 **NOTE:** This version affects your database data if you use the default database migrations that are part of the project - double check the migrations according to your database provider and create a database backup
Jan Škoruba's avatar
Jan Škoruba committed
26

27
```sh
Jan Škoruba's avatar
Jan Škoruba committed
28
dotnet new -i Skoruba.IdentityServer4.Admin.Templates::2.0.0
29
30
```

Jan Škoruba's avatar
Jan Škoruba committed
31
### Create new project:
32
33

```sh
Jan Škoruba's avatar
Jan Škoruba committed
34
dotnet new skoruba.is4admin --name MyProject --title MyProject --adminemail "admin@example.com" --adminpassword "Pa$$word123" --adminrole MyRole --adminclientid MyClientId --adminclientsecret MyClientSecret --dockersupport true
35
36
```

janskoruba's avatar
janskoruba committed
37
38
39
40
Project template options:

```
--name: [string value] for project name
Jan Škoruba's avatar
Jan Škoruba committed
41
42
--adminpassword: [string value] admin password
--adminemail: [string value] admin email
janskoruba's avatar
janskoruba committed
43
44
--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
45
46
--adminclientid: [string value] for client name, that is used in the IdentityServer4 configuration for admin client
--adminclientsecret: [string value] for client secret, that is used in the IdentityServer4 configuration for admin client
Jan Škoruba's avatar
Jan Škoruba committed
47
--dockersupport: [boolean value] include docker support
janskoruba's avatar
janskoruba committed
48
49
```

50
## How to configure the Administration - IdentityServer4 and Asp.Net Core Identity
janskoruba's avatar
janskoruba committed
51

52
- [Follow these steps for setup project to use existing IdentityServer4 and Asp.Net Core Identity](docs/Configure-Administration.md)
janskoruba's avatar
janskoruba committed
53

54
55
### Template uses following list of nuget packages

janskoruba's avatar
janskoruba committed
56
- [Available nuget packages](https://www.nuget.org/profiles/skoruba)
57

Jan Škoruba's avatar
Jan Škoruba committed
58
59
60
61
### Running in Visual Studio

- Set Startup projects:
  - Skoruba.IdentityServer4.Admin
Jan Škoruba's avatar
Jan Škoruba committed
62
  - Skoruba.IdentityServer4.Admin.Api
Jan Škoruba's avatar
Jan Škoruba committed
63
64
  - Skoruba.IdentityServer4.STS.Identity

Jan Škoruba's avatar
Jan Škoruba committed
65
66
67
68
69
## Configuration of Administration for Deployment

- [Configuration of Admin for deploy on Azure](docs/Configure-Azure-Deploy.md)
- [Configuration of Admin on Ubuntu with PostgreSQL database](docs/Configure-Ubuntu-PostgreSQL-Tutorial.md)

janskoruba's avatar
janskoruba committed
70
71
72
73
## Administration UI preview

- This administration uses bootstrap 4

Jan Škoruba's avatar
Jan Škoruba committed
74
### Admin UI - Light mode 🌞
75

Jan Škoruba's avatar
Jan Škoruba committed
76
77
![Admin-preview](docs/Images/App/1.PNG)

Jan Škoruba's avatar
Jan Škoruba committed
78
### Admin UI - Dark mode 🌙
Jan Škoruba's avatar
Jan Škoruba committed
79
80

![Admin-preview](docs/Images/App/2.PNG)
janskoruba's avatar
janskoruba committed
81

Jan Škoruba's avatar
Jan Škoruba committed
82
### Security token service (STS)
83

Jan Škoruba's avatar
Jan Škoruba committed
84
![Admin-preview](docs/Images/App/4.PNG)
85

Jan Škoruba's avatar
Jan Škoruba committed
86
### Forms:
janskoruba's avatar
janskoruba committed
87

Jan Škoruba's avatar
Jan Škoruba committed
88
![Admin-preview-form](docs/Images/App/3.png)
janskoruba's avatar
janskoruba committed
89

90
## Cloning
91

92
93
94
```sh
git clone https://github.com/skoruba/IdentityServer4.Admin
```
95

Jan Škoruba's avatar
Jan Škoruba committed
96
## Running via Docker
Jan Škoruba's avatar
Jan Škoruba committed
97

Jan Škoruba's avatar
Jan Škoruba committed
98
99
- It is possible to run Admin UI through the docker.

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
### Docker setup

### DNS

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.

#### DNS on docker-host machine only

Edit your hosts file:

- On Linux: `\etc\hosts` 
- On Windows: `C:\Windows\system32\drivers\etc\hosts` 

 and add the following entries:

```custom
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.

### Certificates

We also need certificates in order to serve on HTTPS. We'll make our own self-signed certificates with [mkcert](https://github.com/FiloSottile/mkcert). 

> If the domain is publicly available through DNS, you can use [Let's Encypt](https://letsencrypt.org/). Nginx-proxy has support for that, which is left out in this setup.

#### MkCert

##### Create the root certificate

Use [mkcert](https://github.com/FiloSottile/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.

```bash
cd shared/nginx/certs
mkcert --install
copy $env:LOCALAPPDATA\mkcert\rootCA.pem ./cacerts.pem
copy $env:LOCALAPPDATA\mkcert\rootCA.pem ./cacerts.crt
```
##### Create the `skoruba.local` certificates

Generate 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.

```bash
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
```

##### This docker setup is come from this [repository](https://github.com/bravecobra/identityserver-ui) - thanks to [bravecobra](https://github.com/bravecobra). 😊

### Run docker-compose

Jan Škoruba's avatar
Jan Škoruba committed
157
- Project contains the `docker-compose.vs.debug.yml` and `docker-compose.override.yml` to enable debugging with a seeded environment. 
Jan Škoruba's avatar
Jan Škoruba committed
158
- The following possibility to get a running seeded and debug-able (in VS) environment:
Jan Škoruba's avatar
Jan Škoruba committed
159

Jan Škoruba's avatar
Jan Škoruba committed
160
161
```
docker-compose build
Jan Škoruba's avatar
Jan Škoruba committed
162
docker-compose up -d
Jan Škoruba's avatar
Jan Škoruba committed
163
```
Jan Škoruba's avatar
Jan Škoruba committed
164
165

> It is also possible to set as startup project the project called `docker-compose` in Visual Studio.
Jan Škoruba's avatar
Jan Škoruba committed
166

Jan Škoruba's avatar
Jan Škoruba committed
167
### Docker images
Jan Škoruba's avatar
Jan Škoruba committed
168
- Docker images will be available also in [docker hub](https://hub.docker.com/u/skoruba)
Jan Škoruba's avatar
Jan Škoruba committed
169
170
  - AdminUI:    
    - `skoruba/identityserver4-admin:2.0.0`
Jan Škoruba's avatar
Jan Škoruba committed
171
  - Admin Api:
Jan Škoruba's avatar
Jan Škoruba committed
172
    - `skoruba/identityserver4-admin-api:2.0.0`
Jan Škoruba's avatar
Jan Škoruba committed
173
  - STS:
Jan Škoruba's avatar
Jan Škoruba committed
174
    - `skoruba/identityserver4-sts-identity:2.0.0`
175
       
Jan Škoruba's avatar
Jan Škoruba committed
176
177
### Publish Docker images to Docker hub
- Check the script in `build/publish-docker-images.ps1` - change the profile name according to your requirements.
Jan Škoruba's avatar
Jan Škoruba committed
178

179
## Installation of the Client Libraries
180

181
182
183
```sh
cd src/Skoruba.IdentityServer4.Admin
npm install
Jan Škoruba's avatar
Jan Škoruba committed
184
185
186

cd src/Skoruba.IdentityServer4.STS.Identity
npm install
187
```
188

189
## Bundling and Minification
190

191
192
193
194
195
196
197
The following Gulp commands are available:

- `gulp fonts` - copy fonts to the `dist` folder
- `gulp styles` - minify CSS, compile SASS to CSS
- `gulp scripts` - bundle and minify JS
- `gulp clean` - remove the `dist` folder
- `gulp build` - run the `styles` and `scripts` tasks
Jan Škoruba's avatar
Jan Škoruba committed
198
- `gulp watch` - watch all changes in all sass files
199
200

## EF Core & Data Access
201

202
203
204
205
206
207
- The solution uses these `DbContexts`:

  - `AdminIdentityDbContext`: for Asp.Net Core Identity
  - `AdminLogDbContext`: for logging
  - `IdentityServerConfigurationDbContext`: for IdentityServer configuration store
  - `IdentityServerPersistedGrantDbContext`: for IdentityServer operational store
Jan Škoruba's avatar
Jan Škoruba committed
208
  - `AuditLoggingDbContext`: for Audit Logging
Jan Škoruba's avatar
Jan Škoruba committed
209
  - `IdentityServerDataProtectionDbContext`: for dataprotection
210

Jan Škoruba's avatar
Jan Škoruba committed
211
### Run entity framework migrations:
Jan Škoruba's avatar
Jan Škoruba committed
212
213
214

> NOTE: Initial migrations are a part of the repository.

Jan Škoruba's avatar
Jan Škoruba committed
215
216
217
218
  - It is possible to use powershell script in folder `build/add-migrations.ps1`.
  - This script take two arguments:
    - --migration (migration name)
    - --migrationProviderName (provider type - available choices: All, SqlServer, MySql, PostgreSQL)
219

Jan Škoruba's avatar
Jan Škoruba committed
220
- For example: 
cuibty's avatar
cuibty committed
221
`.\add-migrations.ps1 -migration DbInit -migrationProviderName SqlServer`
222

Jan Škoruba's avatar
Jan Škoruba committed
223
224
225
226
### Available database providers:
- SqlServer
- MySql
- PostgreSQL
227

Jan Škoruba's avatar
Jan Škoruba committed
228
> It is possible to switch the database provider via `appsettings.json`:
229
```
Jan Škoruba's avatar
Jan Škoruba committed
230
231
232
"DatabaseProviderConfiguration": {
        "ProviderType": "SqlServer" 
    }
233
```
Jan Škoruba's avatar
Jan Škoruba committed
234
235
236
237
        
### Connection strings samples for available db providers:
**PostgreSQL**: 
> Server=localhost;Port=5432;Database=IdentityServer4Admin;User Id=sa;Password=#;
238

Jan Škoruba's avatar
Jan Škoruba committed
239
240
**MySql:** 
> server=localhost;database=IdentityServer4Admin;user=root;password=#
Jan Škoruba's avatar
Jan Škoruba committed
241

242

Jan Škoruba's avatar
Jan Škoruba committed
243
### We suggest to use seed data:
244

Jan Škoruba's avatar
Jan Škoruba committed
245
- In `Program.cs` -> `Main`, uncomment `DbMigrationHelpers.EnsureSeedData(host)` or use dotnet CLI `dotnet run /seed` or via `SeedConfiguration` in `appsettings.json`
Jan Škoruba's avatar
Jan Škoruba committed
246
247
- The `Clients` and `Resources` files in `identityserverdata.json` (section called: IdentityServerData) - are the initial data, based on a sample from IdentityServer4
- The `Users` file in `identitydata.json` (section called: IdentityData) contains the default admin username and password for the first login
248

249
## Authentication and Authorization
250

Jan Škoruba's avatar
Jan Škoruba committed
251
252
- Change the specific URLs and names for the IdentityServer and Authentication settings in `appsettings.json`
- In the controllers is used the policy which name is stored in - `AuthorizationConsts.AdministrationPolicy`. In the policy - `AuthorizationConsts.AdministrationPolicy` is defined required role stored in - `appsettings.json` - `AdministrationRole`.
253
- With the default configuration, it is necessary to configure and run instance of IdentityServer4. It is possible to use initial migration for creating the client as it mentioned above
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
## Azure Key Vault

- It is possible to use Azure Key Vault and configure it in the `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.

- It is possible to use Azure Key Vault for following parts of application:

### Application Secrets and Database Connection Strings:

- It is necesarry to configure the connection to Azure Key Vault and allow following settings:

```
"AzureKeyVaultConfiguration": {
    "ReadConfigurationFromKeyVault": true
  }
```

### Dataprotection:

Enable Azure Key Vault for dataprotection with following configuration:
```
"DataProtectionConfiguration": {
    "ProtectKeysWithAzureKeyVault": false
  }
```

The you need specify the key identifier in configuration:

```
"AzureKeyVaultConfiguration": {
    "DataProtectionKeyIdentifier": ""
  }
```

### IdentityServer certificate for signing tokens:

- It is possible to go to Azure Key Vault - generate new certificate and use this certificate name below:

```
"AzureKeyVaultConfiguration": {
    "IdentityServerCertificateName": ""
  }
```
Jan Škoruba's avatar
Jan Škoruba committed
308
309
310
311
312
313
314
315

## Logging

- We are using `Serilog` with pre-definded following Sinks - white are available in `serilog.json`:

  - Console
  - File
  - MSSqlServer
Jan Škoruba's avatar
Jan Škoruba committed
316
  - Seq
Jan Škoruba's avatar
Jan Škoruba committed
317
  
Jan Škoruba's avatar
Jan Škoruba committed
318
```json
Jan Škoruba's avatar
Jan Škoruba committed
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
{
    "Serilog": {
        "MinimumLevel": {
            "Default": "Error",
            "Override": {
                "Skoruba": "Information"
            }
        },
        "WriteTo": [
            {
                "Name": "Console"
            },
            {
                "Name": "File",
                "Args": {
                    "path": "log.txt",
                    "rollingInterval": "Day"
                }
            },
            {
                "Name": "MSSqlServer",
                "Args": {
Jan Škoruba's avatar
Jan Škoruba committed
341
                    "connectionString": "...",
Jan Škoruba's avatar
Jan Škoruba committed
342
343
344
345
346
347
348
349
350
351
352
353
                    "tableName": "Log",
                    "columnOptionsSection": {
                        "addStandardColumns": [ "LogEvent" ],
                        "removeStandardColumns": [ "Properties" ]
                    }
                }
            }
        ]
    }
}
```

Jan Škoruba's avatar
Jan Škoruba committed
354
355
## Audit Logging

Jan Škoruba's avatar
Jan Škoruba committed
356
- This solution uses audit logging via - https://github.com/skoruba/AuditLogging (check this link for more detal about this implementation :blush:)
Jan Škoruba's avatar
Jan Škoruba committed
357
358
- In the Admin UI project is following setup:

Jan Škoruba's avatar
Jan Škoruba committed
359
```cs
Jan Škoruba's avatar
Jan Škoruba committed
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
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>>();
```

Valentin LECERF's avatar
Valentin LECERF committed
380
381
382
383
384
385
### Admin Configuration

Admin and STS can be customized without editing code in `appsettings.json` under AdminConfiguration section

#### Themes

Jan Škoruba's avatar
Jan Škoruba committed
386
387
Ui can be customized using themes integrated from [bootswatch](https://bootswatch.com).

Jan Škoruba's avatar
Jan Škoruba committed
388
389
From version 2.0.0 is possible to change theme from UI. 🎈

Valentin LECERF's avatar
Valentin LECERF committed
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
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)

- Important Note: Theme can use external ressources which caused errors due to CSP. If you get errors, please make sure that you configured correctly CSP section in your `appsettings.json` with thrusted domains for ressources.

```json
  "AdminConfiguration": {
    "PageTitle": "Skoruba IdentityServer4",
    "HomePageLogoUri": "~/images/skoruba-icon.png",
    "FaviconUri": "~/favicon.ico",
    "Theme": "united",
    "CustomThemeCss": null,
    ...
  },
```

Jan Škoruba's avatar
Jan Škoruba committed
407
408
409
410
### Audit Logging Configuration

In `appsettings.json` is following configuration:

Jan Škoruba's avatar
Jan Škoruba committed
411
```json
Jan Škoruba's avatar
Jan Škoruba committed
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
"AuditLoggingConfiguration": {
    "Source": "IdentityServer.Admin.Web",
    "SubjectIdentifierClaim": "sub",
    "SubjectNameClaim": "name",
    "IncludeFormVariables": false
  }
```

The `Skoruba.IdentityServer4.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`.

427
428
429
430
431
432
433
434
435
436
437
438
439
440
### Login Configuration

- In `Skoruba.IdentityServer4.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": {
Jan Škoruba's avatar
Jan Škoruba committed
441
    "ResolutionPolicy": "Email"    
442
443
444
445
446
447
448
449
450
451
452
453
454
  }
```

### Register Configuration

- In `Skoruba.IdentityServer4.STS.Identity` - in `appsettings.json` is possible to disable user registration (`default: true`):

```
 "RegisterConfiguration": {
    "Enabled": false
  }
```

455
456
## How to configure API & Swagger

Jan Škoruba's avatar
Jan Škoruba committed
457
- For development is running on url - `https://localhost:44302` and swagger UI is available on url - `https://localhost:44302/swagger`
458
459
460
461
- For swagger UI is configured a client and an API in STS:

```
"AdminApiConfiguration": {
Jan Škoruba's avatar
Jan Škoruba committed
462
  "IdentityServerBaseUrl": "https://localhost:44310",
463
464
465
466
467
468
469
470
471
472
  "OidcSwaggerUIClientId": "skoruba_identity_admin_api_swaggerui",
  "OidcApiName": "skoruba_identity_admin_api"
}
```

- Swagger UI contains following endpoints:

![SwaggerUI-preview](docs/Images/Admin-Swagger-UI.PNG)


473
474
## How to configure an external provider in STS

475
- In `Skoruba.IdentityServer4.STS.Identity/Helpers/StartupHelpers.cs` - is method called `AddExternalProviders` which contains the example with `GitHub`, `AzureAD` configured in `appsettings.json`:
476
477
478
479
480

```
"ExternalProvidersConfiguration": {
        "UseGitHubProvider": false,
        "GitHubClientId": "",
481
482
483
484
485
486
487
488
        "GitHubClientSecret": "",
        "UseAzureAdProvider": false,
        "AzureAdClientId": "",
        "AzureAdTenantId": "",
        "AzureInstance": "",
        "AzureAdSecret": "",
        "AzureAdCallbackPath": "",
        "AzureDomain": "" 
489
490
491
492
}
```

- It is possible to extend `ExternalProvidersConfiguration` with another configuration properties.
493
494
495
- If you use DockerHub built image, you can use appsettings to configure these providers without changing the code
  - GitHub
  - AzureAD
496
497
498
499
500
501
502

### List of external providers for ASP.NET Core:
  - https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
  - https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/
 
### Azure AD
- Great article how to set up Azure AD:
503
  - https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-aspnet-core-webapp
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523

## Email service

- It is possible to set up emails via:

### SendGrid

In STS project - in `appsettings.json`:
```
"SendgridConfiguration": {
        "ApiKey": "",
        "SourceEmail": "",
        "SourceName": ""
    }
```

### SMTP

```
"SmtpConfiguration": {
Jan Škoruba's avatar
Jan Škoruba committed
524
        "From": "",
525
526
527
528
529
530
        "Host": "",
        "Login": "",
        "Password": ""
    }
```

531
532
533
534
535
536
537
538
539
540
541
## CSP - Content Security Policy

- If you want to use favicon or logo not included/hosted on the same place, you need to declare trusted domain where ressources are hosted in appsettings.json.

```
  "CspTrustedDomains": [
    "google.com",
    "mydomain.com"
  ],
```

Jan Škoruba's avatar
Jan Škoruba committed
542
543
544
545
546
## Health checks

- AdminUI, AdminUI Api and STS contain endpoint `health`, which check databases and IdentityServer.


547
## Localizations - labels, messages
548

549
550
551
552
553
554
- The project has following translations:
  - English
  - Chinese
  - Russian
  - Persian
  - Swedish
Jan Škoruba's avatar
Jan Škoruba committed
555
556
557
  - Danish
  - Spanish
  - French
Jan Škoruba's avatar
Jan Škoruba committed
558
  - Finish
Jan Škoruba's avatar
Jan Škoruba committed
559
  - German
Jan Škoruba's avatar
Jan Škoruba committed
560
  - Portuguese
561
562
563
  
#### Feel free to send a PR with your translation. :blush:

564
- All labels and messages are stored in the resources `.resx` - locatated in `/Resources`
565

Jan Škoruba's avatar
Jan Škoruba committed
566
567
568
  - Client label descriptions from - http://docs.identityserver.io/en/latest/reference/client.html
  - Api Resource label descriptions from - http://docs.identityserver.io/en/latest/reference/api_resource.html
  - Identity Resource label descriptions from - http://docs.identityserver.io/en/latest/reference/identity_resource.html
569

Jan Škoruba's avatar
Jan Škoruba committed
570
571
## Tests

572
573
- The solution contains unit and integration tests.

Jan Škoruba's avatar
Jan Škoruba committed
574
Integration tests use StartupTest class which is pre-configured with:
Jan Škoruba's avatar
Jan Škoruba committed
575
  - `DbContext` contains setup for InMemory database
Jan Škoruba's avatar
Jan Škoruba committed
576
  - `Authentication` is setup for `CookieAuthentication` - with fake login url for testing purpose only
Jan Škoruba's avatar
Jan Škoruba committed
577
  - `AuthenticatedTestRequestMiddleware` - middleware for testing of authentication.
578

579
## Overview
580

Jan Škoruba's avatar
Jan Škoruba committed
581
### Solution structure:
582

Jan Škoruba's avatar
Jan Škoruba committed
583
- STS:
584

Jan Škoruba's avatar
Jan Škoruba committed
585
  - `Skoruba.IdentityServer4.STS.Identity` - project that contains the instance of IdentityServer4 and combine these samples - [Quickstart UI for the IdentityServer4 with Asp.Net Core Identity and EF Core storage](https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Quickstarts/9_Combined_AspId_and_EFStorage) and [damienbod - IdentityServer4 and Identity template](https://github.com/damienbod/IdentityServer4AspNetCoreIdentityTemplate)
Jan Škoruba's avatar
Jan Škoruba committed
586

Jan Škoruba's avatar
Jan Škoruba committed
587
588
- Admin UI Api:

Jan Škoruba's avatar
Jan Škoruba committed
589
  - `Skoruba.IdentityServer4.Admin.Api` - project with Api for managing data of IdentityServer4 and Asp.Net Core Identity, with swagger support as well
Jan Škoruba's avatar
Jan Škoruba committed
590

Jan Škoruba's avatar
Jan Škoruba committed
591
- Admin UI:
592

Jan Škoruba's avatar
Jan Škoruba committed
593
594
595
  - `Skoruba.IdentityServer4.Admin.UI` - ASP.NET Core MVC application that contains Admin UI

  - `Skoruba.IdentityServer4.Admin` - ASP.NET Core MVC application that uses Admin UI package and it's only for application bootstrap
596

597
598
599
600
601
602
  - `Skoruba.IdentityServer4.Admin.BusinessLogic` - project that contains Dtos, Repositories, Services and Mappers for the IdentityServer4

  - `Skoruba.IdentityServer4.Admin.BusinessLogic.Identity` - project that contains Dtos, Repositories, Services and Mappers for the Asp.Net Core Identity

  - `Skoruba.IdentityServer4.Admin.BusinessLogic.Shared` - project that contains shared Dtos and ExceptionHandling for the Business Logic layer of the IdentityServer4 and Asp.Net Core Identity

Jan Škoruba's avatar
Jan Škoruba committed
603
604
605
  - `Skoruba.IdentityServer4.Shared` - Shared common Identity DTOS for Admin UI, Admin UI Api and STS

  - `Skoruba.IdentityServer4.Shared.Configuration` - Shared common layer for Admin UI, Admin UI Api and STS
Jan Škoruba's avatar
Jan Škoruba committed
606

607
608
  - `Skoruba.IdentityServer4.Admin.EntityFramework` - EF Core data layer that contains Entities for the IdentityServer4

Jan Škoruba's avatar
Jan Škoruba committed
609
610
  - `Skoruba.IdentityServer4.Admin.EntityFramework.Configuration` - EF Core data layer that contains configurations

Jan Škoruba's avatar
Jan Škoruba committed
611
  - `Skoruba.IdentityServer4.Admin.EntityFramework.Identity` - EF Core data layer that contains Repositories for the Asp.Net Core Identity
Jan Škoruba's avatar
Jan Škoruba committed
612
613
  
  - `Skoruba.IdentityServer4.Admin.EntityFramework.Extensions` - project that contains extensions related to EntityFramework
614

Jan Škoruba's avatar
Jan Škoruba committed
615
  - `Skoruba.IdentityServer4.Admin.EntityFramework.Shared` - project that contains DbContexts for the IdentityServer4, Logging and Asp.Net Core Identity, inluding shared Identity entities
616

Jan Škoruba's avatar
Jan Škoruba committed
617
618
619
620
621
622
623
  - `Skoruba.IdentityServer4.Admin.EntityFramework.SqlServer` - project that contains migrations for SqlServer

  - `Skoruba.IdentityServer4.Admin.EntityFramework.MySql` - project that contains migrations for MySql

  - `Skoruba.IdentityServer4.Admin.EntityFramework.PostgreSQL` - project that contains migrations for PostgreSQL


Jan Škoruba's avatar
Jan Škoruba committed
624
625
- Tests:

626
  - `Skoruba.IdentityServer4.Admin.IntegrationTests` - xUnit project that contains the integration tests for AdminUI
Jan Škoruba's avatar
Jan Škoruba committed
627
628
  
  - `Skoruba.IdentityServer4.Admin.Api.IntegrationTests` - xUnit project that contains the integration tests for AdminUI Api
629
630

  - `Skoruba.IdentityServer4.Admin.UnitTests` - xUnit project that contains the unit tests for AdminUI
631

632
  - `Skoruba.IdentityServer4.STS.IntegrationTests` - xUnit project that contains the integration tests for STS
633

Jan Škoruba's avatar
Jan Škoruba committed
634
### The admininistration contains the following sections:
635

636
![Skoruba.IdentityServer4.Admin App](docs/Images/Skoruba.IdentityServer4.Admin-Solution.png)
skoruba's avatar
skoruba committed
637

638
## IdentityServer4
639

640
**Clients**
skoruba's avatar
skoruba committed
641

642
It is possible to define the configuration according the client type - by default the client types are used:
643

644
- Empty
Jan Škoruba's avatar
Jan Škoruba committed
645
- Web Application - Server side - Authorization Code Flow with PKCE
646
- Single Page Application - Javascript - Authorization Code Flow with PKCE
647
- Native Application - Mobile/Desktop - Hybrid flow
Jan Škoruba's avatar
Jan Škoruba committed
648
- Machine/Robot - Client Credentials flow
Jan Škoruba's avatar
Jan Škoruba committed
649
- TV and Limited-Input Device Application - Device flow
650

651
652
- Actions: Add, Update, Clone, Remove
- Entities:
653
654
655
656
657
658
659
660
  - Client Cors Origins
  - Client Grant Types
  - Client IdP Restrictions
  - Client Post Logout Redirect Uris
  - Client Properties
  - Client Redirect Uris
  - Client Scopes
  - Client Secrets
661

Tomáš Hübelbauer's avatar
Tomáš Hübelbauer committed
662
**API Resources**
663
664

- Actions: Add, Update, Remove
665
666
667
668
669
- Entities:
  - Api Claims
  - Api Scopes
  - Api Scope Claims
  - Api Secrets
Jan Škoruba's avatar
Jan Škoruba committed
670
  - Api Properties
671

Tomáš Hübelbauer's avatar
Tomáš Hübelbauer committed
672
**Identity Resources**
673

674
675
- Actions: Add, Update, Remove
- Entities:
676
  - Identity Claims
Jan Škoruba's avatar
Jan Škoruba committed
677
  - Identity Properties
678

679
## Asp.Net Core Identity
680

681
**Users**
682

683
684
- Actions: Add, Update, Delete
- Entities:
685
686
687
  - User Roles
  - User Logins
  - User Claims
688

689
**Roles**
690

691
692
- Actions: Add, Update, Delete
- Entities:
693
  - Role Claims
694
695
696
697
698

## Application Diagram

![Skoruba.IdentityServer4.Admin Diagram](docs/Images/Skoruba.IdentityServer4.Admin-App-Diagram.png)

699
## Roadmap & Vision
700

janskoruba's avatar
janskoruba committed
701
702
703
### 1.0.0:

- [x] Create the Business Logic & EF layers - available as a nuget package
Jan Škoruba's avatar
Jan Škoruba committed
704
- [x] Create a project template using dotnet CLI - `dotnet new template`
janskoruba's avatar
janskoruba committed
705
  - [x] First template: The administration of the IdentityServer4 and Asp.Net Core Identity
706
- [x] Add logging into
Jan Škoruba's avatar
Jan Škoruba committed
707
  - [x] Database
Jan Škoruba's avatar
Jan Škoruba committed
708
  - [x] File
Jan Škoruba's avatar
Jan Škoruba committed
709
  - [x] Seq
janskoruba's avatar
janskoruba committed
710
711
712
- [x] Add localization for other languages
  - [x] English
  - [x] Chinese
713
  - [x] Russian
Jan Škoruba's avatar
Jan Škoruba committed
714
  - [x] Persian
715
  - [x] Swedish
Jan Škoruba's avatar
Jan Škoruba committed
716
717
  - [x] Danish
  - [x] Spanish
Jan Škoruba's avatar
Jan Škoruba committed
718
719
  - [x] French
  - [x] Finish
Jan Škoruba's avatar
Jan Škoruba committed
720
721
- [x] Manage profile
- [x] Password reset
722
- [x] Link account to an external provider (example with Github)
Jan Škoruba's avatar
Jan Škoruba committed
723
- [x] Two-Factor Authentication (2FA)
Jan Škoruba's avatar
Jan Škoruba committed
724
- [x] User registration
725
- [x] Email service
726
  - [x] SendGrid
Jan Škoruba's avatar
Jan Škoruba committed
727
728
729
730
- [x] Add API
  - [x] IdentityServer4
  - [x] Asp.Net Core Identity
  - [x] Add swagger support
Jan Škoruba's avatar
Jan Škoruba committed
731
732
- [x] Add audit logs to track changes ([#61](https://github.com/skoruba/IdentityServer4.Admin/issues/61))
- [x] Docker support ([#121](https://github.com/skoruba/IdentityServer4.Admin/issues/121))
Jan Škoruba's avatar
Jan Škoruba committed
733
734
- [x] Health Checks (Databases and IdentityServer)
- [x] Support for multiple database providers (SqlServer, Mysql, PostgreSQL)
Jan Škoruba's avatar
Jan Škoruba committed
735
- [x] Simplify Admin Identity middleware ([#430](https://github.com/skoruba/IdentityServer4.Admin/issues/430))
Jan Škoruba's avatar
Jan Škoruba committed
736
- [x] Add support for loading signing key from Azure Key Vault ([#533](https://github.com/skoruba/IdentityServer4.Admin/issues/533))
Jan Škoruba's avatar
Jan Škoruba committed
737
- [x] Protect keys for dataprotection from Azure Key Vault ([#715](https://github.com/skoruba/IdentityServer4.Admin/pull/715))
Jan Škoruba's avatar
Jan Škoruba committed
738

739
### 2.0.0
Jan Škoruba's avatar
Jan Škoruba committed
740
- [x] Update to IdentityServer4 version 4 ([#633](https://github.com/skoruba/IdentityServer4.Admin/issues/633))
Jan Škoruba's avatar
Jan Škoruba committed
741
- [x] Add support for themes ([#725](https://github.com/skoruba/IdentityServer4.Admin/issues/725))
Jan Škoruba's avatar
Jan Škoruba committed
742
- [x] Extract UI part into nuget package ([#770](https://github.com/skoruba/IdentityServer4.Admin/issues/770), [#409](https://github.com/skoruba/IdentityServer4.Admin/issues/409), [#55](https://github.com/skoruba/IdentityServer4.Admin/issues/55),), [#322](https://github.com/skoruba/IdentityServer4.Admin/issues/322), [#28](https://github.com/skoruba/IdentityServer4.Admin/issues/28), , [#133](https://github.com/skoruba/IdentityServer4.Admin/issues/133)) 
743

Jan Škoruba's avatar
Jan Škoruba committed
744
745
746
747
### 3.0.0
- [ ] Connect Admin Api to the Admin UI ([#478](https://github.com/skoruba/IdentityServer4.Admin/issues/478))

### 4.0.0:
Jan Škoruba's avatar
Jan Škoruba committed
748

Jan Škoruba's avatar
Jan Škoruba committed
749
750
- [ ] Create a project template using dotnet CLI - `dotnet new template`
  - [ ] Second template: The administration of the IdentityServer4 (without Asp.Net Core Identity) ([#79](https://github.com/skoruba/IdentityServer4.Admin/issues/79))
Jan Škoruba's avatar
Jan Škoruba committed
751
- [ ] Add windows authentication ([#479](https://github.com/skoruba/IdentityServer4.Admin/issues/479))
Jan Škoruba's avatar
Jan Škoruba committed
752

janskoruba's avatar
janskoruba committed
753
754
755

### Future:

Jan Škoruba's avatar
Jan Škoruba committed
756
757
758
- Add UI tests ([#97](https://github.com/skoruba/IdentityServer4.Admin/issues/97), [#116](https://github.com/skoruba/IdentityServer4.Admin/issues/116))
- Add more unit and integration tests :blush:
- Extend administration for another protocols
Jan Škoruba's avatar
Jan Škoruba committed
759

760

761
## Licence
762

763
This repository is licensed under the terms of the [**MIT license**](LICENSE.md).
764

765
**NOTE**: This repository uses the source code from https://github.com/IdentityServer/IdentityServer4.Quickstart.UI which is under the terms of the
766
767
[**Apache License 2.0**](https://github.com/IdentityServer/IdentityServer4.Quickstart.UI/blob/master/LICENSE).

768
## Acknowledgements
769

770
This web application is based on these projects:
771

772
- ASP.NET Core
773
- IdentityServer4.EntityFramework
774
- ASP.NET Core Identity
775
776
777
778
779
780
- XUnit
- Fluent Assertions
- Bogus
- AutoMapper
- Serilog

781
Thanks to [Tomáš Hübelbauer](https://github.com/TomasHubelbauer) for the initial code review.
782

783
Thanks to [Dominick Baier](https://github.com/leastprivilege) and [Brock Allen](https://github.com/brockallen) - the creators of IdentityServer4.
784

janskoruba's avatar
janskoruba committed
785
786
787
788
789
## Contributors

Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):

<!-- prettier-ignore-start -->
Jan Škoruba's avatar
Jan Škoruba committed
790
| [<img src="https://avatars3.githubusercontent.com/u/35664089?s=460&v=3" width="100px;"/><br /><sub> Jan Škoruba</sub>](https://github.com/skoruba) <br /> 💻 💬 📖 💡 🤔 | [<img src="https://avatars0.githubusercontent.com/u/6831144?s=460&v=3" width="100px;"/><br /><sub> Tomáš Hübelbauer</sub>](https://github.com/TomasHubelbauer) <br /> 💻 👀 📖  🤔 | [<img src="https://avatars0.githubusercontent.com/u/1004852?s=460&v=3" width="100px;"/><br /><sub>Michał Drzał </sub>](https://github.com/xmichaelx) <br />💻 👀 📖 💡 🤔 | [<img src="https://avatars0.githubusercontent.com/u/2261603?s=460&v=3" width="100px;"/><br /><sub>cerginio </sub>](https://github.com/cerginio) <br /> 💻 🐛 💡 🤔 | [<img src="https://avatars3.githubusercontent.com/u/13407080?s=460&v=3" width="100px;"/><br /><sub>Sven Dummis </sub>](https://github.com/svendu) <br /> 📖| [<img src="https://avatars1.githubusercontent.com/u/1687087?s=460&v=3" width="100px;"/><br /><sub>Seaear</sub>](https://github.com/Seaear) <br />💻 🌍|
janskoruba's avatar
janskoruba committed
791
| :---: | :---: | :---: | :---: | :---: | :---: |
Jan Škoruba's avatar
Jan Škoruba committed
792
|[<img src="https://avatars1.githubusercontent.com/u/1150473?s=460&v=3" width="118px;"/><br /><sub>Rune Antonsen </sub>](https://github.com/ruant) <br />🐛|[<img src="https://avatars1.githubusercontent.com/u/5537607?s=460&v=3" width="118px;"/><br /><sub>Sindre Njøsen </sub>](https://github.com/Sindrenj) <br />💻|[<img src="https://avatars1.githubusercontent.com/u/40323674?s=460&v=3" width="118px;"/><br /><sub>Alevtina Brown </sub>](https://github.com/alev7ina) <br />🌍|[<img src="https://avatars3.githubusercontent.com/u/29726153?s=460&v=3" width="118px;"/><br /><sub>Brice </sub>](https://github.com/Brice-xCIT) <br />💻|[<img src="https://avatars0.githubusercontent.com/u/17114154?s=460&v=3" width="118px;"/><br /><sub>TheEvilPenguin </sub>](https://github.com/TheEvilPenguin) <br />💻|[<img src="https://avatars3.githubusercontent.com/u/15545395?s=460&v=3" width="118px;"/><br /><sub>Saeed Rahmani </sub>](https://github.com/saeedrahmo) <br />🌍|
Jan Škoruba's avatar
Jan Škoruba committed
793
794
|[<img src="https://avatars0.githubusercontent.com/u/15867612?s=460&v=3" width="118px;"/><br /><sub>Andy Yu </sub>](https://github.com/Zyxious) <br />🌍|[<img src="https://avatars2.githubusercontent.com/u/51412447?s=400&v=3" width="118px;"/><br /><sub>ChrisSzabo </sub>](https://github.com/ChrisSzabo) <br />💻|[<img src="https://avatars1.githubusercontent.com/u/6860441?s=400&v=3" width="118px;"/><br /><sub>aiscrim </sub>](https://github.com/aiscrim) <br />💻 💡 🤔|[<img src="https://avatars2.githubusercontent.com/u/12528083?s=400&v=3" width="118px;"/><br /><sub>HrDahl </sub>](https://github.com/HrDahl) <br />🌍|[<img src="https://avatars0.githubusercontent.com/u/3269687?s=400&v=4" width="118px;"/><br /><sub>Andrew Godfroy </sub>](https://github.com/killerrin) <br />📖|[<img src="https://avatars0.githubusercontent.com/u/391353?s=400&v=3" width="118px;"/><br /><sub>bravecobra </sub>](https://github.com/bravecobra) <br />💻|
|[<img src="https://avatars0.githubusercontent.com/u/449663?s=400&v=3" width="118px;"/><br /><sub>Sabit Igde </sub>](https://github.com/sabitertan) <br />💻|[<img src="https://avatars2.githubusercontent.com/u/7965212?s=400&v=3" width="118px;"/><br /><sub>Rico Herlt </sub>](https://github.com/rherlt) <br />💻|[<img src="https://avatars0.githubusercontent.com/u/1926879?s=400&v=3" width="118px;"/><br /><sub>b0 </sub>](https://github.com/b0) <br />💻|[<img src="https://avatars2.githubusercontent.com/u/1941149?s=400&v=3" width="118px;"/><br /><sub>DrQwertySilence </sub>](https://github.com/DrQwertySilence) <br />🌍|[<img src="https://avatars2.githubusercontent.com/u/3332745?s=400&v=3" width="118px;"/><br /><sub>Carl Quirion </sub>](https://github.com/nlz242) <br />💻|[<img src="https://avatars2.githubusercontent.com/u/43409914?s=400&v=3" width="118px;"/><br /><sub>Aegide </sub>](https://github.com/Aegide) <br />🌍|
Jan Škoruba's avatar
Jan Škoruba committed
795
796
797
|[<img src="https://avatars0.githubusercontent.com/u/12243486?s=400&v=3" width="118px;"/><br /><sub>LobsterBandit </sub>](https://github.com/LobsterBandit) <br />💻|[<img src="https://avatars2.githubusercontent.com/u/3465794?s=400&v=3" width="118px;"/><br /><sub>Mehmet Perk </sub>](https://github.com/mperk) <br />💻|[<img src="https://avatars2.githubusercontent.com/u/46886295?s=400&v=3" width="118px;"/><br /><sub>tapmui </sub>](https://github.com/tapmui) <br />🌍|[<img src="https://avatars0.githubusercontent.com/u/12451743?s=400&v=3" width="118px;"/><br /><sub>Saeed Rahimi </sub>](https://github.com/saeedrahimi) <br />💻|[<img src="https://avatars3.githubusercontent.com/u/10605614?s=400&u=9d5f1bca5e31db4eb1975bd5043be2972aa32519&v=3" width="118px;"/><br /><sub>Joshua Williams </sub>](https://github.com/jwilliamsnephos) <br />💻|[<img src="https://avatars3.githubusercontent.com/u/12607748?s=400&u=189a0ff36baaeab34250062fe26ed13a1b78c011&v=3" width="118px;"/><br /><sub>Shengjie Yan </sub>](https://github.com/sheng-jie) <br />💻
|[<img src="https://avatars3.githubusercontent.com/u/18211871?s=400&u=a994693d3f5d7c5d5365a635af54106452bc16cb&v=3" width="118px;"/><br /><sub>Anatoliy </sub>](https://github.com/UspAN) <br />💻|[<img src="https://avatars0.githubusercontent.com/u/3778268?s=400&u=1702548638153e09cf51d2a80731c7f33ea9185f&v=3" width="118px;"/><br /><sub>Nicholas Peterson </sub>](https://github.com/nickelbob) <br />💻|[<img src="https://avatars2.githubusercontent.com/u/13870734?s=400&u=cbc2f60b6cd630a286b7e7b1c157951287f25563&v=3" width="118px;"/><br /><sub>Alec Papierniak </sub>](https://github.com/AlecPapierniak) <br />💻|[<img src="https://avatars0.githubusercontent.com/u/33623601?s=400&u=53a2bb57c68045766f11fcc5fd6d0282992fec39&v=3" width="118px;"/><br /><sub>Carl Reid </sub>](https://github.com/carlreid) <br />💻|[<img src="https://avatars1.githubusercontent.com/u/12170676?s=400&u=5053e27317b4f7f577504aa0c1c3fddc0dbcbb89&v=3" width="118px;"/><br /><sub>ViRuSTriNiTy </sub>](https://github.com/ViRuSTriNiTy) <br />💻|[<img src="https://avatars2.githubusercontent.com/u/10232683?s=400&v=3" width="118px;"/><br /><sub>J. Arturo </sub>](https://github.com/zinkpad) <br />💻
|[<img src="https://avatars1.githubusercontent.com/u/7604648?s=400&u=59a1ce466533aadb4c02944805c62957935b0ba9&v=3" width="118px;"/><br /><sub>Weihan Li </sub>](https://github.com/WeihanLi) <br />💻|[<img src="https://avatars3.githubusercontent.com/u/4563019?s=400&v=3" width="118px;"/><br /><sub>Saša Tančev </sub>](https://github.com/tancevsasa) <br />💻|[<img src="https://avatars1.githubusercontent.com/u/12811343?s=400&u=a417cca5ea7e206ecd979d2f623502bc766a504c&v=3" width="118px;"/><br /><sub>cuibty </sub>](https://github.com/cuibty) <br />💻|[<img src="https://avatars3.githubusercontent.com/u/17126867?s=400&u=387bb1de303c993b683cd1335f57a96e1671be45&v=3" width="118px;"/><br /><sub>Simo Paasisalo </sub>](https://github.com/spaasis) <br />💻|[<img src="https://avatars1.githubusercontent.com/u/10352866?s=400&v=3" width="118px;"/><br /><sub>klyse </sub>](https://github.com/klyse) <br />💻|[<img src="https://avatars0.githubusercontent.com/u/19854428?s=400&u=d0f37a7f51e8eaac4da754c9f8deae714e03da65&v=3" width="118px;"/><br /><sub>Martinus Suherman </sub>](https://github.com/martinussuherman) <br />💻
798
|[<img src="https://avatars1.githubusercontent.com/u/540241?s=400&v=3" width="118px;"/><br /><sub>Pavel Usachev </sub>](https://github.com/pavel-usachev) <br />💻|[<img src="https://avatars2.githubusercontent.com/u/64419131?s=400&u=e18b51ba9a0c1c2bf69ed86fba2251b44c1c3136&v=3" width="118px;"/><br /><sub>LabTrans - STIGeo </sub>](https://github.com/labtrans-ufsc) <br />🌍|[<img src="https://avatars1.githubusercontent.com/u/7376668?s=400&u=93af8ae5f2980c172f2ca13b5380f20a50053866&v=4" width="118px;"/><br /><sub>Valentin LECERF </sub>](https://github.com/ioxFR) <br />💻|[<img src="https://avatars0.githubusercontent.com/u/9968151?s=400&u=c210e5d589ec6433069105d1420bf3d8cb6265f2&v=4" width="118px;"/><br /><sub>Thomas Aunvik </sub>](https://github.com/ThomasAunvik) <br />🐛|[<img src="https://avatars1.githubusercontent.com/u/661509?s=400&u=16eeaa522ebe0f92ef2851b7bbf721f349b815b5&v=4" width="118px;"/><br /><sub>Sebastian Gebhardt </sub>](https://github.com/sgebhardt) <br />🐛
janskoruba's avatar
janskoruba committed
799
800
801
802
803
<!-- prettier-ignore-end -->

This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification.
Contributions of any kind are welcome!

804
## Contact and Suggestion
805

806
I am happy to share my attempt of the implementation of the administration for IdentityServer4 and ASP.NET Core Identity.
807

808
Any feedback is welcome - feel free to create an issue or send me an email - [jan@skoruba.com](mailto:jan@skoruba.com). Thank you :blush:
Jan Škoruba's avatar
Jan Škoruba committed
809
810
811
812
813

## Support and Donation 🕊️

If you like my work, you can support me by donation. 👍 

Jan Škoruba's avatar
Jan Škoruba committed
814
### Paypal
Jan Škoruba's avatar
Jan Škoruba committed
815
https://www.paypal.me/skoruba
Jan Škoruba's avatar
Jan Škoruba committed
816
817
818

### Patreon
https://www.patreon.com/skoruba