ADFS + Angular + ASP.NET Core API

Hello everyone!

In this article I’m going to talk about ADFS + Angular + ASP.NET Core API.

I needed to do these 3 things work together and I had a huge difficulty to find content about doing that. When it had information about Angular, it did not have about ASP.NET Core API, or it was about ASP.NET MVC projects. Oh, it was sad!

But now, I have those 3 things working together and I’d like to explain some couple things I learned and also provide a project that may help someone else.

So, let’s get started!

Part 01: ADFS

I’m not going to focus on configuring your application in ADFS, I think you can find enough content about it on internet.

But, you need to know some things:

Because of the frontend will be decoupled of your backend, you need to use an approach of JWT + OAUTH/OIDC, where you’ll have an access token. So basically the “authentication happens” in the frontend and the backend checks if the request is valid, or in other words, if the request has a valid access token in its header.

This is called the Implicit Flow and, based in what I researched in that time, this is just allowed as of ADFS 4.

Besides that, it’s good to have in mind that because it is a SPA application, it there is a specific way to configure it on ADFS, something like “native application” or similar to that. Well, I guess you can find it on Google and after that you’ll have a client ID and other informations.

Part 02: Angular

I won’t focus on creating an Angular application. I imagine you know how to do that. If not, check these links:

https://angular.io/
https://cli.angular.io/

I have a project where you can base yourself: https://github.com/gabrielfbarros/aspnetcore-angular-adfs/tree/master/front.

You may imagine that I did not focus in a great structure to the application!

To make the integration with ADFS easier I looked for a lib that could help me with that. I found few ones, but the one that seemed to be more used and worked for me was “angular-oauth2-oidc”. You can check it here: https://www.npmjs.com/package/angular-oauth2-oidc

In my example above, basically I created an Angular 5 application via CLI, and followed what the lib tutorial says. I detail it below:

- You need to add the lib in your package.json file. Look, if you need support for Angular < 6 (4.3 to 5.x) you can download the former version 3.1.4 (npm i angular-oauth2-oidc@^3 --save). If you’re working with Angular 6+, you can use latest version. Check the tutorial in npm website.

- In the app.component, create a constructor and inside it, you configure the OAuthService from the lib:

You noticed that the redirectUri I just set to the base url of my application. This configuration should be set with the redirect url you configured in ADFS, because after authenticating the user, the ADFS will redirect to that configured url.

The clientId is the one generated by ADFS for your application. It is something like a “guid” value.

The loginUrl is the url to the authorize endpoint of ADFS. Basically you need to change “YOUR_SERVER” by the path to your ADFS server, in the example above.

The issuer is basically the url to the server that holds ADFS, finishing only with “/adfs”, but in my case, this path was different from the previous path loginUrl. I don’t know exactly why. After a lot of tests, I found out that you have an endpoint that provides you several other informations: https://YOUR_SERVER/adfs/.well-known/openid-configuration, and one of the informations in that was the issuer, that I just used in my Angular configuration.

Well that was basically all configuration I needed to the lib “see” my ADFS.

- In the app.module you need to import “OAuthModule.forRoot()” in the imports declaration.

- In my example I created a home.component that has a button that sends a GET request to an API, and the API is guarded by security policies. So, I created my.service, where a created the following function:

Look the “this.getAuthHeader()” call. You can check that my.service extends a base.service, where I created that function:

Well, here is where the magic happens! Here I use “this.oauthService.getAccessToken()” to get the access token and I put it in the header as an Authorization Bearer property.

- Besides that, I created an app.routes and an auth-guard.service. In the guard service I check if it there is a valid access token in the session storage. If not or if it fails to log the user in, it will init the implicit flow, that will open the login page of ADFS:

So using this guard in my routes, I guarantee that the user is authenticated:

{ path: ‘home’, component: HomeComponent, canActivate: [AuthGuardService] }

- And last thing but not less important, in my home.component it there is a logout function:

Well, you can see that it’s very simple, but only after you know all this!

In the home page, after you log in, you’ll see the access token generated by ADFS and that will be sent to the API. You can check it in https://jwt.io/, check what informations is ADFS returning to you. In my case we were able to get several important informations to the application from ADFS.

Part 03: ASP.NET Core API

For the backend, I also have a project where you can base yourself: https://github.com/gabrielfbarros/aspnetcore-angular-adfs/tree/master/back.

You also may imagine that I did not focus in a great structure to the application!

In my example above, basically I created an ASP.NET Core 2.0 API, from the template of Visual Studio.

The main configuration occurs in the class Startup.cs. As I mentioned before, the API will receive requests and for each request it needs to check if a valid access token is provided, otherwise the API should return code 401 (Unauthorized).

To make sure that any request are going to check the access token, you need to add add a filter to your MVC pipeline. In the ConfigureServices method:

Look that I defined a name to my authentication scheme: “Bearer”. And now we need to configure the authentication as JWT. Still in the ConfigureServices method:

You see that Authority is the issuer of Angular application.

The Audience was my Achilles’ heel! I took some time to found out what information should I use here. You can notice that the value has “microsoft:identityserver:” and the client id. Well, this information I got from the access token, looking it in https://jwt.io/. It is the “aud” value in the token.

The ValidIssuer is the services/trust endpoint of ADFS.

In the Events property, you can configure OnTokenValidated and add Claims to the identity or you can do any other thing that is necessary after the token is validated.

And not mandatory, but very useful is to configure policies, that is a new feature of ASP.NET Core:

Here we create a policy and says which Claim is necessary to satisfy the policy. Look that the claim is the same I add to the user in the OnTokenValidated above, so the user will have access to that policy.

And to the policy makes sense, we can use it in our Controller:

[Authorize(Policy = “Given Policy”)]
public class HomeController : Controller

So, with all this configuration, any request, for any controller, it will check against your ADFS if it there is a valid access token in the header. And to this HomeController specifically, it will check if the user complies with the policy we have created.

And that’s it! It doesn’t look so hard now, but I took some time to see some things.

If you have other approaches to this combination of technologies, please let us know, leave your notes!

I hope I could help you!

Bye!

Gabriel Faraday de Barros

Written by

I'm a software developer that likes process improvement and Agile

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade