An authentication and authorization example with two identity servers, an Angular client and a resource api. The two servers are based in OpenIddict.
There are several identity servers, some of them being made specifically for the .NET ecosystem, but the language used doesn't matter since the identity server should be an independent server for an SSO (Single Sign On) approach.
If there is a chance the identity server needs to be customized it is safer to use a solution based on the stack you are comfortable with. For .NET, the most popular identity solutions are AAD (Azure Active Directory), Identity Server and OpenIddict.
- AAD: It's hosted (SaaS) and free for the first 50,000 active users. The caveat is that the solution is dependent on Microsoft Azure.
- Identity Server: This is the most popular identity solution in .NET. It is no more free after 4 clients in an enterprise environment.
- OpenIddict: It's a library used to create identity servers. It's very popular since it's free. The OrchardCore (a SaaS application framework and CMS) uses it.
This repository provides sample solutions using the OpenIddict library for the following reasons:
- Not tied to a cloud provider, host the samples where you want.
- It's free, whatever the number of clients and users you need to support.
- It's highly customizable.
- It's .NET ecosytem friendly.
The solution has 4 projects:
It's an identity server based on the Orchard Core modular framework and the OpenId module already configured. The module uses OpenIddict-core and as the author recommends is a good way to configure a simple and easy identity server.
When you run the project, you can select the Identity recipe, which will load the identity.recipe.json
containing all the necessary default configuration for an identity server. Once the setup is done, the /admin
url gives you access to the dashboard.
It's a custom identity server using OpenIddict-core and the Velusia sample
It uses the .NET self-contained UI for Identity with automatically generated views. login and registry are customized using generated views in the Areas folder.
It's a simple Angular app to test how to login and logout with a code flow + PKCE and silent refresh approach. For authentication and authorization it uses the angular-oauth2-oidc library by Manfred Steyer.
The project has two guards that only let the principal-feature and optional-feature modules be lazy loaded if the user is authenticated.
The principal-feature module will redirect to the login page in the identity server if the user is not authenticated.
A button will be shown if the user has an administrator role. For this, a hasRole structural directive is used.
The optional-feature module will redirect to a noauth page if the user is not authenticated.
When the user is authenticated a request to the example api will be made in order to retrieve the weather forecast. The request will be returned with the response only if the user id contains the forecast role
Follow these steps to setup HTTPS in development:
- Execute the CreateAngularDevelopmentCertificate to generate the certificate files (dev_localhost.key, dev_localhost.pem, dev_localhost.pfx).
- Copy the generated files to the ssl folder at root level in angular-openid project
- Add the ssl configuration to the angular.json file
"serve": { "builder": "@angular-devkit/build-angular:dev-server", "configurations": { "production": { "browserTarget": "angular-openid:build:production" }, "development": { "browserTarget": "angular-openid:build:development", + "ssl": true, + "sslKey": "ssl/dev_localhost.key", + "sslCert": "ssl/dev_localhost.pem" } }, "defaultConfiguration": "development" },
- Add a script to package.json to have the posibility of execute the app without ssl
"start": "ng serve --ssl=false --open", "start-with-ssl": "ng serve --open",
- Modify the CORS configuration in the Startup.cs file in OrchardOpenId project
services.AddCors(options => { options.AddPolicy(name: CORS_POLICY, builder => { builder.WithOrigins("https://localhost:4200"); builder.AllowAnyMethod(); builder.AllowAnyHeader(); }); });
- In the Orchard Core dashboard (
/admin
), open the OpenID Connect menu, choose Applications and edit angularClient app. Update the Redirect and Post Logout Redirect URIs.
The sample API is configured to work with the two identity server projects.
A JWT bearer schema is used with OrchardOpenId. For _OpendIdServer_it's the OpenIddict schema which is used.
In my opinion the OpenIddict schema is a better solution because it uses introspection to secure the connection which is the recommeded approach with the OpenIddict library.
A forecastPolicy is used to authorize the user if forecast is a contained scope.
It's a small console program that generates the certificate files to secure the Angular SPA application. It follows the DamienBod approach
- Open a terminal with OpenIdServer or OrchardServer root folder.
- Run
dotnet watch run
- Open a terminal with ExampleApi root folder.
- Run
dotnet watch run
- Follow the steps to generate the certificates
- Open a terminal with angular-openId root folder.
- Run
npm install
- Run
npm run start-with-ssl
- OpenID Connect Flows
- OAuth is Not User Authorization
- Identity vs Permissions: Identity is universal, whereas permissions are application specific
- SPAs are dead
- SPA necromancy
- Security in Angular series
- Implementing openId code flow with PKCE using OpenIdDict and angular
- angular-oauth2-oidc
- Example angular-oauth2-oidc with AuthGuard