/openiddict-with-angular

An authentication and authorization example with OpenIdDict as a identity server and an Angular client

Primary LanguageC#MIT LicenseMIT

OpenIddict with Angular

An authentication and authorization example with two identity servers, an Angular client and a resource api. The two servers are based in OpenIddict.

Why use OpenIddict for the identity servers?

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.

Structure

The solution has 4 projects:

OrchardOpenId

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.

OpenIdServer

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.

AngularOpenId

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.

principal-feature module

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.

optional-feature module

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

ssl

Follow these steps to setup HTTPS in development:

  1. Execute the CreateAngularDevelopmentCertificate to generate the certificate files (dev_localhost.key, dev_localhost.pem, dev_localhost.pfx).
  2. Copy the generated files to the ssl folder at root level in angular-openid project
  3. 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"
     },
  4. 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",
  5. 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();
                             });
     });
  6. 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.

Example API

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.

CreateAngularDevelopmentCertificate

It's a small console program that generates the certificate files to secure the Angular SPA application. It follows the DamienBod approach

Run the example

  1. Open a terminal with OpenIdServer or OrchardServer root folder.
  2. Run dotnet watch run
  3. Open a terminal with ExampleApi root folder.
  4. Run dotnet watch run
  5. Follow the steps to generate the certificates
  6. Open a terminal with angular-openId root folder.
  7. Run npm install
  8. Run npm run start-with-ssl

Links