Reputation: 71
I have an application https://app.example.com (home) and I have deep link working https://app.example.com/function/123 (direct_link) and navigating directly to direct_link works if the user is already authenticated.
We are using angular-oauth2-oidc and I can't find a way to initiate authentication and bring the user back to direct_link post authentication, it always returns to the home and I have paste the direct_link again in the address bar.
import { AuthConfig } from 'angular-oauth2-oidc';
export const authConfig: AuthConfig = {
// Url of the Identity Provider
issuer: 'https://cognito-idp.<region>.amazonaws.com/<id>',
// URL of the SPA to redirect the user to after login
redirectUri: window.location.origin,
// The SPA's id. The SPA is registerd with this id at the auth-server
clientId: '<id>',
// set the scope for the permissions the client should request
// The first three are defined by OIDC. The 4th is a usecase-specific one
scope: 'openid',
strictDiscoveryDocumentValidation: false,
responseType:'token',
oidc: true
}
export class AuthGuardService implements CanActivate{
constructor(private oauthService: OAuthService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
if (this.oauthService.hasValidIdToken()) {
return true;
}
this.router.navigate(['home'], { queryParams: { returnUrl: state.url }});
return false;
}
}
export class HomeComponent implements OnInit {
returnUrl:string;
constructor(
private oauthService: OAuthService,
private router: Router) { }
login() {
this.oauthService.redirectUri = window.location.origin + this.returnUrl;
this.oauthService.initImplicitFlow();
}
logout() {
this.oauthService.logOut();
}
ngOnInit() {
}
}
Upvotes: 2
Views: 4376
Reputation: 3018
We're using the angular-oauth2-oidc
library with Azure AD B2C as well, and had a similar requirement.
Our deep linking requirements prevented us from using the redirectUri as the URL was dynamic (ie: product IDs included in the URL), and Azure AD B2C doesn't support wildcard redirectUris.
Our solution was to capture the current URL in session storage prior to invoking the oauthService's login flow, and then using that stored URL after the login is complete to redirect to the original URL, so for example:
export class AuthenticationService {
constructor(private storageService: SessionStorageService, private oauthService: OAuthService) { }
...
isLoggedIn(): boolean {
return this.oauthService.hasValidAccessToken();
}
...
login(): void {
this.oauthService.tryLoginImplicitFlow().then(success => {
if (!success) {
this.storageService.set('requestedUrl', location.pathname + location.search);
this.oauthService.initLoginFlow();
} else {
let requestedUrl = this.storageService.get('requestedUrl');
if (requestedUrl) {
sessionStorage.removeItem('requestedUrl');
location.replace( location.origin + requestedUrl);
}
}
This login method is part of our own auth service which mostly just delegates over to the OAuthService provided in the angular-oauth2-oidc package.
In our login method, we first attempt the tryLoginImplicitFlow()
to see if the user has been authenticated.
If the tryLoginImplicitFlow()
returns false, it means they aren't logged in, and we capture their current URL and shove it into session storage.
If it returns true, means they are authenticated, so we check to see if there is a stored URL, and if so, we redirect to it.
From a flow point of view, it works like this:
isLoggedIn()
method of the auth service, and if not logged in, invokes the login()
methodtryLoginImplicitFlow()
(which does things like checking for a state hash in the URL), and it fails, so the method calls initLoginFlow()
isLoggedIn()
, which is still false, so calls the login()
methodtryLoginImplicitFlow()
(which picks up the fact that the user was just redirected from the B2C, and grabs the tokens) and it succeeds. I know what you are thinking: "WOW! That's a whole lot of re-directs" ...and you are right - but it actually is surprisingly quick.
Upvotes: 2