4

我有一个受 Identity Aware Proxy (IAP) 保护的 Angular 应用程序。我正在尝试将 Firebase 添加到此应用中,以便将 Firestore 用于使用 AngularFire 的组件。我不想让用户登录两次,所以我想到了使用 IAP 向 Firebase 进行身份验证。

我试过了:

  • 让 GCP 发挥它的魔力,看看用户是否会自动插入 Firebase Auth 模块 - 不是。

  • GCP_IAAP_AUTH_TOKEN我已经尝试在cookie中使用您从 IAP 获得的令牌,signInWithCustomToken方法是 - 不起作用,令牌无效。

  • getRedirectResult在通过 IAP 登录后尝试使用它是否被注入到那里 - 它不是。

我花了几天的时间试图让这个工作,我也让一个同事看过它,但这似乎是不可能的。现在,作为最后的手段,我在这里写信看看是否有人知道这是否可能。

如果没有,我将不得不建议团队切换身份验证方法并摆脱 IAP,但我宁愿保留它。


更多信息:

环境: App Engine 上的 NodeJS 10 灵活

角度版本: 7.xx

AngularFire 版本: 5.2.3

注意:我没有后端,因为我想单独使用这个组件,如果需要的话,最多可以使用几个 Cloud Functions。我正在尝试将 Firestore 用作“后端”。

4

3 回答 3

4

我设法使用为 Cloud IAP 进行的身份验证中的 id 令牌自动在 Firebase 上进行身份验证。

我只需要使用Google API Client Library for JavaScript

1) 将 Google JS 库添加到您的页面,即

<script src="https://apis.google.com/js/platform.js"></script>

2)加载OAuth2库,gapi.auth2

gapi.load('client:auth2', callback)
gapi.auth2.init()

3) 从以下位置获取 id 令牌GoogleAuth

const auth = gapi.auth2.getAuthInstance() 
const token = auth.currentUser.get().getAuthResponse().id_token;

4) 将令牌传递给GoogleAuthProvider 的凭据

const credential = firebase.auth.GoogleAuthProvider.credential(token);

5) 使用凭据在 Firebase 上进行身份验证

firebase.auth().signInAndRetrieveDataWithCredential(credential)

将所有东西放在一个 Angular 组件上,这就是我所拥有的(包括注销方法)

import { Component, isDevMode, OnInit } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import { Router } from '@angular/router';
import * as firebase from 'firebase/app';

// TODO: move this all to some global state logic

@Component({
  selector: 'app-sign-in-page',
  templateUrl: './sign-in-page.component.html',
  styleUrls: ['./sign-in-page.component.scss']
})
export class SignInPageComponent implements OnInit {
  GoogleAuth?: gapi.auth2.GoogleAuth = null;

  constructor(public auth: AngularFireAuth, private router: Router) { }

  async ngOnInit(): Promise<void> {
    // The build is restricted by Cloud IAP on non-local environments. Google
    // API Client is used to take the id token from IAP's authentication and
    // auto authenticate Firebase.
    //
    // GAPI auth: https://developers.google.com/identity/sign-in/web/reference#gapiauth2authorizeparams-callback
    // GoogleAuthProvider: https://firebase.google.com/docs/reference/js/firebase.auth.GoogleAuthProvider

    if (isDevMode()) return;

    await this.loadGapiAuth();

    this.GoogleAuth = gapi.auth2.getAuthInstance();

    // Prevents a reauthentication and a redirect from `/signout` to `/dashboard` route
    if (this.GoogleAuth && this.router.url === "/signin") {
      const token = this.GoogleAuth.currentUser.get().getAuthResponse().id_token;
      const credential = firebase.auth.GoogleAuthProvider.credential(token);

      this.auth.onAuthStateChanged((user) => {
        if (user) this.router.navigate(["/dashboard"]);
      });

      this.auth.signInAndRetrieveDataWithCredential(credential)
    }
  }

  // Sign in button, which calls this method, should only be displayed for local
  // environment where Cloud IAP isn't setup
  login() {
    this.auth.useDeviceLanguage();
    const provider = new firebase.auth.GoogleAuthProvider();
    provider.addScope("profile");
    provider.addScope("email");
    this.auth.signInWithRedirect(provider);
  }

  logout() {
    this.auth.signOut();

    if (this.GoogleAuth) {
      // It isn't a real sign out, since there's no way yet to sign out user from IAP
      // https://issuetracker.google.com/issues/69698275

      // Clearing the cookie does not change the fact that the user is still
      // logged into Google Accounts. When the user goes to your website again,
      // opens a new tab, etc. The user is still authenticated with Google and
      // therefore is still authenticated with Google IAP.
      window.location.href = "/?gcp-iap-mode=CLEAR_LOGIN_COOKIE"
    }
  }

  private async loadGapiAuth() {
    await new Promise((resolve) => gapi.load('client:auth2', resolve));
    await new Promise((resolve) => gapi.auth2.init(GAPI_CONFIG).then(resolve));
  }
}
于 2020-05-19T18:37:52.270 回答
1

鉴于 IAP 和 Firebase 的性质,这似乎是不可能的。解决方法可能与之前的评论中提到的一样,以实现自定义提供程序,但您应该创建自己的令牌。那么也许,如果这可能是实现目标的最佳方式,请重新考虑您的解决方案。

于 2020-01-13T23:43:36.267 回答
1

我没有使用 Google Identity Aware Product 的经验,但我的期望是您必须为 Firebase Authentication 实现一个自定义提供程序。您现在缺少的关键部分是一个服务器端代码,它从 IAP 令牌中获取信息并从中生成一个有效的 Firebase 令牌然后,您将该令牌传递回客户端,客户端可以使用它来使用signInWithCustomToken.

于 2020-01-08T15:16:35.777 回答