auth0 2.36.2 → 2.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/README.md +33 -11
- package/package.json +22 -14
- package/src/Auth0RestClient.js +72 -71
- package/src/RetryRestClient.js +78 -81
- package/src/auth/DatabaseAuthenticator.js +242 -259
- package/src/auth/OAUthWithIDTokenValidation.js +99 -103
- package/src/auth/OAuthAuthenticator.js +325 -344
- package/src/auth/PasswordlessAuthenticator.js +238 -252
- package/src/auth/TokensManager.js +231 -246
- package/src/auth/UsersManager.js +149 -160
- package/src/auth/idToken.js +22 -19
- package/src/auth/index.js +510 -581
- package/src/errors.js +23 -23
- package/src/index.js +3 -2
- package/src/management/ActionsManager.js +510 -584
- package/src/management/BlacklistedTokensManager.js +77 -84
- package/src/management/BrandingManager.js +141 -163
- package/src/management/ClientGrantsManager.js +132 -145
- package/src/management/ClientsManager.js +145 -161
- package/src/management/ConnectionsManager.js +215 -204
- package/src/management/CustomDomainsManager.js +140 -157
- package/src/management/DeviceCredentialsManager.js +95 -111
- package/src/management/EmailProviderManager.js +110 -128
- package/src/management/EmailTemplatesManager.js +96 -112
- package/src/management/GrantsManager.js +94 -101
- package/src/management/GuardianManager.js +381 -455
- package/src/management/HooksManager.js +283 -325
- package/src/management/JobsManager.js +310 -343
- package/src/management/LogStreamsManager.js +142 -158
- package/src/management/LogsManager.js +92 -99
- package/src/management/ManagementTokenProvider.js +112 -120
- package/src/management/MigrationsManager.js +81 -90
- package/src/management/OrganizationsManager.js +686 -761
- package/src/management/PromptsManager.js +160 -182
- package/src/management/ResourceServersManager.js +143 -160
- package/src/management/RolesManager.js +323 -369
- package/src/management/RulesConfigsManager.js +94 -110
- package/src/management/RulesManager.js +154 -176
- package/src/management/StatsManager.js +87 -103
- package/src/management/TenantManager.js +81 -97
- package/src/management/TicketsManager.js +107 -115
- package/src/management/UserBlocksManager.js +135 -162
- package/src/management/UsersManager.js +729 -852
- package/src/management/index.js +3094 -3619
- package/src/utils.js +31 -60
package/src/auth/UsersManager.js
CHANGED
|
@@ -1,172 +1,161 @@
|
|
|
1
|
-
|
|
2
|
-
var axios = require('axios');
|
|
1
|
+
const axios = require('axios');
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
const { ArgumentError } = require('rest-facade');
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
|
-
* @class UsersManager
|
|
8
6
|
* Provides methods for getting user information and impersonating users.
|
|
9
|
-
* @constructor
|
|
10
|
-
* @memberOf module:auth
|
|
11
|
-
*
|
|
12
|
-
* @param {Object} options Manager options.
|
|
13
|
-
* @param {String} options.baseUrl The auth0 account URL.
|
|
14
|
-
* @param {String} [options.headers] Default request headers.
|
|
15
|
-
* @param {String} [options.clientId] Default client ID.
|
|
16
7
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
class UsersManager {
|
|
9
|
+
/**
|
|
10
|
+
* @param {object} options Manager options.
|
|
11
|
+
* @param {string} options.baseUrl The auth0 account URL.
|
|
12
|
+
* @param {string} [options.headers] Default request headers.
|
|
13
|
+
* @param {string} [options.clientId] Default client ID.
|
|
14
|
+
*/
|
|
15
|
+
constructor(options) {
|
|
16
|
+
if (typeof options !== 'object') {
|
|
17
|
+
throw new ArgumentError('Missing users manager options');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (typeof options.baseUrl !== 'string') {
|
|
21
|
+
throw new ArgumentError('baseUrl field is required');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
this.baseUrl = options.baseUrl;
|
|
25
|
+
this.headers = options.headers;
|
|
26
|
+
this.clientId = options.clientId;
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Given an access token get the user profile linked to it.
|
|
31
|
+
*
|
|
32
|
+
* @example <caption>
|
|
33
|
+
* Get the user information based on the Auth0 access token (obtained during
|
|
34
|
+
* login). Find more information in the
|
|
35
|
+
* <a href="https://auth0.com/docs/auth-api#!#get--userinfo">API Docs</a>.
|
|
36
|
+
* </caption>
|
|
37
|
+
*
|
|
38
|
+
* auth0.users.getInfo(accessToken, function (err, userInfo) {
|
|
39
|
+
* if (err) {
|
|
40
|
+
* // Handle error.
|
|
41
|
+
* }
|
|
42
|
+
*
|
|
43
|
+
* console.log(userInfo);
|
|
44
|
+
* });
|
|
45
|
+
* @param {string} accessToken User access token.
|
|
46
|
+
* @param {Function} [cb] Callback function.
|
|
47
|
+
* @returns {Promise|undefined}
|
|
48
|
+
*/
|
|
49
|
+
getInfo(accessToken, cb) {
|
|
50
|
+
const url = `${this.baseUrl}/userinfo`;
|
|
51
|
+
const headers = { ...this.headers };
|
|
52
|
+
|
|
53
|
+
if (accessToken === null || accessToken === undefined) {
|
|
54
|
+
throw new ArgumentError('An access token is required');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (typeof accessToken !== 'string' || accessToken.trim().length === 0) {
|
|
58
|
+
throw new ArgumentError('Invalid access token');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Send the user access token in the Authorization header.
|
|
62
|
+
headers['Authorization'] = `Bearer ${accessToken}`;
|
|
63
|
+
|
|
64
|
+
// Perform the request.
|
|
65
|
+
const promise = axios({
|
|
66
|
+
method: 'GET',
|
|
67
|
+
url,
|
|
68
|
+
headers,
|
|
69
|
+
}).then(({ data }) => data);
|
|
70
|
+
|
|
71
|
+
// Use callback if given.
|
|
72
|
+
if (cb instanceof Function) {
|
|
73
|
+
promise.then(cb.bind(null, null)).catch(cb);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return promise;
|
|
24
78
|
}
|
|
25
79
|
|
|
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
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Impersonate the user with the given user ID.
|
|
82
|
+
*
|
|
83
|
+
* @example <caption>
|
|
84
|
+
* Gets a link that can be used once to log in as a specific user. Useful for
|
|
85
|
+
* troubleshooting. Find more information in the
|
|
86
|
+
* [API Docs](https://auth0.com/docs/auth-api#!#post--users--user_id--impersonate).
|
|
87
|
+
* </caption>
|
|
88
|
+
*
|
|
89
|
+
* var settings = {
|
|
90
|
+
* impersonator_id: '{IMPERSONATOR_ID}',
|
|
91
|
+
* protocol: 'oauth2',
|
|
92
|
+
* additionalParameters: {} // Optional additional params.
|
|
93
|
+
* };
|
|
94
|
+
*
|
|
95
|
+
* auth0.users.impersonate(userId, settings, function (err, link) {
|
|
96
|
+
* if (err) {
|
|
97
|
+
* // Handle error.
|
|
98
|
+
* }
|
|
99
|
+
*
|
|
100
|
+
* console.log(link);
|
|
101
|
+
* });
|
|
102
|
+
* @param {string} userId User ID token.
|
|
103
|
+
* @param {object} settings Impersonation settings.
|
|
104
|
+
* @param {string} settings.impersonator_id Impersonator user ID.
|
|
105
|
+
* @param {string} settings.protocol The authentication protocol.
|
|
106
|
+
* @param {string} settings.token API v1 token obtained for impersonation
|
|
107
|
+
* @param {string} [settings.clientId] Client id used for impersonation. Uses the one supplied in the constructor by default.
|
|
108
|
+
* @param {Function} [cb] Callback function.
|
|
109
|
+
* @returns {Promise|undefined}
|
|
110
|
+
*/
|
|
111
|
+
impersonate(userId, settings, cb) {
|
|
112
|
+
const url = `${this.baseUrl}/users/${userId}/impersonate`;
|
|
113
|
+
|
|
114
|
+
if (userId === null || userId === undefined) {
|
|
115
|
+
throw new ArgumentError('You must specify a user ID');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (typeof userId !== 'string' || userId.trim().length === 0) {
|
|
119
|
+
throw new ArgumentError('The user ID is not valid');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (typeof settings !== 'object') {
|
|
123
|
+
throw new ArgumentError('Missing impersonation settings object');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (
|
|
127
|
+
typeof settings.impersonator_id !== 'string' ||
|
|
128
|
+
settings.impersonator_id.trim().length === 0
|
|
129
|
+
) {
|
|
130
|
+
throw new ArgumentError('impersonator_id field is required');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (typeof settings.protocol !== 'string' || settings.protocol.trim().length === 0) {
|
|
134
|
+
throw new ArgumentError('protocol field is required');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (typeof settings.token !== 'string' || settings.token.trim().length === 0) {
|
|
138
|
+
throw new ArgumentError('token field is required');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const data = { client_id: settings.clientId || this.clientId, ...settings };
|
|
142
|
+
const headers = { Authorization: `Bearer ${settings.token}`, ...this.headers };
|
|
143
|
+
// Perform the request.
|
|
144
|
+
const promise = axios({
|
|
145
|
+
method: 'POST',
|
|
146
|
+
headers,
|
|
147
|
+
data,
|
|
148
|
+
url,
|
|
149
|
+
}).then(({ data }) => data);
|
|
150
|
+
|
|
151
|
+
// Use callback if given.
|
|
152
|
+
if (cb instanceof Function) {
|
|
153
|
+
promise.then(cb.bind(null, null)).catch(cb);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return promise;
|
|
62
158
|
}
|
|
63
|
-
|
|
64
|
-
if (typeof accessToken !== 'string' || accessToken.trim().length === 0) {
|
|
65
|
-
throw new ArgumentError('Invalid access token');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Send the user access token in the Authorization header.
|
|
69
|
-
headers['Authorization'] = 'Bearer ' + accessToken;
|
|
70
|
-
|
|
71
|
-
// Perform the request.
|
|
72
|
-
var promise = axios({
|
|
73
|
-
method: 'GET',
|
|
74
|
-
url: url,
|
|
75
|
-
headers: headers
|
|
76
|
-
}).then(({ data }) => data);
|
|
77
|
-
|
|
78
|
-
// Use callback if given.
|
|
79
|
-
if (cb instanceof Function) {
|
|
80
|
-
promise.then(cb.bind(null, null)).catch(cb);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return promise;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Impersonate the user with the given user ID.
|
|
89
|
-
*
|
|
90
|
-
* @method impersonate
|
|
91
|
-
* @memberOf module:auth.UsersManager.prototype
|
|
92
|
-
*
|
|
93
|
-
* @example <caption>
|
|
94
|
-
* Gets a link that can be used once to log in as a specific user. Useful for
|
|
95
|
-
* troubleshooting. Find more information in the
|
|
96
|
-
* [API Docs](https://auth0.com/docs/auth-api#!#post--users--user_id--impersonate).
|
|
97
|
-
* </caption>
|
|
98
|
-
*
|
|
99
|
-
* var settings = {
|
|
100
|
-
* impersonator_id: '{IMPERSONATOR_ID}',
|
|
101
|
-
* protocol: 'oauth2',
|
|
102
|
-
* additionalParameters: {} // Optional additional params.
|
|
103
|
-
* };
|
|
104
|
-
*
|
|
105
|
-
* auth0.users.impersonate(userId, settings, function (err, link) {
|
|
106
|
-
* if (err) {
|
|
107
|
-
* // Handle error.
|
|
108
|
-
* }
|
|
109
|
-
*
|
|
110
|
-
* console.log(link);
|
|
111
|
-
* });
|
|
112
|
-
*
|
|
113
|
-
* @param {String} userId User ID token.
|
|
114
|
-
* @param {Object} settings Impersonation settings.
|
|
115
|
-
* @param {String} settings.impersonator_id Impersonator user ID.
|
|
116
|
-
* @param {String} settings.protocol The authentication protocol.
|
|
117
|
-
* @param {String} settings.token API v1 token obtained for impersonation
|
|
118
|
-
* @param {String} [settings.clientId] Client id used for impersonation. Uses the one supplied in the constructor by default.
|
|
119
|
-
* @param {Function} [cb]] Callback function.
|
|
120
|
-
*
|
|
121
|
-
* @return {Promise|undefined}
|
|
122
|
-
*/
|
|
123
|
-
UsersManager.prototype.impersonate = function(userId, settings, cb) {
|
|
124
|
-
var url = this.baseUrl + '/users/' + userId + '/impersonate';
|
|
125
|
-
|
|
126
|
-
if (userId === null || userId === undefined) {
|
|
127
|
-
throw new ArgumentError('You must specify a user ID');
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (typeof userId !== 'string' || userId.trim().length === 0) {
|
|
131
|
-
throw new ArgumentError('The user ID is not valid');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (typeof settings !== 'object') {
|
|
135
|
-
throw new ArgumentError('Missing impersonation settings object');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (
|
|
139
|
-
typeof settings.impersonator_id !== 'string' ||
|
|
140
|
-
settings.impersonator_id.trim().length === 0
|
|
141
|
-
) {
|
|
142
|
-
throw new ArgumentError('impersonator_id field is required');
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (typeof settings.protocol !== 'string' || settings.protocol.trim().length === 0) {
|
|
146
|
-
throw new ArgumentError('protocol field is required');
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (typeof settings.token !== 'string' || settings.token.trim().length === 0) {
|
|
150
|
-
throw new ArgumentError('token field is required');
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
var data = extend({ client_id: settings.clientId || this.clientId }, settings);
|
|
154
|
-
var headers = extend({ Authorization: `Bearer ${settings.token}` }, this.headers);
|
|
155
|
-
// Perform the request.
|
|
156
|
-
var promise = axios({
|
|
157
|
-
method: 'POST',
|
|
158
|
-
headers: headers,
|
|
159
|
-
data: data,
|
|
160
|
-
url: url
|
|
161
|
-
}).then(({ data }) => data);
|
|
162
|
-
|
|
163
|
-
// Use callback if given.
|
|
164
|
-
if (cb instanceof Function) {
|
|
165
|
-
promise.then(cb.bind(null, null)).catch(cb);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return promise;
|
|
170
|
-
};
|
|
159
|
+
}
|
|
171
160
|
|
|
172
161
|
module.exports = UsersManager;
|
package/src/auth/idToken.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
const urlDecodeB64 = function (data) {
|
|
2
2
|
return Buffer.from(data, 'base64').toString('utf8');
|
|
3
3
|
};
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Decodes a string token into the 3 parts, throws if the format is invalid
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
|
+
* @param {string} token token
|
|
9
|
+
* @returns {object}
|
|
8
10
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
const decode = function (token) {
|
|
12
|
+
const parts = token.split('.');
|
|
11
13
|
|
|
12
14
|
if (parts.length !== 3) {
|
|
13
15
|
throw new Error('ID token could not be decoded');
|
|
@@ -17,34 +19,35 @@ var decode = function(token) {
|
|
|
17
19
|
_raw: token,
|
|
18
20
|
header: JSON.parse(urlDecodeB64(parts[0])),
|
|
19
21
|
payload: JSON.parse(urlDecodeB64(parts[1])),
|
|
20
|
-
signature: parts[2]
|
|
22
|
+
signature: parts[2],
|
|
21
23
|
};
|
|
22
24
|
};
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
const DEFAULT_LEEWAY = 60; //default clock-skew, in seconds
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* Validator for ID Tokens following OIDC spec.
|
|
28
|
-
*
|
|
29
|
-
* @param
|
|
30
|
-
* @
|
|
30
|
+
*
|
|
31
|
+
* @param {string} token the string token to verify
|
|
32
|
+
* @param {object} options the options required to run this verification
|
|
33
|
+
* @returns {object} The decoded token payload, or throws an exception if validation failed
|
|
31
34
|
*/
|
|
32
|
-
|
|
35
|
+
const validate = function (token, options) {
|
|
33
36
|
if (!token) {
|
|
34
37
|
throw new Error('ID token is required but missing');
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
const decodedToken = decode(token);
|
|
38
41
|
|
|
39
42
|
// Check algorithm
|
|
40
|
-
|
|
43
|
+
const { header } = decodedToken;
|
|
41
44
|
if (header.alg !== 'RS256' && header.alg !== 'HS256') {
|
|
42
45
|
throw new Error(
|
|
43
46
|
`Signature algorithm of "${header.alg}" is not supported. Expected the ID token to be signed with "RS256" or "HS256".`
|
|
44
47
|
);
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
const { payload } = decodedToken;
|
|
48
51
|
|
|
49
52
|
// Issuer
|
|
50
53
|
if (!payload.iss || typeof payload.iss !== 'string') {
|
|
@@ -93,14 +96,14 @@ var validate = function(token, options) {
|
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
// --Time validation (epoch)--
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
const now = Math.floor(Date.now() / 1000);
|
|
100
|
+
const leeway = options.leeway || DEFAULT_LEEWAY;
|
|
98
101
|
|
|
99
102
|
// Expires at
|
|
100
103
|
if (!payload.exp || typeof payload.exp !== 'number') {
|
|
101
104
|
throw new Error('Expiration Time (exp) claim must be a number present in the ID token');
|
|
102
105
|
}
|
|
103
|
-
|
|
106
|
+
const expTime = payload.exp + leeway;
|
|
104
107
|
|
|
105
108
|
if (now > expTime) {
|
|
106
109
|
throw new Error(
|
|
@@ -147,7 +150,7 @@ var validate = function(token, options) {
|
|
|
147
150
|
);
|
|
148
151
|
}
|
|
149
152
|
|
|
150
|
-
|
|
153
|
+
const authValidUntil = payload.auth_time + options.maxAge + leeway;
|
|
151
154
|
if (now > authValidUntil) {
|
|
152
155
|
throw new Error(
|
|
153
156
|
`Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Currrent time (${now}) is after last auth at ${authValidUntil}`
|
|
@@ -159,6 +162,6 @@ var validate = function(token, options) {
|
|
|
159
162
|
};
|
|
160
163
|
|
|
161
164
|
module.exports = {
|
|
162
|
-
decode
|
|
163
|
-
validate
|
|
165
|
+
decode,
|
|
166
|
+
validate,
|
|
164
167
|
};
|