auth/index.js

  1. /** @module auth **/
  2. var util = require('util');
  3. var pkg = require('../../package.json');
  4. var utils = require('../utils');
  5. var jsonToBase64 = utils.jsonToBase64;
  6. var ArgumentError = require('../exceptions').ArgumentError;
  7. // Authenticators.
  8. var OAuthAuthenticator = require('./OAuthAuthenticator');
  9. var DatabaseAuthenticator = require('./DatabaseAuthenticator');
  10. var PasswordlessAuthenticator = require('./PasswordlessAuthenticator');
  11. // Managers
  12. var UsersManager = require('./UsersManager');
  13. var TokensManager = require('./TokensManager');
  14. var BASE_URL_FORMAT = 'https://%s';
  15. /**
  16. * @class
  17. * Authentication API SDK.
  18. *
  19. * This client must used to access Auth0's
  20. * <a href="https://auth0.com/docs/auth-api">Authentication API</a>.
  21. * @constructor
  22. * @memberOf module:auth
  23. *
  24. * @example <caption>
  25. * The <b>AuthenticationClient</b> constructor takes an <i>optional</i> client
  26. * ID, if specified it will be used as default value for all endpoints that
  27. * accept a client ID.
  28. * </caption>
  29. *
  30. * var AuthenticationClient = require('auth0'). AuthenticationClient;
  31. * var auth0 = new AuthenticationClient({
  32. * domain: '{YOUR_ACCOUNT}.auth0.com',
  33. * clientId: '{OPTIONAL_CLIENT_ID}'
  34. * });
  35. *
  36. * @param {Object} options Options for the Authentication Client
  37. * SDK.
  38. * @param {String} options.domain AuthenticationClient server domain.
  39. * @param {String} [options.clientId] Default client ID.
  40. */
  41. var AuthenticationClient = function (options) {
  42. if (!options || typeof options !== 'object') {
  43. throw new ArgumentError(
  44. 'Authentication Client SDK options must be an object'
  45. );
  46. }
  47. if (!options.domain || options.domain.length === 0) {
  48. throw new ArgumentError('Must provide a domain');
  49. }
  50. var managerOptions = {
  51. clientId: options.clientId,
  52. headers: {
  53. 'User-agent': 'node.js/' + process.version.replace('v', ''),
  54. 'Content-Type': 'application/json'
  55. },
  56. baseUrl: util.format(BASE_URL_FORMAT, options.domain)
  57. };
  58. if (options.telemetry !== false) {
  59. var telemetry = jsonToBase64(options.clientInfo || this.getClientInfo());
  60. managerOptions.headers['Auth0-Client'] = telemetry;
  61. }
  62. /**
  63. * OAuth authenticator.
  64. *
  65. * @type {OAuthAuthenticator}
  66. */
  67. this.oauth = new OAuthAuthenticator(managerOptions);
  68. /**
  69. * Database authenticator.
  70. *
  71. * @type {DatabaseAuthenticator}
  72. */
  73. this.database = new DatabaseAuthenticator(managerOptions, this.oauth);
  74. /**
  75. * Passwordless authenticator.
  76. *
  77. * @type {PasswordlessAuthenticator}
  78. */
  79. this.passwordless = new PasswordlessAuthenticator(managerOptions, this.oauth);
  80. /**
  81. * Users manager.
  82. *
  83. * @type {UsersManager}
  84. */
  85. this.users = new UsersManager(managerOptions);
  86. /**
  87. * Tokens manager.
  88. *
  89. * @type {TokensManager}
  90. */
  91. this.tokens = new TokensManager(managerOptions);
  92. };
  93. /**
  94. * Return an object with information about the current client,
  95. *
  96. * @method getClientInfo
  97. * @memberOf module:auth.AuthenticationClient.prototype
  98. *
  99. * @return {Object} Object containing client information.
  100. */
  101. AuthenticationClient.prototype.getClientInfo = function () {
  102. var clientInfo = {
  103. name: 'node-auth0',
  104. version: pkg.version,
  105. dependencies: [],
  106. environment: [{
  107. name: 'node.js',
  108. version: process.version.replace('v', '')
  109. }]
  110. };
  111. // Add the dependencies to the client info object.
  112. Object
  113. .keys(pkg.dependencies)
  114. .forEach(function (name) {
  115. clientInfo.dependencies.push({
  116. name: name,
  117. version: pkg.dependencies[name]
  118. });
  119. });
  120. return clientInfo;
  121. };
  122. /**
  123. * Start passwordless flow sending an email.
  124. *
  125. * @method requestMagicLink
  126. * @memberOf module:auth.AuthenticationClient.prototype
  127. *
  128. * @example <caption>
  129. * Given the user `email` address, it will send an email with a link. You can
  130. * then authenticate with this user opening the link and he will be
  131. * automatically logged in to the application. Optionally, you can
  132. * append/override parameters to the link (like `scope`, `redirect_uri`,
  133. * `protocol`, `response_type`, etc.) using `authParams` object.
  134. *
  135. * Find more information in the
  136. * <a href="https://auth0.com/docs/auth-api#!#post--with_email">API Docs</a>
  137. * </caption>
  138. *
  139. * var data = {
  140. * email: '{EMAIL}',
  141. * authParams: {} // Optional auth params.
  142. * };
  143. *
  144. * auth0.requestMagicLink(data, function (err) {
  145. * if (err) {
  146. * // Handle error.
  147. * }
  148. * };
  149. *
  150. * @param {Object} data User data object.
  151. * @param {String} data.email User email address.
  152. * @param {Object} [data.authParams] Authentication parameters.
  153. *
  154. * @return {Promise|undefined}
  155. */
  156. AuthenticationClient.prototype.requestMagicLink = function (data, cb) {
  157. data.send = 'link';
  158. return this.passwordless.sendEmail(data, cb);
  159. };
  160. /**
  161. * Start passwordless flow sending an email.
  162. *
  163. * @method requestEmailCode
  164. * @memberOf module:auth.AuthenticationClient.prototype
  165. *
  166. * @example <caption>
  167. * Given the user `email` address, it will send an email with a verification
  168. * code. You can then authenticate with this user using the `/oauth/ro`
  169. * endpoint using the email as username and the code as password.
  170. *
  171. * Find more information in the
  172. * <a href="https://auth0.com/docs/auth-api#!#post--with_email">API Docs</a>
  173. * </caption>
  174. *
  175. * var data = {
  176. * email: '{EMAIL}',
  177. * authParams: {} // Optional auth params.
  178. * };
  179. *
  180. * auth0.requestEmailCode(data, function (err) {
  181. * if (err) {
  182. * // Handle error.
  183. * }
  184. * };
  185. *
  186. * @param {Object} data User data object.
  187. * @param {String} data.email User email address.
  188. * @param {Object} [data.authParams] Authentication parameters.
  189. *
  190. * @return {Promise|undefined}
  191. */
  192. AuthenticationClient.prototype.requestEmailCode = function (data, cb) {
  193. data.send = 'code';
  194. return this.passwordless.sendEmail(data, cb);
  195. };
  196. /**
  197. * Start passwordless flow sending an SMS.
  198. *
  199. * @method requestSMSCode
  200. * @memberOf module:auth.AuthenticationClient.prototype
  201. *
  202. * @example <caption>
  203. * Given the user `phone_number`, it will send a SMS message with a
  204. * verification code. You can then authenticate with this user using the
  205. * `/oauth/ro` endpoint specifying `phone_number` as `username` and `code` as
  206. * `password`:
  207. * </caption>
  208. *
  209. * var data = {
  210. * phone_number: '{PHONE}'
  211. * };
  212. *
  213. * auth0.requestSMSCode(data, function (err) {
  214. * if (err) {
  215. * // Handle error.
  216. * }
  217. *
  218. * });
  219. *
  220. * @param {Object} data User data object.
  221. * @param {String} data.phone_number The user phone number.
  222. *
  223. * @return {Promise|undefined}
  224. */
  225. AuthenticationClient.prototype.requestSMSCode = function (data, cb) {
  226. var translatedData = {
  227. phone_number: data.phoneNumber || data.phone_number
  228. };
  229. return this.passwordless.sendSMS(translatedData, cb);
  230. };
  231. /**
  232. * Sign in with the given user credentials.
  233. *
  234. * @method verifySMSCode
  235. * @memberOf module:auth.AuthenticationClient.prototype
  236. *
  237. * @example <caption>
  238. * Given the user credentials (`phone_number` and `code`), it will do the
  239. * authentication on the provider and return a JSON with the `access_token`
  240. * and `id_token`.
  241. * </caption>
  242. *
  243. * var data = {
  244. * username: '{PHONE_NUMBER}',
  245. * password: '{VERIFICATION_CODE}'
  246. * };
  247. *
  248. * auth0.verifySMSCode(data, function (err) {
  249. * if (err) {
  250. * // Handle error.
  251. * }
  252. * });
  253. *
  254. * @example <caption>
  255. * The user data object has the following structure.
  256. * </caption>
  257. *
  258. * {
  259. * id_token: String,
  260. * access_token: String,
  261. * token_type: String
  262. * }
  263. *
  264. * @param {Object} data Credentials object.
  265. * @param {String} data.username Phone number.
  266. * @param {String} data.password Verification code.
  267. * @param {String} data.target Target client ID.
  268. * @param {String} data.grant_type Grant type.
  269. *
  270. * @return {Promise|undefined}
  271. */
  272. AuthenticationClient.prototype.verifySMSCode = function (data, cb) {
  273. var translatedData = {
  274. username: data.phoneNumber || data.phone_number || data.username,
  275. password: data.code || data.password
  276. };
  277. return this.passwordless.signIn(translatedData, cb);
  278. };
  279. /**
  280. * Exchange the token of the logged in user with a token that is valid to call
  281. * the API (signed with the API secret).
  282. *
  283. * @method getDelegationToken
  284. * @memberOf module:auth.AuthenticationClient.prototype
  285. *
  286. * @example <caption>
  287. * Given an existing token, this endpoint will generate a new token signed
  288. * with the target client secret. This is used to flow the identity of the
  289. * user from the application to an API or across different APIs that are
  290. * protected with different secrets. Find more information in the
  291. * <a href="https://auth0.com/docs/auth-api#!#post--delegation">API Docs</a>.
  292. * </caption>
  293. *
  294. * var data = {
  295. * id_token: '{ID_TOKEN}',
  296. * api_type: 'app',
  297. * target: '{TARGET}',
  298. * grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer'
  299. * };
  300. *
  301. * auth0.getDelegationToken(data, function (err, token) {
  302. * if (err) {
  303. * // Handle error.
  304. * }
  305. *
  306. * console.log(token);
  307. * });
  308. *
  309. * @param {Object} data Token data object.
  310. * @param {String} data.id_token The user ID token.
  311. * @param {String} data.api_type The API type (aws, firebase, etc).
  312. * @param {String} data.target The target client ID.
  313. * @param {String} data.grant_type The grant type.
  314. *
  315. * @return {Promise|undefined}
  316. */
  317. AuthenticationClient.prototype.getDelegationToken = function (data, cb) {
  318. var translatedData = {
  319. id_token: data.id_token,
  320. api_type: data.api || data.api_type,
  321. scope: data.scope,
  322. target: data.targetClientId || data.target,
  323. grant_type: data.grant_type
  324. };
  325. return this.tokens.getDelegationToken(translatedData, cb);
  326. };
  327. /**
  328. * Change password using a database or active directory service.
  329. *
  330. * @method changePassword
  331. * @memberOf module:auth.AuthenticationClient.prototype
  332. *
  333. * @example <caption>
  334. * Given the user email, the connection specified and the new password to
  335. * use, Auth0 will send a forgot password email. Once the user clicks on the
  336. * confirm password change link, the new password specified in this POST will
  337. * be set to this user. Find more information in the
  338. * <a href="https://auth0.com/docs/auth-api#!#post--dbconnections-change_password">
  339. * API Docs</a>.
  340. * </caption>
  341. *
  342. * var data = {
  343. * email: '{EMAIL}',
  344. * password: '{PASSWORD}',
  345. * connection: 'Username-Password-Authentication'
  346. * };
  347. *
  348. * auth0.changePassword(data, function (err, message) {
  349. * if (err) {
  350. * // Handle error.
  351. * }
  352. *
  353. * console.log(message);
  354. * });
  355. *
  356. * @param {Object} data User data object.
  357. * @param {String} data.email User email.
  358. * @param {String} data.password User password.
  359. * @param {String} data.connection Identity provider for the user.
  360. *
  361. * @return {Promise|undefined}
  362. */
  363. AuthenticationClient.prototype.changePassword = function (data, cb) {
  364. var translatedData = {
  365. connection: data.connection,
  366. email: data.email || data.username,
  367. password: data.password
  368. };
  369. return this.database.changePassword(data, cb);
  370. };
  371. /**
  372. * Request a change password email using a database or active directory service.
  373. *
  374. * @method requestChangePasswordEmail
  375. * @memberOf module:auth.AuthenticationClient.prototype
  376. *
  377. * @example <caption>
  378. * Given the user email, the connection specified, Auth0 will send a change
  379. * password email. once the user clicks on the confirm password change link,
  380. * the new password specified in this POST will be set to this user. Find more
  381. * information in the <a href="https://auth0.com/docs/auth-api#!#post--dbconnections-change_password>
  382. * API Docs</a>.
  383. * </caption>
  384. *
  385. * var data = {
  386. * email: '{EMAIL}',
  387. * connection: 'Username-Password-Authentication'
  388. * };
  389. *
  390. * auth0.requestChangePasswordEmail(data, function (err, message) {
  391. * if (err) {
  392. * // Handle error.
  393. * }
  394. *
  395. * console.log(message);
  396. * });
  397. *
  398. * @param {Object} data User data object.
  399. * @param {String} data.email User email.
  400. * @param {String} data.connection Identity provider for the user.
  401. *
  402. * @return {Promise|undefined}
  403. */
  404. AuthenticationClient.prototype.requestChangePasswordEmail = function (data, cb) {
  405. var translatedData = {
  406. connection: data.connection,
  407. email: data.email || data.username
  408. };
  409. return this.database.requestChangePasswordEmail(data, cb);
  410. };
  411. /**
  412. * Given an access token get the user profile linked to it.
  413. *
  414. * @method getProfile
  415. * @memberOf module:auth.AuthenticationClient.prototype
  416. *
  417. * @example <caption>
  418. * Get the user information based on the Auth0 access token (obtained during
  419. * login). Find more information in the
  420. * <a href="https://auth0.com/docs/auth-api#!#get--userinfo">API Docs</a>.
  421. * </caption>
  422. *
  423. * auth0.getProfile(data, function (err, userInfo) {
  424. * if (err) {
  425. * // Handle error.
  426. * }
  427. *
  428. * console.log(userInfo);
  429. * });
  430. *
  431. * @param {String} accessToken The user access token.
  432. *
  433. * @return {Promise|undefined}
  434. */
  435. utils.wrapPropertyMethod(AuthenticationClient, 'getProfile', 'users.getInfo');
  436. module.exports = AuthenticationClient;