---
id: 589a8eb3f9fc0f352b528e72
title: 实现第三种社交登录
challengeType: 2
forumTopicId: 301558
dashedName: implementation-of-social-authentication-iii
---

# --description--

验证策略的最后一部分是处理从 GitHub 返回的个人信息。 如果用户存在，我们就需要从数据库中读取用户数据并在 profile 页面加载；否则，我们需要把用户信息添加到数据库。 GitHub 在用户信息中为我们提供了独一无二的 *id*，我们可以通过序列化的 id 在数据库中搜索用户（已实现）。 以下是这个逻辑的实现示例，我们应该把它传到新策略的第二个参数，就是目前 `console.log(profile);` 的下方：

```js
myDataBase.findOneAndUpdate(
  { id: profile.id },
  {
    $setOnInsert: {
      id: profile.id,
      name: profile.displayName || 'John Doe',
      photo: profile.photos[0].value || '',
      email: Array.isArray(profile.emails)
        ? profile.emails[0].value
        : 'No public email',
      created_on: new Date(),
      provider: profile.provider || ''
    },
    $set: {
      last_login: new Date()
    },
    $inc: {
      login_count: 1
    }
  },
  { upsert: true, new: true },
  (err, doc) => {
    return cb(null, doc.value);
  }
);
```

`findOneAndUpdate` 的作用是在数据库中查询对象并更新， 如果对象不存在，将插入对象，然后我们可以在回调方法里获取到插入的新对象。 在这个例子中，我们会设置 `last_login`，而且总会为 `login_count` 加 `1`。只有在插入一个新对象（新用户）时，我们才会初始化这些字段。 另外，还需要注意默认值的使用。 有时返回的用户信息可能不全，可能是因为用户没有填写，也可能是因为用户选择不公开一部分信息。 在这种情况下，我们需要进行相应的处理，以防我们的 app 报错。

你现在应该可以登录你的应用了，试试吧。

完成上述要求后，你可以在下方提交你的页面链接。 如果你遇到了问题，可以参考 [这里](https://gist.github.com/camperbot/183e968f0e01d81dde015d45ba9d2745) 的答案。

# --hints--

GitHub 策略应配置完成。

```js
(getUserInput) =>
  $.get(getUserInput('url') + '/_api/auth.js').then(
    (data) => {
      assert.match(
        data,
        /GitHubStrategy[^]*myDataBase/gi,
        'Strategy should use now use the database to search for the user'
      );
      assert.match(
        data,
        /GitHubStrategy[^]*return cb/gi,
        'Strategy should return the callback function "cb"'
      );
    },
    (xhr) => {
      throw new Error(xhr.statusText);
    }
  );
```

# --solutions--

```js
/**
  Backend challenges don't need solutions, 
  because they would need to be tested against a full working project. 
  Please check our contributing guidelines to learn more.
*/
```
