AngularFire2 Login Logout Subscrever a questão do Auth - Angular2

9

Ok, então estou batendo com a cabeça contra a parede por meio dia tentando resolver isso, razão pela qual ainda não me refiro ao meu nível de conhecimento com AngularFire2 e Angular2 é um pouco novato .

Eu tenho um aplicativo, um formulário de login simples que usa AngularFire2 se conecta a Facebook , recupera os usuários Access Token e Facebook Id e chama o Facebook Graph API que retorna nome, sobrenome, gênero, email etc. .

Como mostrado aqui:

loginWithFacebook(): FirebaseListObservable<string> {

    return FirebaseListObservable.create(obs => {
        this.af.auth.login({
            provider: AuthProviders.Facebook,
            method: AuthMethods.Popup,
            scope: ['public_profile']
        }).then((authState: any) => {

            let authSubscription = this.af.auth.subscribe(auth => {

             if (auth == null) return;

                let url = 'https://graph.facebook.com/v2.8/${auth.facebook.uid}?fields=first_name,last_name,gender,email&access_token=${authState.facebook.accessToken}';

                this.http.get(url).subscribe(response => {
                    let user = response.json()

                    this.af.database.object('/users/' + authState.uid).update({
                        first_name: user.first_name,
                        last_name: user.last_name,
                        display_name: auth.facebook.displayName,
                        gender: user.gender,
                        email_address: auth.facebook.email,
                        accessToken: authState.facebook.accessToken,
                        facebook_Id: auth.facebook.uid,
                    })
                },
                    err => {
                        obs.next(false);
                    });

            });

            authSubscription.unsubscribe();

            obs.next(true);

        }).catch(err => {
            obs.next(false);
        });
    });

}

Facebook Id = Vem de auth Access Token = Vem de authState

Em seguida, salve as informações retornadas de Facebook Graph API a Firebase .

Agora vem o problema, como você pode ver dentro da função especificada acima, eu me inscrevi no método auth , isso me permite acessar o Facebook Id e o Access Token que é necessário para chamar Facebook Graph API

Na navegação do meu aplicativo, eu tenho um botão de logout. Quando o usuário clica nesse botão eu chamo

this.af.auth.logout();

Uma vez que eu tenha pressionado o logout, minha função especificada acima será chamada devido a estar inscrito na alteração de auth , eu coloquei uma instrução if dentro para verificar se a autenticação é nula, se for, retornar que está funcionando - Parece um pouco hacky para mim.

Se eu tentar entrar novamente, o URL para chamar Facebook Graph API falhará em ${auth.facebook.uid} , o que indica que é undefined , o que não sei ao certo por que isso falharia porque para mim ele é classificado como novo faça o login para que o método seja executado do início ao fim novamente.

Agora, minha pergunta é esta:

Como posso me inscrever no auth no meu método Login com o Facebook? e ainda acessar o Facebook Id e Access Token

Estou tentando descobrir como o método funcionará em dois cenários:

  1. O usuário já existe no banco de dados
  2. O usuário não existe, por isso é uma nova inscrição.

O logout e o Sign Up / Login devem ser isolados uns dos outros e não interferir nas responsabilidades uns dos outros.

Se alguém puder compartilhar algum conhecimento ou sugerir uma maneira muito mais limpa de fazer isso, eu aprecio muito isso.

Atualizar

Eu criei um repositório no Github , que é uma versão reduzida do meu aplicativo e mostra o erro que estou tendo.

Repo

Para replicar:

Dentro do método login.service loginWithFacebook você verá esta linha de código:

if (auth.facebook.uid == null) return;

comente isso e siga as etapas abaixo.

  1. Faça login com o facebook na página de inscrição
  2. sair usando o botão de logout
  3. Faça login novamente com o Facebook, logo após o logout

Você notará o primeiro login, pois assim que você sair e fizer login novamente com o facebook, a API do gráfico falhará devido a auth.facebook.uid ser indefinido.

Agora, idealmente, não quero me inscrever no evento de autenticação porque o fato de estarmos implementando o login no Google, o e-mail e a senha.

O único local em que gostaria de assinar o evento auth estaria dentro da barra de navegação, o que alterará a navegação no menu quando o usuário for autorizado.

NOTA: isso está vinculado a uma conta de teste no Firebase. Depois que esse problema for resolvido, a conta de teste será excluída. Assim, todas as informações da conta que foram usadas para testar isso serão excluídas.

Atualização final

Ok, então decidi abrir uma recompensa para ajudar a encontrar uma solução.

A única maneira de ver isso funcionando é ter uma página de login, essa página de login atenderá usuários novos e existentes, se o usuário fizer login com o Facebook se for novo, ligue para a API do Facebook Graph para recuperar informações sobre eles e em seguida, salve-o, se existirem, não ligue para a API do Graph do Facebook.

Como espero que isso funcione:

Novo usuário:

1.  User navigates to website
2.  Signs in with Facebook
3.  Popup appears
4.  Users grants the permissions I’ve requested
5.  Callback to website <- at this point I have access to users Facebook Id and accessToken via the auth
6.  Call Facebook Graph API retrieve first_name, last name etc passing in users Facebook Id and accessToken
7.  Then save the information returned from Facebook Graph to Firebase

Usuário existente

Se o usuário já se inscreveu usando o Facebook, quando ele faz login, não desejo ligar para a API de gráficos do Facebook. A chamada para o gráfico só é necessária uma vez para novas contas.

Além disso, o repo ainda está disponível.

Erro impresso no console, depois de se registrar pela primeira vez, efetuando logout, efetuando login:

PacoteAngularFire2json

{"_args": [
    [
      {
        "raw": "angularfire2@^2.0.0-beta.7",
        "scope": null,
        "escapedName": "angularfire2",
        "name": "angularfire2",
        "rawSpec": "^2.0.0-beta.7",
        "spec": ">=2.0.0-beta.7 <3.0.0",
        "type": "range"
      },
      "/Users/Scott/Desktop/test-application-master 2"
    ]
  ],
  "_from": "angularfire2@>=2.0.0-beta.7 <3.0.0",
  "_id": "angularfire2@2.0.0-beta.7",
  "_inCache": true,
  "_location": "/angularfire2",
  "_nodeVersion": "6.9.1",
  "_npmOperationalInternal": {
    "host": "packages-12-west.internal.npmjs.com",
    "tmp": "tmp/angularfire2-2.0.0-beta.7.tgz_1484315670561_0.09154823864810169"
  },
  "_npmUser": {
    "name": "davideast",
    "email": "dceast@gmail.com"
  },
  "_npmVersion": "3.10.8",
  "_phantomChildren": {},
  "_requested": {
    "raw": "angularfire2@^2.0.0-beta.7",
    "scope": null,
    "escapedName": "angularfire2",
    "name": "angularfire2",
    "rawSpec": "^2.0.0-beta.7",
    "spec": ">=2.0.0-beta.7 <3.0.0",
    "type": "range"
  },
  "_requiredBy": [
    "/"
  ],
  "_resolved": "https://registry.npmjs.org/angularfire2/-/angularfire2-2.0.0-beta.7.tgz",
  "_shasum": "ce4f98467c5a8b2cc1dfd607fda718aee8d64521",
  "_shrinkwrap": null,
  "_spec": "angularfire2@^2.0.0-beta.7",
  "_where": "/Users/Scott/Desktop/test-application-master 2",
  "author": {
    "name": "jeffbcross,davideast"
  },
  "bugs": {
    "url": "https://github.com/angular/angularfire2/issues"
  },
  "dependencies": {},
  "description": "<p align=\"center\">   <h1 align=\"center\">AngularFire2</h1>   <p align=\"center\">The official library for Firebase and Angular 2</p> </p>",
  "devDependencies": {
    "@angular/compiler-cli": "^2.0.0",
    "@angular/platform-server": "^2.0.0-rc.5",
    "@types/jasmine": "^2.5.36",
    "@types/request": "0.0.30",
    "concurrently": "^2.2.0",
    "conventional-changelog-cli": "^1.2.0",
    "es6-module-loader": "^0.17.10",
    "es6-shim": "^0.35.0",
    "gulp": "^3.9.0",
    "gulp-jasmine": "^2.2.1",
    "gulp-typescript": "^2.10.0",
    "http-server": "^0.8.5",
    "jasmine": "^2.4.1",
    "jasmine-core": "^2.4.1",
    "json": "^9.0.3",
    "karma": "^0.13.19",
    "karma-chrome-launcher": "^0.2.2",
    "karma-firefox-launcher": "^0.1.7",
    "karma-jasmine": "^0.3.6",
    "karma-mocha-reporter": "^2.0.2",
    "karma-systemjs": "^0.10.0",
    "ncp": "^2.0.0",
    "parse5": "^1.3.2",
    "protractor": "3.0.0",
    "reflect-metadata": "0.1.2",
    "rimraf": "^2.5.4",
    "rollup": "^0.35.11",
    "rollup-watch": "^2.5.0",
    "systemjs": "^0.19.16",
    "systemjs-builder": "^0.15.7",
    "traceur": "0.0.96",
    "typedoc": "github:jeffbcross/typedoc",
    "typescript": "^2.0.2",
    "zone.js": "^0.7.2"
  },
  "directories": {},
  "dist": {
    "shasum": "ce4f98467c5a8b2cc1dfd607fda718aee8d64521",
    "tarball": "https://registry.npmjs.org/angularfire2/-/angularfire2-2.0.0-beta.7.tgz"
  },
  "homepage": "https://github.com/angular/angularfire2#readme",
  "keywords": [
    "angular2",
    "angular",
    "firebase"
  ],
  "license": "MIT",
  "main": "bundles/angularfire2.umd.js",
  "maintainers": [
    {
      "name": "angularcore",
      "email": "angular-core+npm@google.com"
    },
    {
      "name": "davideast",
      "email": "dceast@gmail.com"
    },
    {
      "name": "jeffbcross",
      "email": "middlefloor@gmail.com"
    }
  ],
  "module": "index.js",
  "name": "angularfire2",
  "optionalDependencies": {},
  "peerDependencies": {
    "@angular/common": "^2.0.0",
    "@angular/compiler": "^2.0.0",
    "@angular/core": "^2.0.0",
    "@angular/platform-browser": "^2.0.0",
    "@angular/platform-browser-dynamic": "^2.0.0",
    "firebase": "^3.0.0",
    "rxjs": "^5.0.1"
  },
  "readme": "ERROR: No README data found!",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/angular/angularfire2.git"
  },
  "scripts": {},
  "typings": "index.d.ts",
  "version": "2.0.0-beta.7"
}
    
por Code Ratchet 01.02.2017 в 08:23
fonte

1 resposta

2

Você deve criar um LoginService !

E login e assinatura de autenticação separados.

export class LoginService {

   public isLoggedIn = false;
   private _authSubsription;

   constructor(private _af: AngularFire) {
      this._authSubscription = this._af.auth.subscribe(auth => {
         if (!auth) {
            console.log('LOGGED OUT!!');
            this.isLoggedIn = false;
            return;
         }

         this.isLoggedIn = true;

         // do your stuff here ..
      });
   }

   public login() {
      this._af.auth.login({
         provider: AuthProviders.Facebook,
         method: AuthMethods.Popup,
         scope: ['public_profile']
      });
   }

   public logout() {
      this._af.auth.logout();
   }
}

Veja minha ramificação: link

E PR: link

Existe um problema com o seu LoginService . É instanciado duas vezes, não sei porquê.

    
por mxii 01.02.2017 / 08:35
fonte