web-dev-qa-db-ja.com

空白の画面を表示するFirebaseでのGoogle認証プログレッシブウェブアプリ

Firebaseを使用してデータを保存する最初のプログレッシブウェブアプリを作成しようとしています。また、アプリを使用するすべてのユーザーのエントリポイントとして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. アプリをホーム画面に追加して再度ログインしようとすると、以下のオプションの入力を求められます。

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秒のわずかな遅延で動作しました。しかし、ログアウトして再度ログインしようとすると、ログイン後に空白の画面が表示されます。

18
Aakash Thakur

ペットのウェブアプリでもほぼ同じ動作をしました。私自身のために、私は次のステップでそれを解決します:

  1. Firebaseの初期化をapp.module.tsに移動します
@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));
    });
}
  1. auth.guard.tsで管理したLoginPageへのリダイレクト
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;
        }
    }
}
  1. auth.service.tsに次のコードがありました
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;
    }
}

お役に立てば幸いです。

6
Vitali Solyanik

モバイルでは、アプリは現在のブラウザの新しいタブではなく新しいブラウザで認証を開くようです。そのため、Googleでの認証後に、最初のブラウザに有効なリダイレクトを戻すことはできません。リダイレクトを使用してサインインする場合、同じブラウザーにとどまるため、サービスを次のように変更する必要があります。

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

redirect authはPWAでは機能しません(場合によっては異なるブラウザインスタンスを使用する可能性があります)。これを回避するには、pop-up authフローを使用します。

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

唯一の流れの違いは、現在のインスタンスをリダイレクトする代わりに、ポップアップブラウザウィンドウを起動することです。これにより、認証結果を取得するためのロジックの一部も簡素化されます。非PWAで通常のフローを維持したい場合は、アプリがホーム画面から起動されたかどうかを検出できます。

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

0
Nico Valencia