1 | _ = require 'lodash'
|
2 | debug = require('debug')('express-meshblu-auth:info')
|
3 |
|
4 | class MeshbluAuthExpress
|
5 | constructor: (@meshbluOptions, dependencies={}) ->
|
6 | @MeshbluHttp = dependencies.MeshbluHttp ? require 'meshblu-http'
|
7 |
|
8 | authDeviceWithMeshblu: (uuid, token, callback=->) =>
|
9 | return callback new Error('Meshblu credentials missing') unless uuid? && token?
|
10 | options = @_extendMeshbluAuth({ uuid, token })
|
11 | meshbluHttp = new @MeshbluHttp options
|
12 | meshbluHttp.authenticate (error) =>
|
13 | if error?
|
14 | isUserError = @_isUserError error
|
15 | debug 'authenticate got an error', { isUserError }, error
|
16 | return callback null, null if isUserError
|
17 | return callback error
|
18 | meshbluAuth = @_defaultMeshbluAuth { uuid, token }
|
19 | return callback null, meshbluAuth
|
20 |
|
21 | getDeviceFromMeshblu: (uuid, token, callback=->) =>
|
22 | return callback new Error('Meshblu credentials missing') unless uuid? && token?
|
23 | options = @_extendMeshbluAuth({ uuid, token })
|
24 | meshbluHttp = new @MeshbluHttp options
|
25 | meshbluHttp.whoami (error, meshbluDevice) =>
|
26 | if error?
|
27 | isUserError = @_isUserError error
|
28 | debug 'whoami got an error', { isUserError }, error
|
29 | return callback null, null if isUserError
|
30 | return callback error
|
31 | return callback null, null unless meshbluDevice?
|
32 | meshbluAuth = @_defaultMeshbluAuth { uuid, token }
|
33 | return callback null, {meshbluAuth, meshbluDevice}
|
34 |
|
35 | getFromAnywhere: (request) =>
|
36 | auth = @getFromHeaders request
|
37 | return auth if auth?
|
38 | auth = @getFromSkynetHeaders request
|
39 | return auth if auth?
|
40 | auth = @getFromXMeshbluHeaders request
|
41 | return auth if auth?
|
42 | auth = @getFromCookies request
|
43 | return auth if auth?
|
44 | auth = @getFromBasicAuth request
|
45 | return auth if auth?
|
46 | auth = @getFromBearerToken request
|
47 | return auth if auth?
|
48 | return null
|
49 |
|
50 | getFromBasicAuth: (request) =>
|
51 | @_getFromAuthorizationHeader request, 'Basic'
|
52 |
|
53 | getFromBearerToken: (request) =>
|
54 | @_getFromAuthorizationHeader request, 'Bearer'
|
55 |
|
56 | getFromCookies: (request) =>
|
57 | @_getFromObject request, request.cookies
|
58 |
|
59 | getFromHeaders: (request) =>
|
60 | @_getFromObject request, request.headers
|
61 |
|
62 | getFromSkynetHeaders: (request) =>
|
63 | @_getFromObject request,
|
64 | meshblu_auth_uuid: request.headers.skynet_auth_uuid
|
65 | meshblu_auth_token: request.headers.skynet_auth_token
|
66 |
|
67 | getFromXMeshbluHeaders: (request) =>
|
68 | lowerCaseHeaders = _.mapKeys request.headers, (value, key) => key?.toLocaleLowerCase()
|
69 | @_getFromObject request,
|
70 | meshblu_auth_uuid: lowerCaseHeaders['x-meshblu-uuid']
|
71 | meshblu_auth_token: lowerCaseHeaders['x-meshblu-token']
|
72 |
|
73 | _generateBearerToken: ({uuid,token}) =>
|
74 | return new Buffer("#{uuid}:#{token}").toString 'base64'
|
75 |
|
76 | _getFromAuthString: (authString) =>
|
77 | auth = new Buffer(authString, 'base64').toString().split(':')
|
78 | return null unless _.size(auth) == 2
|
79 | return {
|
80 | uuid: _.trim auth[0]
|
81 | token: _.trim auth[1]
|
82 | }
|
83 |
|
84 | _getFromAuthorizationHeader: (request, scheme) =>
|
85 | return null unless request.headers?
|
86 | parts = request.headers.authorization?.split(' ')
|
87 | return null unless parts? && parts[0]?.toLocaleLowerCase() == scheme?.toLocaleLowerCase()
|
88 | return @_getFromAuthString parts[1]
|
89 |
|
90 | _getFromObject: (request, object) =>
|
91 | {meshblu_auth_uuid, meshblu_auth_token, meshblu_auth_bearer} = object ? {}
|
92 |
|
93 | if meshblu_auth_bearer?
|
94 | {uuid, token} = @_getFromAuthString meshblu_auth_bearer
|
95 | meshblu_auth_uuid = uuid
|
96 | meshblu_auth_token = token
|
97 |
|
98 | return null unless meshblu_auth_uuid? && meshblu_auth_token?
|
99 | return {
|
100 | uuid: _.trim meshblu_auth_uuid
|
101 | token: _.trim meshblu_auth_token
|
102 | }
|
103 |
|
104 | _isUserError: (error) =>
|
105 | return unless error.code?
|
106 | error.code < 500
|
107 |
|
108 | _extendMeshbluAuth: ({ uuid, token }) =>
|
109 | return _.extend {}, @meshbluOptions, { uuid, token }
|
110 |
|
111 | _defaultMeshbluAuth: ({ uuid, token }) =>
|
112 | bearerToken = @_generateBearerToken { uuid, token }
|
113 | return _.defaults { uuid, token, bearerToken }, @meshbluOptions
|
114 |
|
115 | _setMeshbluAuth: (request, uuid, token) =>
|
116 | return unless uuid? && token?
|
117 | uuid = _.trim uuid
|
118 | token = _.trim token
|
119 | request.meshbluAuth = _.defaults {uuid, token}, @meshbluOptions, request.meshbluAuth
|
120 |
|
121 | module.exports = MeshbluAuthExpress
|