使用OIDC进行角度深层链接导航

时间:2020-01-18 17:41:33

标签: angularjs angular-oauth2-oidc

我有一个应用程序https://app.example.com(家庭),并且有深层链接工作https://app.example.com/function/123(direct_link),如果用户已经通过身份验证,则可以直接导航到direct_link。

我们使用的是angular-oauth2-oidc,我找不到启动身份验证并将用户带回direct_link后身份验证的方法,它总是返回家中,并且我再次将direct_link粘贴到地址栏中。

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() {
  }

}

1 个答案:

答案 0 :(得分:3)

我们还将angular-oauth2-oidc库与Azure AD B2C一起使用,并且有类似的要求。

我们的深层链接要求使我们无法使用redirectUri,因为URL是动态的(即URL中包含产品ID),并且Azure AD B2C不支持通配符redirectUris。

我们的解决方案是在会话存储之前中捕获当前URL,以调用oauthService的登录流程,然后在登录完成后使用该存储的URL重定向到原始URL,例如:

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);
                }
            }

此登录方法是我们自己的身份验证服务的一部分,该服务主要只是委托给angular-oauth2-oidc软件包中提供的OAuthService。

在我们的登录方法中,我们首先尝试tryLoginImplicitFlow()来查看用户是否已通过身份验证。

如果tryLoginImplicitFlow()返回false,则表示它们尚未登录,我们将捕获其当前URL并将其推送到会话存储中。

如果返回true,则表示它们已通过身份验证,因此我们检查是否存在存储的URL,如果存在,则将其重定向到该URL。

从流程的角度来看,它的工作方式如下:

  1. 用户尝试访问深层链接:/ site / products / 1234
  2. 应用程序组件(未显示)检查auth服务的isLoggedIn()方法,如果未登录,则调用login()方法
  3. 登录方法尝试使用tryLoginImplicitFlow()(执行类似检查URL中的状态哈希的操作),但失败,因此该方法调用initLoginFlow()
  4. 用户被重定向到某些xxxx.b2clogin.com域并登录; B2C将用户重定向到我们的Web应用程序的根目录
  5. 应用程序组件再次启动并检查isLoggedIn()(仍然为false),因此调用login()方法
  6. Login方法尝试使用tryLoginImplicitFlow()(它发现用户刚刚从B2C重定向,并获取了令牌)并成功。
  7. 登录方法检查会话存储中是否有最初请求的URL,在那里找到它,并将用户重定向到该原始页面。

我知道您在想什么:“哇!这是很多重定向”……您说的很对-但这实际上出奇地快。