firebase中的Google身份验证显示空白屏幕Progressive Web App

时间:2017-10-04 16:59:17

标签: angular firebase firebase-authentication progressive-web-apps

我正在创建我的第一个使用firebase存储数据的Progressive Web应用程序。我还使用Gmail作为将使用该应用的所有用户的入口点。但是我坚持实施登录。以下是我登录的代码:

HTML:

<button md-raised-button color="warn" (click)="logInGoogle()"><md-icon>group</md-icon>Sign in with google to enjoy the app</button> 

TS:

logInGoogle(){
    this.authService.loginWithGoogle().then( user => {
      console.log("User is logged in");
      //this.router.navigate(['/addweather']);
    })
    .catch( err => {
      console.log('some error occured');
    })
  }

这是服务:

loginWithGoogle() {
    return this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
  }

另请检查我auth构造函数中的app.component.ts状态:

this.authService.afAuth.authState.subscribe(
      (auth) => {
        if(auth === null){
          console.log("Not Logged in.");
          this.router.navigate(['login']);
          this.isLoggedIn = false;
        }
        else {
          console.log("Successfully Logged in.");
          this.isLoggedIn = true;
          this.router.navigate(['']);
        }
      }
    )

现在应用程序显示了一些行为:

  1. 此登录功能在浏览器上工作正常,如果我点击登录按钮,它会打开一个新窗口,授权我并返回打开该应用程序的同一选项卡。

  2. 当我将应用程序添加到主屏幕并尝试再次登录时,它会提示我以下选项:

  3. enter image description here

    一旦我点击chrome,它就会授权我并将我重定向到应用程序,但应用程序现在显示一个空白屏幕,oAuth屏幕只是处于无限处理状态。 为什么会发生这种情况?我的意思是,它不应该像应用程序在浏览器中运行时那样正常工作。

    同样在点击登录按钮时,它不应该提示选项,如上图所示;相反,它应该打开一个oAuth对话框。我尝试使用以下代码执行此操作:

    logInGoogle(){
        var newWindow = window.open('https://accounts.google.com/o/oauth2/auth?scope=https://www.google.com/m8/feeds&client_id=9722-j3fstr5sh6pumie.apps.googleusercontent.com&redirect_uri=https://weatherapp321.firebaseapp.com/__/auth/handler&response_type=token', 'name', 'height=600,width=450');
    
      }
    

    现在,这不是通过选项提示,而是打开一个所需的对话框。但在授权后,这让我回到了登录页面。 为什么会发生这种情况?当我已经检查app.component.ts中的身份验证状态并在用户获得授权时将用户重定向到主页。

    感谢您的耐心和阅读直到最后。非常感谢帮助。

    修改

    根据Yevgen的建议: 试过signInWithRedirect。它在我第一次登录时有效,稍微延迟了2秒。但后来我退出并尝试再次登录,登录后出现空白屏幕。

3 个答案:

答案 0 :(得分:6)

我的宠物网络应用程序上的行为几乎相同。 为了我自己,我将在接下来的步骤中解决它:

  1. 我将firebase初始化移至app.module.ts
  2. &#13;
    &#13;
    @NgModule({
        ...
        providers: [
            { provide: APP_INITIALIZER, useFactory: appConfig, deps: [AuthService], multi: true }
        ]
    })
    
    export function appConfig(authService) {
        const app = firebase.initializeApp({
            apiKey
            authDomain
        });
        return () => new Promise((resolve, reject) => {
            firebase.auth()
            .onAuthStateChanged(data => {
                if (data) {
                  firebase.auth().currentUser.getToken()
                    .then((token: string) => authService.setToken(token););
                }
                resolve(true);
            }, error => resolve(true));
        });
    }
    &#13;
    &#13;
    &#13;

    1. 重定向到我在auth.guard.ts
    2. 中管理的LoginPage

      &#13;
      &#13;
      export class AuthGuard implements CanActivate {
          constructor(
              private authService: AuthService,
              private router: Router
          ) {}
      
          canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
              if (this.authService.isAuthenticated()) {
                  return true;
              } else {
                  this.router.navigate(['/signin']);
                  return false;
              }
          }
      }
      &#13;
      &#13;
      &#13;

      1. 我的auth.service.ts
      2. 中有下一个代码

        &#13;
        &#13;
        export class AuthService {
            token: string;
        
            signinUser(email: string, password: string) {
                return new Promise((resolve, reject) => {
                    firebase.auth().signInWithEmailAndPassword(email, password)
                        .then(resp => {
                            firebase.auth().currentUser.getToken()
                                .then((token: string) => {
                                    this.token = token;
                                    resolve(resp);
                                }).catch(reject);
                            return resp;
                        })
                        .catch(reject);
                    });
            }
        
            signoutUser() {
                return firebase.auth().signOut()
                    .then(resp => this.token = null);
            }
        
            getToken() {
                firebase.auth().currentUser.getToken()
                    .then((token: string) => this.setToken(token));
                return this.token;
            }
            
            setToken(token) {
              this.token = token;
            }
        
            isAuthenticated() {
                return this.token != null;
            }
        }
        &#13;
        &#13;
        &#13;

        我希望它会对你有所帮助。

答案 1 :(得分:1)

在移动设备上看,您的应用程序会打开身份验证,而不是当前浏览器的新选项卡,但是在新的浏览器中,因此在使用Google进行身份验证后,无法将有效的重定向返回到初始浏览器。如果您使用重定向登录,则会保留在同一浏览器中,因此您需要将服务更改为:

loginWithGoogle() {
    return this.afAuth.auth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());
}

答案 2 :(得分:0)

redirect auth 在PWA上不起作用(在某些情况下可能使用不同的浏览器实例)。您可以使用弹出式身份验证流程来解决此问题:

https://firebase.google.com/docs/auth/web/google-signin

它看起来像这样:

firebase.auth().signInWithPopup(provider).then(function(result) {
  // This gives you a Google Access Token. You can use it to access the Google API.
  var token = result.credential.accessToken;
  // The signed-in user info.
  var user = result.user;
  // ...
}).catch(function(error) {
  // Handle Errors here.
  var errorCode = error.code;
  var errorMessage = error.message;
  // The email of the user's account used.
  var email = error.email;
  // The firebase.auth.AuthCredential type that was used.
  var credential = error.credential;
  // ...
});

只有流量差异在于它会启动弹出式浏览器窗口,而不是重定向当前实例。这简化了获取auth结果的一些逻辑。如果您希望在非PWA上保留正常流量,则可以检测应用程序是否从主屏幕启动:

https://developers.google.com/web/updates/2015/10/display-mode