首页 文章

AngularFire2登录注销订阅Auth问题 - Angular2

提问于
浏览
9

好的,所以我've been banging my head against the wall for half a day trying to resolve this, reason I haven' t因为我的知识水平 AngularFire2Angular2 有点初学者 .

我有一个应用程序,一个简单的登录表单,使用 AngularFire2 连接到 Facebook ,检索用户 Access TokenFacebook Id 然后调用 Facebook Graph API ,它返回名字,姓氏,性别,电子邮件等 .

如下图所示:

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 =来自 auth Access Token =来自 authState

然后我将 Facebook Graph API 返回的信息保存到 Firebase .

现在问题来了,正如你在上面指定的函数中看到的那样,我已经订阅了 auth 方法,这允许我访问 Facebook IdAccess Token ,这是调用 Facebook Graph API 所必需的

在我的应用程序导航中,我有一个注销按钮 . 当用户点击此按钮时,我会打电话

this.af.auth.logout();

一旦我按下注销,上面指定的函数将被调用,因为订阅了 auth 的更改,我在内部放置了一个if语句来检查auth是否为null,如果是这样返回哪个工作 - 看起来有点hacky对我来说 .

如果我然后尝试重新登录,则在 ${auth.facebook.uid} 上调用 Facebook Graph API 的URL失败,这表示它是 undefined ,我将其归类为新登录,因此该方法应该从头到尾再次运行 .

现在我的问题是:

如何在我的Login with facebook方法中订阅 auth ?仍然可以访问 Facebook IdAccess Token

我试图找出一种方法,该方法将适用于两种情况:

  • 用户已存在于数据库中

  • 用户不存在,因此它是一个新的注册 .

注销和注册/登录都应彼此隔离,不要干扰彼此的职责 .

如果任何人都可以分享任何知识或建议更清洁的方式这样做,我将非常感激 .

Update

我在 Github 上创建了一个存储库,它是我的应用程序的缩减版本,它显示了我遇到的错误 .

Repo

复制:

login.service loginWithFacebook方法中,您将看到以下代码行:

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

对此进行评论并按照以下步骤操作 .

  • 在注册页面上登录facebook
    使用注销按钮

  • 注销

  • 退出后直接用facebook登录

您将注意到第一次登录时,只要您注销并使用Facebook重新登录,图形API将因未定义 auth.facebook.uid 而失败 .

现在理想情况下,我不想订阅auth事件的原因是因为我们将使用Google和电子邮件和密码实现登录 .

我想订阅 auth 事件的唯一地方是导航栏内部,当用户获得授权时,它会更改菜单导航 .

注意:这与firebase上的测试帐户相关联 . 解决此问题后,将删除测试帐户 . 因此,将删除用于测试此信息的所有帐户信息 .

Final Update

好的,所以我决定打开这个奖金以帮助找到解决方案 .

我能看到这个工作的唯一方法是有一个登录页面,这个登录页面将迎合新用户和现有用户,如果用户是新用户登录,那么请调用Facebook Graph API检索有关他们的信息,然后保存,如果他们存在,那么不要调用Facebook Graph API .

我希望如何工作:

新用户:

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

现有用户

如果用户已经使用Facebook注册,那么当他/她登录时我不想调用Facebook Graph API时,对于新帐户只需要调用一次图表 .

回购仍然可用 .

在首次注册,注销,登录后,错误打印到控制台:

enter image description here

AngularFire2包json

{
  "_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"
}

1 回答

  • 2

    你应该创建一个 LoginService

    并单独登录和授权订阅 .

    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();
       }
    }
    

    看我的分支:https://github.com/mxii/test-application

    和公关:https://github.com/Atkinson88/test-application/pull/1

    您的 LoginService 存在问题 . 它实例化了两次,我不知道为什么 .

相关问题