OAuth 访问令牌和刷新令牌访问令牌就像一张电影片:您可从售票处获得一张小纸片,证明您已付费获得了进入观看的权利。进入电影院时,您将这个纸片提供给一位员工,他告诉您您有权看哪场电影 — 并将这个纸片撕掉一半,确保它仅能使用一次。
类似地,OAuth 访问令牌是一个具有较短存活时间 (TTL) 的一次性令牌。下一次用户通过 Meetup 链接登录到 UGLI 时,他或她不需要提供用户名和密码。Passport 会向 Meetup 发送一个刷新令牌。除非用户撤销从 Meetup 对 UGLI 的访问,否则 Meetup 会以一个具有较短 TTL 的新访问令牌作为响应。
刷新令牌应在系统中存在较长时间 — 基本上讲,只要用户帐户存在,它就会存在。相对而言,访问令牌是寿命较短的暂时性对象,每次用户向远程 OAuth 提供商执行身份验证时都会重新生成它。
在下一节中,您将从 Meetup.com 获取 consumerKey 和 consumerSecret,并将它们保存在 config.js 文件中。但您在继续后面的操作之前,需要对当前的文件执行两处额外的更改。
紧随新 MeetupStrategy 构造函数之后的函数是从 Meetup.com 接收响应的事件处理函数。我们对响应的 3 个重要部分感兴趣:访问令牌、刷新令牌和用户配置文件。(参见 边栏来获取这些令牌的详细信息。)
访问令牌和刷新令牌是您原封不动地传递给 Passport 的字符串。尽管它们对 OAuth 操作的成功至关重要,但就它们本身而言看起来很令人讨厌。(清单 10 包含二者的示例。)
用户配置文件更有趣。它是 OAuth 提供商返回的一个 JSON 对象,其中包含成功经过身份验证的用户的信息。不同 OAuth 提供商之间的具体细节不同。清单 10 给出了 Meetup 返回的用户配置文件的一个示例。
清单 10. 从 Meetup.com OAuth 提供商返回的用户配置文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| {
provider: 'meetup',
id: 13848777,
displayName: 'Scott Davis',
_raw: '{
"results": [{
"status": "active",
"link": "http:\\\/\\\/www.meetup.com\\\/members\\\/13848777",
"photo": {
"photo_link": "http:\\\/\\\/photos1.meetupstatic.com\\\/photos\\\/member\\\/7\\\/4\\\/d\\\/2\\
\/member_11849906.jpeg",
"thumb_link": "http:\\\/\\\/photos3.meetupstatic.com\\\/photos\\\/member\\\/7\\\/4\\\/d\\\/2\\
\/thumb_11849906.jpeg",
"photo_id": 11849906
},
"country": "us",
"state": "CO",
"city": "Denver",
"id": 13848777,
"joined": 1295844957000,
"bio": "Scott Davis is the founder of ThirstyHead.com, a training and
consulting company that specializes in leading-edge technology solutions like
HTML 5, NoSQL, Groovy, and Grails.",
"name": "Scott Davis",
"other_services": {
"twitter": {
"identifier": "@scottdavis99"
}
}
}]
}',
_json: {
results: [ [Object] ],
meta: {
link: 'https://api.meetup.com/2/members',
total_count: 1,
url: 'https://api.meetup.com/2/members?order=name&member_id=13848777&offset=0
&format=json&page=800',
title: 'Meetup Members v2',
updated: 1392763702000,
description: 'API method for accessing members of Meetup Groups',
method: 'Members',
},
accessToken: 'c7b5577bb80aab55439785cd86abcdef',
refreshToken: '2af98db68950235a1e2519a734abcdef'
}
}
|
可以看到,Meetup 返回用户详细信息,比如姓名、住址、加入日期、面部照片、链接的社交媒体帐户等。
需要做的最后一件事是完成 Meetup 策略的自定义,将 Meetup 配置文件字段映射回 app/models/user.server.model.js 中定义的 User Mongoose 对象。编辑 config/strategies/meetup.js 中剩余的 Facebook 部分,如清单 11 所示。
清单 11. 将 OAuth 用户配置文件映射到 User 对象1
2
3
4
5
6
7
8
9
10
11
| // Create the user OAuth profile
var providerUserProfile = {
firstName: '',
lastName: '',
displayName: profile.displayName,
email: '',
username: profile.id,
provider: profile.provider,
providerIdentifierField: 'id',
providerData: providerData
};
|
如果在 Meetup 配置文件中看到您想要添加到 User 对象中的 JSON,这是执行更改的完美时机。不要忘记向 public/modules/users/views 中的 HTML 表单添加新字段。
您完成的 config/strategies/meetup.js 应类似于清单 12。
清单 12. 完整的 config/strategies/meetup.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| 'use strict';
/**
* Module dependencies.
*/
var passport = require('passport'),
url = require('url'),
MeetupStrategy = require('passport-meetup').Strategy,
config = require('../config'),
users = require('../../app/controllers/users');
module.exports = function() {
// Use meetup strategy
passport.use(new MeetupStrategy({
consumerKey: config.meetup.clientID,
consumerSecret: config.meetup.clientSecret,
callbackURL: config.meetup.callbackURL,
},
function(req, accessToken, refreshToken, profile, done) {
// Set the provider data and include tokens
var providerData = profile._json;
providerData.accessToken = accessToken;
providerData.refreshToken = refreshToken;
// Create the user OAuth profile
var providerUserProfile = {
firstName: '',
lastName: '',
displayName: profile.displayName,
email: '',
username: profile.id,
provider: profile.provider,
providerIdentifierField: 'id',
providerData: providerData
};
// Save the user OAuth profile
users.saveOAuthUserProfile(req, providerUserProfile, done);
}
));
};
|
测试此代码之前,需要执行另外一件事:从 Meetup 获取 consumerKey 和 consumerSecret。 |