aboutsummaryrefslogtreecommitdiff
path: root/lib/handlers/auth.js
blob: 1db9494dbd5f972039b9ae5ba380fa2e061511d5 (plain)
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
'use strict';

const Co = require('co');
const JsonWebToken = require('jsonwebtoken');
const Pify = require('pify');
const TwitterHelper = require('../twitter_helper');

const internals = {};

internals.kRedirectUrl = 'https://api.twitter.com/oauth/authenticate?oauth_token=';
internals.kLoginRedirect = '/login';

internals.signJsonWebToken = Pify(JsonWebToken.sign);

/**
 * Handles the HTTP requests for auth related operations.
 *
 * @class AuthHandler
 * @param {Dasein.tConfiguration} config The configuration to
 * initialize.
 */
module.exports = internals.AuthHandler = class AuthHandler {

  constructor(config) {

    this._twitterHelper = new TwitterHelper(config.twitter);
    this._jwtConfig = config.jwt;
  }

  /**
   * Triggers the twitter login flow. Redirects to twitter's oauth
   * request page
   *
   * @function login
   * @memberof AuthHandler
   * @instance
   * @return {generator} a koa compatible handler generator function
   */
  login() {

    const twitterHelper = this._twitterHelper;

    return function *handleLogin() {

      const requestToken = yield twitterHelper.getRequestToken();
      const loginUrl = `${internals.kRedirectUrl}${requestToken.oAuthToken}`;

      this.body = { loginUrl };
    };
  }

  /**
   * Handles twitter's callback. Fetches the oAuth Verifier, attempts to
   * obtain a user object and responds with the JWT
   *
   * @function callback
   * @memberof AuthHandler
   * @instance
   * @return {generator} a koa compatible handler generator function
   */
  callback() {

    const self = this;

    return function *handleCallback() {

      if (this.request.query.denied) {
        return this.throw(401);
      }

      const oAuthToken = this.request.body.oAuthToken;
      const oAuthVerifier = this.request.body.oAuthVerifier;
      let user;

      try {
        const accessToken = yield self._twitterHelper.getAccessToken(oAuthToken, oAuthVerifier);
        user = yield self._twitterHelper.getUser(accessToken.oAuthAccessToken, accessToken.oAuthAccessTokenSecret);
      }
      catch (err) {
        console.error(err.stack || err.message || err);
        return this.throw(401);
      }

      const expiresAt = Date.now() + self._jwtConfig.duration * 1000;

      const token = yield self._getToken(user);

      const response = {
        expiresAt,
        user,
        token
      };

      this.body = response;
    };
  }

  // Generates a JSON Web Token

  _getToken(payload) {

    const self = this;

    return Co(function * () {

      const token = yield internals.signJsonWebToken(payload, self._jwtConfig.secret, {
        expiresIn: self._jwtConfig.duration
      });

      return token;
    });
  }
};