1

我有一个应用程序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() {
  }

}
4

1 回答 1

3

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

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

我们的解决方案是在调用 oauthService 的登录流程之前捕获会话存储中的当前 URL ,然后在登录完成后使用该存储的 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,如果有,我们重定向到它。

从流程的角度来看,它是这样工作的:

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

我知道你在想什么:“哇!这是一大堆重定向”......你是对的 - 但它实际上速度惊人。

于 2020-02-26T18:04:18.877 回答