]>
Commit | Line | Data |
---|---|---|
1 | 'use strict'; | |
2 | ||
3 | const Co = require('co'); | |
4 | const JsonWebToken = require('jsonwebtoken'); | |
5 | const Pify = require('pify'); | |
6 | const TwitterHelper = require('../twitter_helper'); | |
7 | ||
8 | const internals = {}; | |
9 | ||
10 | internals.kRedirectUrl = 'https://api.twitter.com/oauth/authenticate?oauth_token='; | |
11 | internals.kLoginRedirect = '/login'; | |
12 | ||
13 | internals.signJsonWebToken = Pify(JsonWebToken.sign); | |
14 | ||
15 | /** | |
16 | * Handles the HTTP requests for auth related operations. | |
17 | * | |
18 | * @class AuthHandler | |
19 | * @param {Dasein.tConfiguration} config The configuration to | |
20 | * initialize. | |
21 | */ | |
22 | module.exports = internals.AuthHandler = class AuthHandler { | |
23 | ||
24 | constructor(config) { | |
25 | ||
26 | this._twitterHelper = new TwitterHelper(config.twitter); | |
27 | this._jwtConfig = config.jwt; | |
28 | } | |
29 | ||
30 | /** | |
31 | * Triggers the twitter login flow. Redirects to twitter's oauth | |
32 | * request page | |
33 | * | |
34 | * @function login | |
35 | * @memberof AuthHandler | |
36 | * @instance | |
37 | * @return {generator} a koa compatible handler generator function | |
38 | */ | |
39 | login() { | |
40 | ||
41 | const twitterHelper = this._twitterHelper; | |
42 | ||
43 | return function *handleLogin() { | |
44 | ||
45 | const requestToken = yield twitterHelper.getRequestToken(); | |
46 | const loginUrl = `${internals.kRedirectUrl}${requestToken.oAuthToken}`; | |
47 | ||
48 | this.body = { loginUrl }; | |
49 | }; | |
50 | } | |
51 | ||
52 | /** | |
53 | * Handles twitter's callback. Fetches the oAuth Verifier, attempts to | |
54 | * obtain a user object and responds with the JWT | |
55 | * | |
56 | * @function callback | |
57 | * @memberof AuthHandler | |
58 | * @instance | |
59 | * @return {generator} a koa compatible handler generator function | |
60 | */ | |
61 | callback() { | |
62 | ||
63 | const self = this; | |
64 | ||
65 | return function *handleCallback() { | |
66 | ||
67 | if (this.request.query.denied) { | |
68 | return this.throw(401); | |
69 | } | |
70 | ||
71 | const oAuthToken = this.request.body.oAuthToken; | |
72 | const oAuthVerifier = this.request.body.oAuthVerifier; | |
73 | let user; | |
74 | ||
75 | try { | |
76 | const accessToken = yield self._twitterHelper.getAccessToken(oAuthToken, oAuthVerifier); | |
77 | user = yield self._twitterHelper.getUser(accessToken.oAuthAccessToken, accessToken.oAuthAccessTokenSecret); | |
78 | } | |
79 | catch (err) { | |
80 | console.error(err.stack || err.message || err); | |
81 | return this.throw(401); | |
82 | } | |
83 | ||
84 | const expiresAt = Date.now() + self._jwtConfig.duration * 1000; | |
85 | ||
86 | const token = yield self._getToken(user); | |
87 | ||
88 | const response = { | |
89 | expiresAt, | |
90 | user, | |
91 | token | |
92 | }; | |
93 | ||
94 | this.body = response; | |
95 | }; | |
96 | } | |
97 | ||
98 | // Generates a JSON Web Token | |
99 | ||
100 | _getToken(payload) { | |
101 | ||
102 | const self = this; | |
103 | ||
104 | return Co(function * () { | |
105 | ||
106 | const token = yield internals.signJsonWebToken(payload, self._jwtConfig.secret, { | |
107 | expiresIn: self._jwtConfig.duration | |
108 | }); | |
109 | ||
110 | return token; | |
111 | }); | |
112 | } | |
113 | }; |