Token Based Security: Angular Applications, Part 2
In the previous post on the topic of Token Based Security, we created an API endpoint and protected it (using Authorize attribute) with IdentityServer. Then, we set up a simple Angular application with an AuthService to use oidc-client library. We also created few angular components at the end of the previous post, as well as two buttons for login/logout purposes in appComponent, then wired the following method with click events:
Today, we will continue from the previous post and complete the login/logout process. We will see how the OIDC client library makes it very easy to implement the complex redirect flows out of the box.
So, let’s start and complete the logout method code first:
As you may notice, from AppComponent logout() method, we are simply delegating the work to authService, which will use OIDC Client library to make this happen. Let’s look at that next.
Login/Logout Process Completion
From AppComponent UI buttons, we are calling methods in AuthService. Here again, we are simply calling appropriate methods on userManager object and that will do all the heavy lifting for us:
Notice, the word Redirect in both methods. Yes, this code will redirect the user to IDP, where he/she will be logged in/logged out on the IDP level, and once that completes, the user is redirected back to the angular application.
Handling Redirect Callbacks
When the user is redirected back to the angular application, we need to add some more angular code to let the angular application handle the login/logout completion process.
For that purpose, I created the following two methods in AuthService.ts:
The code is self-explanatory: we are calling appropriate methods on userManager object to handle the Redirect Callbacks. So completeLogin will be called (using signin-callback.component, as we will see later in this post) at the end of the login process (after the user enters username/password on IDP). This method is also raising notification about user login.
Similar to that, completeLogout will be called at end of the logout process (using signout-callback.component, which we will see next). This code is also clearing up user property on authService.
Sign In/Sign Out Callback Components
Here are the components to handle Sign in/Sign out callbacks. IDP will redirect users to these components as part of the authorization flow:
The following code shows SigninCallback component:
As you can see, we are calling the completeLogin() method, which we created earlier in the AuthService, and once completed, we are navigating the user to root URL (also removing the signinRedirect from the back navigation stack of the browser). Notice, for the template, it is just an empty div.
Next, let’s see the code for the SignoutCallback component:
This is very similar to the SigninCallback component, an empty div, and completeLogout method call.
At this point, our login/logout functionality is in place. Now, let’s configure STS to allow angular client by adding client information as shown next.
Configure IDP With Angular Client Information
Here is the client setup (Config.cs) in the IDP:
We have discussed all of this information in the earlier posts of this series. Notice with the RedirectUris and PostLogoutRedirectUris, we need to create these routes in our angular app and wire sign in and sign out callback components we created earlier so that redirects can happen as planned.
Angular Routes for RedirectURIs
Let’s update the routing information in the angular application:
Notice that paths are set up as configured in IDP and the components we created earlier for the login/logout completion process. This is how they all wired up and work together to implement the flow.
Test the Application
Let’s test the application, by running .NET Core projects (IDP, API etc.) and Angular application. If we navigate to the root URI of the angular app, the following screen appears:
Now, click the login button and we are redirected to IDP (notice the address-bar):
Here, enter the Username and Password (you can use TestUsers we configured in earlier posts) and click the Login button. We are redirected to Angular application as shown below:
So, our login/logout flow is working as expected. If we open up the browser window (session storage), we can see that the following user information is available:
Now, when I click the Logout button, the user is redirected to IDP for logout purposes:
Authorizing Calls to API
We are able to log in/log out successfully. Let’s log in again and try to access the Products page. You will notice, we are still not able to see the products data, and console windows shows us a 401 error:
This happens even though we have access-token from IDP, we have not yet passed it as an HTTP header to API when making HTTP calls. Typically this involves introducing an HTTP Interceptor. We will cover this in the next post, along with some other enhancements.
You can download the source code from this git repository. We will continue in the next post. If you have some comments or questions, let me know. Until next time, Happy Coding.
Credit: Source link