I'm working with an angular 8 SPA, and I'm trying to use the oidc-client-js library to handle the user authentication. The identity provider is implemented by using identity server 4.
Our desired user experience is the following: when the SPA is loaded in the browser, without requiring any kind of user interaction, the login flow is started. Put in other words, we would like to trigger the login flow automatically and to avoid the need for an explicit login button in the first view of the application.
The AppComponent
is the first component loaded in our application and it has the following init method:
ngOnInit() {
this.authService.login();
}
The auth service login is doing the following:
login() {
return this.userManager.signinRedirect();
}
By doing so we are able to successfully redirect the user to the identity server login form. After the login form is submitted identity server redirects the user back to the SPA application on the configured redirect uri (/signin-callback
).
At that point we would like to load a component able to complete the login flow. This component should call the following method of the auth service inside of its ngOnInit
method:
completeLogin() {
return this.userManager.signinRedirectCallback().then(user => {
console.log("Login has been completed.", user);
return user;
});
}
Unfortunately this approach does not work, because when identity server redirects back to the SPA application (after the login form is submitted), the AppComponent
is loaded in the browser and the login flow is started once again and an infinite redirect loop begins, until the browser finally blows up.
Is there a way for us to make this work ?
Additional notes:
this.userManager.signinRedirect()
when the application bootstraps in the browser; we should find a way to avoid the call if the login flow has already been started and the application is being loaded due to the redirect after the user logs in at the identity server level. Is there a robust way to do so ?Update 15th September 2020
The simplest way that I've found to manage this issue is doing the sigin redirect callback inside of a static HTML page, which is not part of the angular application. You can find an example in the sample folder of the oidc client js repository
REQUIREMENTS
There are 2 main aspects to making this work. It is a design pattern really, and can be implemented in any language:
You'll have to figure out the Angular specifics, since I don't know that framework. I hope this gives you a few useful pointers though.
RESOURCES OF MINE
The code below uses plain Typescript, and you'd need to translate that to your preferred Angular syntax.
Code to get an access token. Note that the getAccessToken function triggers the login redirect.
Code to load the page. Note the call to handleLoginResponse as part of page load
Code to deal with access token expiry. Note that on expiry a new login redirect is triggered.
Blog Post with more details on initial OIDC client integration
My blog also has some more advanced samples if useful, on stuff like silent token renewal - and a Quick Start Page where you can run an online React sample with the above behaviour.