Secure your Aurelia app with IdentityServer

Hello and welcome! Today I want to describe how we can secure our Aurelia applications with the help of an Authorization Server, in this case, IdentityServer4. I hope you enjoy 🙂 the topic and find it fruitful for your applications. The topic is twofold, how to run IdentityServer4, and how to configure Aurelia to be able to communicate with our ISP( Identity Service Provider ). We are using one of the awesome plugins of Aurelia to do so; aurelia-open-id-connect, many thanks to Mr. Shaun Luttin for all his efforts. You can download the source code of this post from my Github repository.

Identity Server

The identity server is an Identity Service Provider written for .Net developers. It provides solutions such as single sign-on, identity management, API security and so on for your modern applications. As they say: “The Identity and Access Control solution that works for you”. Let’s begin. Firstly, you need to create an empty Asp.Net Core application by running,

dotnet new web --name Aurelia.IdentityServer

Then you need to add NuGet packages to your project.

dotnet add package IdentityServer4 --version 2.2.0

That being installed, you are ready to configure your own ISP using Identity Server. We need to declare TestUsers, Clients,IdentityResources, and ApiResource. To do so, define a class named IdentityConfiguration and copy the following code:

404: Not Found

There are several things you need to know in the above code snippet, first, we declared the resources we want to protect against unauthorized users, that includes both Identity Resourcesand Api Resources.These lines define those resources. Next, we should define users, in this demo, they are TestUsers, and then the most important part is to specify which clients are requesting for authentication. Before getting into details of the clients it is worthy to note that the user has a SubjectId which must be unique in this server. Clients have so many important properties, let’s check them one by one:

ClientId: This is the client’s identifier which must be unique.

ClientName: This is a human-readable name for the client.

AllowedGrantTypes: Indicates that how this client can interact with the Identity Server. There are several grant types defined in OpenID Connect and OAuth2 specs, of which we use Implicit that is optimized for browser-based applications.

RedirectUris: Where you want the identity server to return the tokens after a successful login.

PostLogoutRedirectUris: Allowed URIs after logout to return to.

AllowedCorsOrigins: If your client is on a different domain than your ISP, then you must specify this property to prevent Cross-Origin Attacks.

AllowedScopes: List of resources, identity and API, that this client is allowed to request. The user can also at the consent page restrict them by checking or unchecking these resources.

After setting those properties properly, we need to configure the IdentityServer4 in our applications, first of all, you need to add the following code snippet to your ConfigureServices method of your Startup class.

We have added a developer signing certificate, and then we have added TestUsers, Clients and Resources defined earlier on. Next step is to add the Authentication middleware to the pipeline, go to your Configure method and paste app.UseIdentityServer() just before the mvc middleware.

404: Not Found

So far so good. One thing is left, and that is to add basic user interfaces for your Identity Server, to do so use the guidance from their official GitHub repository. Now, in order to run the Identity Server execute dotnet run --project Aurelia.IdentityServer or hit F5. You must be able to see the Home page of the project click on Discovery Link to see more details.

Aurelia Side

For this part you have two options, using oidc-client-jsoraurelia-open-id-connect plugin, the latter is a wrapper over the former; thus, while you can use oidc-client-js, I recommend not to do so, because then you have to write a bunch of code to match that library with Aurelia routing system. Well, now we must create another project to handle our client-side application, Aurelia.Client, it is up to you to choose between your options, CLI or etc. After you created the project at the required plugins:

npm install aurelia-open-id-connect --save

Now it’s time to configure the plugin, there are three default configurations hereandhere forAuth0,Azure Active Directory, and Identity Server. Just copy the one for Identity Server to your project and we will change some of the most important properties that will directly affect our project.

404: Not Found

There are two parts you must configure, UserManagerSettings, and OpenIdConncetConfiguration. for the latter you must set where the user should be redirected when login, logout are successfully done, or an unauthorized access detected, these three lines are for that purpose. For UserManagerSettings , you must set:

response_type: Indicates what kind of tokens you expect from the server, and consequently which sort of scopes you can request later on. id_token for identity resources and token for API resources.

scope: This property is a subset of AllowedScopes defined on the server for this client; if response_type does not contain token you cannot request for API resource, you will get an error indicating invalid_scope.

That being set, you are ready to define you routes, use the usual means of declaring routes in Aurelia, the only part you should know about is that henceforth you can add roles property to the settings part of each route; it takes an array of OpenIdConnectRoles,Evryone, the default value, Anonymous, and Authenticated; each of which will influence the routing in one way or another:

Everyone: The name stands for itself, nothing is checked and all users can navigate to this rout.

Anonymous: This is a little bit tricky, routes having this role can be seen when nouser is logged in.

Authenticated: Only logged in users can navigate to this page.

PS: There is a default value converter, openIdConnectNavigationFilter, with the aurelia-open-id-connectplugin, that can be applied on router.navigationproperty to filter visible routes.

404: Not Found

When setting the roleswith Anonymous You can still navigate to route by changing the URL, however, it will not be shown on your navigation menu. The routing code for this sample is as the following:

404: Not Found

So far so good, it’s time to know how to log in and log out of the system; usingaurelia-open-id-connect you can inject an instance of OpenIdConnect and use its login andlogout methods, as easy as that.

Well, now that we have logged into the system and have an access_token , we should be able to call secure APIs; that can be done by adding an Authorizationheader with a Bearer token to our HTTP requests, I used aureia-http-clientplugin to call my REST endpoints.

404: Not Found

An instance of HttpClient injected, and then configured to have the access_token in the header of the requests, so APIs secured with Authorize attribute can now be accessible.

I hope you find this article useful and will be more than happy to hear from you guys, please do not hesitate to get in touch via my Github or Twitter. Have a great day and enjoy coding. 🙂