AngularFire2 登录注销订阅身份验证问题 - Angular2 [英] AngularFire2 Login Logout Subscribe to Auth issue - Angular2

查看:36
本文介绍了AngularFire2 登录注销订阅身份验证问题 - Angular2的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,所以我已经用头撞墙了半天试图解决这个问题,原因我还没有因为我对 AngularFire2 的知识水平code>Angular2 有点初学者.

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

如图所示:

loginWithFacebook(): FirebaseListObservable{返回 FirebaseListObservable.create(obs => {this.af.auth.login({提供者:AuthProviders.Facebook,方法:AuthMethods.Popup,范围:['public_profile']}).then((authState: any) => {让 authSubscription = this.af.auth.subscribe(auth => {if (auth == null) 返回;让 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 => {让用户 = response.json()this.af.database.object('/users/' + authState.uid).update({名字:user.first_name,姓氏:user.last_name,显示名称:auth.facebook.displayName,性别:user.gender,电子邮件地址:auth.facebook.email,accessToken: authState.facebook.accessToken,facebook_Id: auth.facebook.uid,})},错误 =>{obs.next(假);});});authSubscription.unsubscribe();obs.next(真);}).catch(err => {obs.next(假);});});}

Facebook Id = 来自 authAccess Token = 来自 authState

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

现在问题来了,正如你在上面指定的函数中看到的,我订阅了 auth 方法,这允许我访问 Facebook Id 和调用Facebook Graph API

所需的Access Token

在我的应用程序导航中,我有一个注销按钮.当用户单击此按钮时,我调用

this.af.auth.logout();

按下注销后,由于订阅了auth 的更改,将调用上面指定的函数,我在其中放置了一个 if 语句来检查 auth 是否为空,如果所以返回这是有效的 - 对我来说似乎有点hacky.

如果我然后尝试重新登录,调用 Facebook Graph API 的 url 在 ${auth.facebook.uid} 上失败,说明它是 undefined,我不完全确定为什么会失败,因为对我来说它被归类为新登录,因此该方法应该从头到尾再次运行.

现在我的问题是:

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

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

  1. 用户已存在于数据库中
  2. 用户不存在,所以是新注册.

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

如果有人可以分享任何知识或提出更简洁的方法,我将不胜感激.

更新

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

AngularFire2 包 json

<代码>{_args":[[{"raw": "angularfire2@^2.0.0-beta.7",范围":空,"escapedName": "angularfire2","name": "angularfire2","rawSpec": "^2.0.0-beta.7","spec": ">=2.0.0-beta.7 <3.0.0",类型":范围"},/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":真,"_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",电子邮件":dceast@gmail.com"},"_npmVersion": "3.10.8","_phantomChildren": {},_请求":{"raw": "angularfire2@^2.0.0-beta.7",范围":空,"escapedName": "angularfire2","name": "angularfire2","rawSpec": "^2.0.0-beta.7","spec": ">=2.0.0-beta.7 <3.0.0",类型":范围"},_requiredBy":[/"],"_resolved": "https://registry.npmjs.org/angularfire2/-/angularfire2-2.0.0-beta.7.tgz","_shasum": "ce4f98467c5a8b2cc1dfd607fda718aee8d64521",_shrinkwrap":空,"_spec": "angularfire2@^2.0.0-beta.7","_where": "/Users/Scott/Desktop/test-application-master 2",作者": {"name": "jeffbcross,davideast"},错误":{"url": "https://github.com/angular/angularfire2/issues"},依赖关系":{},"description": "<p align=\"center\"> <h1 align=\"center\">AngularFire2</h1> <p align=\"center\">官方库Firebase 和 Angular 2</p> </p>",开发依赖":{"@angular/compiler-cli": "^2.0.0","@angular/platform-server": "^2.0.0-rc.5","@types/jasmine": "^2.5.36","@types/request": "0.0.30","同时": "^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","茉莉花": "^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","量角器": "3.0.0",反射元数据":0.1.2","rimraf": "^2.5.4",汇总":^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","打字稿": "^2.0.2",zone.js":^0.7.2"},目录":{},距离":{"shasum": "ce4f98467c5a8b2cc1dfd607fda718aee8d64521","tarball": "https://registry.npmjs.org/angularfire2/-/angularfire2-2.0.0-beta.7.tgz"},"主页": "https://github.com/angular/angularfire2#readme",关键词":[角度2","角",火力基地"],"许可证": "麻省理工学院","main": "bundles/angularfire2.umd.js",维护者":[{"name": "angularcore","email": "angular-core+npm@google.com"},{"name": "davideast",电子邮件":dceast@gmail.com"},{"name": "jeffbcross",电子邮件":middlefloor@gmail.com"}],模块":index.js","name": "angularfire2","optionalDependencies": {},peerDependencies":{"@angular/common": "^2.0.0","@angular/compiler": "^2.0.0","@angular/core": "^2.0.0","@angular/platform-b​​rowser": "^2.0.0","@angular/platform-b​​rowser-dynamic": "^2.0.0","firebase": "^3.0.0","rxjs": "^5.0.1"},"readme": "错误:未找到 README 数据!",存储库":{"类型": "git","url": "git+https://github.com/angular/angularfire2.git"},脚本":{},"typings": "index.d.ts",版本":2.0.0-beta.7"}

解决方案

你应该创建一个 LoginService

并且分开登录和授权订阅.

export class LoginService {公共 isLoggedIn = false;私人 _authSubsription;构造函数(私有_af:AngularFire){this._authSubscription = this._af.auth.subscribe(auth => {如果(!认证){console.log('退出登录!!');this.isLoggedIn = false;返回;}this.isLoggedIn = true;//在这里做你的事情..});}公共登录(){this._af.auth.login({提供者:AuthProviders.Facebook,方法:AuthMethods.Popup,范围:['public_profile']});}公共注销(){this._af.auth.logout();}}

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

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

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

Ok so I've been banging my head against the wall for half a day trying to resolve this, reason I haven't as of yet is due to my level of knowledge with AngularFire2 and Angular2 is somewhat beginner.

I have an application, a simple login form which uses AngularFire2 connects to Facebook, retrieves the users Access Token and Facebook Id and then calls the Facebook Graph API which returns firstname, lastname, gender, email etc.

As shown here:

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 = Comes from auth Access Token = Comes from authState

I then save the information returned from the Facebook Graph API to Firebase.

Now here comes the issue, as you can see inside the function specified above, I have subscribed to the auth method, this allows me to access the Facebook Id and the Access Token which is required to call Facebook Graph API

In the navigation of my application I have a logout button. When the user clicks this button I call

this.af.auth.logout();

Once I've pressed logout, my function specified above will be called due to being subscribed to the change of auth, I've placed an if statement inside to check if auth is null, if so return which is working - Seems a bit hacky to me.

If I then try and sign back in, the url for calling Facebook Graph API fails on ${auth.facebook.uid} which states it's undefined, which I'm not entirely sure why this would fail because to me it's classed as a new login so the method should run from start to finish again.

Now my question is this:

How can I get around subscribing to the auth within my Login with facebook method? and still access the Facebook Id and Access Token

I'm trying to figure out a way whereby the method will work for two scenarios which are:

  1. User already exists in the database
  2. User does not exist so its a fresh signup.

The logout and Sign Up/Login should both be isolated from one another and not interfere with one another responsibilities.

If anyone can share any knowledge or suggest a much cleaner way of doing this I would highly appreciate it.

Update

I've created a repository on Github which is a cut down version of my application and it shows the error I'm experiencing.

Repo

To replicate:

Inside the login.service loginWithFacebook method you will see this line of code:

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

comment this out and follow the steps below.

  1. Login with facebook on the signup page
  2. signout using the logout button
  3. Sign back in with facebook straight after logging out

You will notice first time logging in it works, as soon as you signout and sign back in with facebook the graph API will fail due to auth.facebook.uid being undefined.

Now Ideally I do not want to subscribe to the auth event reason being is because we will be implementing signin with Google and email and password.

The only place I would like to subscribe to the auth event would be inside the nav bar which changes the menu navigation when the user becomes authorised.

NOTE: this is linked to a test account on firebase. Once this issue has been resolved the test account will be deleted. So all account information that has been used to test this will be deleted.

Final Update

Ok so I’ve decided to open a bounty on this to help find a solution.

The only way I can see this working is having one login page, this login page will cater for new and existing user, if the user logs in with Facebook if they’re new then call Facebook Graph API retrieve information about them and then save it, if they’re existing then don’t call the Facebook Graph API.

How I expect this to work:

New User:

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

Existing user

If the user has already signed up using Facebook then when he / she signs in I don’t want to call the Facebook Graph API, the call to the Graph is only required once for new accounts.

Also the repo is still available.

Error printed to console, after registering for the first time, logging out, logging in:

AngularFire2 package 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"
}

解决方案

You should create a LoginService!

And separate login and auth-subscription.

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

See my branch: https://github.com/mxii/test-application

And PR: https://github.com/Atkinson88/test-application/pull/1

There is an existing problem with your LoginService. Its instantiated twice, I am not sure why.

这篇关于AngularFire2 登录注销订阅身份验证问题 - Angular2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆