auth0-lock 11.34.1 → 11.35.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.
Files changed (81) hide show
  1. package/.circleci/config.yml +1 -1
  2. package/.eslintrc.json +5 -5
  3. package/.github/workflows/codeql.yml +41 -0
  4. package/CHANGELOG.md +38 -0
  5. package/EXAMPLES.md +626 -0
  6. package/README.md +78 -653
  7. package/lib/__tests__/connection/passwordless/passwordless.js +4 -2
  8. package/lib/__tests__/engine/passwordless/social_or_email_login_screen.js +126 -0
  9. package/lib/__tests__/engine/passwordless/social_or_phone_number_login_screen.js +126 -0
  10. package/lib/connection/captcha.js +21 -6
  11. package/lib/connection/database/actions.js +5 -5
  12. package/lib/connection/database/index.js +1 -1
  13. package/lib/connection/database/login_pane.js +1 -1
  14. package/lib/connection/enterprise/actions.js +2 -2
  15. package/lib/connection/enterprise/hrd_pane.js +1 -1
  16. package/lib/connection/passwordless/actions.js +33 -11
  17. package/lib/core/index.js +12 -6
  18. package/lib/core/remote_data.js +9 -0
  19. package/lib/core/web_api/helper.js +3 -3
  20. package/lib/core/web_api/p2_api.js +6 -0
  21. package/lib/core/web_api.js +4 -0
  22. package/lib/core.js +1 -1
  23. package/lib/engine/classic/sign_up_pane.js +1 -1
  24. package/lib/engine/classic/sign_up_screen.js +1 -1
  25. package/lib/engine/passwordless/social_or_email_login_screen.js +12 -1
  26. package/lib/engine/passwordless/social_or_phone_number_login_screen.js +12 -1
  27. package/lib/field/captcha/captcha_pane.js +4 -3
  28. package/lib/field/email/email_pane.js +1 -1
  29. package/lib/field/index.js +1 -1
  30. package/lib/field/password/password_pane.js +1 -1
  31. package/lib/field/username/username_pane.js +1 -1
  32. package/lib/i18n/af.js +3 -1
  33. package/lib/i18n/ar.js +3 -1
  34. package/lib/i18n/az.js +3 -1
  35. package/lib/i18n/bg.js +3 -1
  36. package/lib/i18n/ca.js +3 -1
  37. package/lib/i18n/cs.js +3 -1
  38. package/lib/i18n/da.js +3 -1
  39. package/lib/i18n/de.js +3 -1
  40. package/lib/i18n/el.js +3 -1
  41. package/lib/i18n/en.js +3 -1
  42. package/lib/i18n/es.js +3 -1
  43. package/lib/i18n/et.js +3 -1
  44. package/lib/i18n/fa.js +3 -1
  45. package/lib/i18n/fi.js +3 -1
  46. package/lib/i18n/fr.js +3 -1
  47. package/lib/i18n/he.js +3 -1
  48. package/lib/i18n/hr.js +3 -1
  49. package/lib/i18n/hu.js +3 -1
  50. package/lib/i18n/id.js +3 -1
  51. package/lib/i18n/it.js +3 -1
  52. package/lib/i18n/ja.js +3 -1
  53. package/lib/i18n/ko.js +3 -1
  54. package/lib/i18n/lt.js +3 -1
  55. package/lib/i18n/lv.js +3 -1
  56. package/lib/i18n/ms.js +3 -1
  57. package/lib/i18n/nb.js +3 -1
  58. package/lib/i18n/nl.js +3 -1
  59. package/lib/i18n/nn.js +3 -1
  60. package/lib/i18n/no.js +3 -1
  61. package/lib/i18n/pl.js +3 -1
  62. package/lib/i18n/pt-br.js +3 -1
  63. package/lib/i18n/pt.js +3 -1
  64. package/lib/i18n/ro.js +3 -1
  65. package/lib/i18n/ru.js +3 -1
  66. package/lib/i18n/sk.js +3 -1
  67. package/lib/i18n/sl.js +3 -1
  68. package/lib/i18n/sr.js +3 -1
  69. package/lib/i18n/sv.js +3 -1
  70. package/lib/i18n/tr.js +3 -1
  71. package/lib/i18n/ua.js +3 -1
  72. package/lib/i18n/uk.js +3 -1
  73. package/lib/i18n/vi.js +3 -1
  74. package/lib/i18n/zh-tw.js +3 -1
  75. package/lib/i18n/zh.js +3 -1
  76. package/lib/i18n.js +1 -1
  77. package/lib/lock.js +1 -1
  78. package/lib/passwordless.js +1 -1
  79. package/lib/ui/box/multisize_slide.js +1 -1
  80. package/opslevel.yml +6 -0
  81. package/package.json +22 -21
@@ -52,7 +52,8 @@ describe('passwordless actions', function () {
52
52
  jest.mock('core/web_api', function () {
53
53
  return {
54
54
  startPasswordless: jest.fn(),
55
- passwordlessVerify: jest.fn()
55
+ passwordlessVerify: jest.fn(),
56
+ getPasswordlessChallenge: jest.fn()
56
57
  };
57
58
  });
58
59
  jest.mock('core/actions', function () {
@@ -91,7 +92,8 @@ describe('passwordless actions', function () {
91
92
  connections: jest.fn(),
92
93
  useCustomPasswordlessConnection: jest.fn(function () {
93
94
  return false;
94
- })
95
+ }),
96
+ passwordlessCaptcha: jest.fn()
95
97
  };
96
98
  });
97
99
  jest.mock('store/index', function () {
@@ -0,0 +1,126 @@
1
+ 'use strict';
2
+
3
+ var _react = require('react');
4
+
5
+ var _react2 = _interopRequireDefault(_react);
6
+
7
+ var _testUtils = require('testUtils');
8
+
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+
11
+ jest.mock('connection/enterprise');
12
+ jest.mock('core/index');
13
+
14
+ jest.mock('field/social/social_buttons_pane', function () {
15
+ return (0, _testUtils.mockComponent)('social_buttons_pane');
16
+ });
17
+ jest.mock('field/email/email_pane', function () {
18
+ return (0, _testUtils.mockComponent)('email_pane');
19
+ });
20
+ jest.mock('field/captcha/captcha_pane', function () {
21
+ return (0, _testUtils.mockComponent)('captcha_pane');
22
+ });
23
+ jest.mock('core/pane_separator', function () {
24
+ return (0, _testUtils.mockComponent)('pane_separator');
25
+ });
26
+ jest.mock('connection/database/sign_up_terms', function () {
27
+ return (0, _testUtils.mockComponent)('sign_up_terms');
28
+ });
29
+ jest.mock('connection/passwordless/index', function () {
30
+ return {
31
+ isEmail: jest.fn()
32
+ };
33
+ });
34
+
35
+ var getComponent = function getComponent() {
36
+ var SocialOrEmailScreen = require('engine/passwordless/social_or_email_login_screen').default;
37
+ var screen = new SocialOrEmailScreen();
38
+ return screen.render();
39
+ };
40
+
41
+ describe('email passwordless', function () {
42
+ beforeEach(function () {
43
+ jest.resetModules();
44
+ jest.resetAllMocks();
45
+
46
+ jest.mock('connection/database/index', function () {
47
+ return {
48
+ hasScreen: function hasScreen() {
49
+ return false;
50
+ },
51
+ databaseUsernameValue: jest.fn()
52
+ };
53
+ });
54
+
55
+ jest.mock('connection/database/actions', function () {
56
+ return {
57
+ cancelMFALogin: jest.fn(),
58
+ logIn: jest.fn()
59
+ };
60
+ });
61
+
62
+ jest.mock('core/signed_in_confirmation', function () {
63
+ return {
64
+ renderSignedInConfirmation: jest.fn()
65
+ };
66
+ });
67
+
68
+ jest.mock('connection/enterprise', function () {
69
+ return {
70
+ isHRDEmailValid: jest.fn(function () {
71
+ return false;
72
+ }),
73
+ isHRDDomain: jest.fn(function () {
74
+ return true;
75
+ })
76
+ };
77
+ });
78
+
79
+ jest.mock('core/index', function () {
80
+ return {
81
+ hasSomeConnections: jest.fn(function () {
82
+ return true;
83
+ }),
84
+ passwordlessCaptcha: jest.fn()
85
+ };
86
+ });
87
+ });
88
+
89
+ var defaultProps = {
90
+ i18n: {
91
+ str: function str() {
92
+ for (var _len = arguments.length, keys = Array(_len), _key = 0; _key < _len; _key++) {
93
+ keys[_key] = arguments[_key];
94
+ }
95
+
96
+ return keys.join(',');
97
+ },
98
+ html: function html() {
99
+ for (var _len2 = arguments.length, keys = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
100
+ keys[_key2] = arguments[_key2];
101
+ }
102
+
103
+ return keys.join(',');
104
+ }
105
+ },
106
+ model: 'model'
107
+ };
108
+
109
+ it('renders correctly', function () {
110
+ var Component = getComponent();
111
+
112
+ (0, _testUtils.expectComponent)(_react2.default.createElement(Component, defaultProps)).toMatchSnapshot();
113
+ });
114
+
115
+ it('renders a captcha', function () {
116
+ var Component = getComponent();
117
+
118
+ require('core/index').passwordlessCaptcha.mockReturnValue({
119
+ get: function get() {
120
+ return true;
121
+ }
122
+ });
123
+
124
+ (0, _testUtils.expectComponent)(_react2.default.createElement(Component, defaultProps)).toMatchSnapshot();
125
+ });
126
+ });
@@ -0,0 +1,126 @@
1
+ 'use strict';
2
+
3
+ var _react = require('react');
4
+
5
+ var _react2 = _interopRequireDefault(_react);
6
+
7
+ var _testUtils = require('testUtils');
8
+
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+
11
+ jest.mock('connection/enterprise');
12
+ jest.mock('core/index');
13
+
14
+ jest.mock('field/social/social_buttons_pane', function () {
15
+ return (0, _testUtils.mockComponent)('social_buttons_pane');
16
+ });
17
+ jest.mock('field/phone-number/phone_number_pane', function () {
18
+ return (0, _testUtils.mockComponent)('phone_number_pane');
19
+ });
20
+ jest.mock('field/captcha/captcha_pane', function () {
21
+ return (0, _testUtils.mockComponent)('captcha_pane');
22
+ });
23
+ jest.mock('core/pane_separator', function () {
24
+ return (0, _testUtils.mockComponent)('pane_separator');
25
+ });
26
+ jest.mock('connection/database/sign_up_terms', function () {
27
+ return (0, _testUtils.mockComponent)('sign_up_terms');
28
+ });
29
+ jest.mock('connection/passwordless/index', function () {
30
+ return {
31
+ isEmail: jest.fn()
32
+ };
33
+ });
34
+
35
+ var getComponent = function getComponent() {
36
+ var SocialOrPhoneNumberScreen = require('engine/passwordless/social_or_phone_number_login_screen').default;
37
+ var screen = new SocialOrPhoneNumberScreen();
38
+ return screen.render();
39
+ };
40
+
41
+ describe('sms passwordless', function () {
42
+ beforeEach(function () {
43
+ jest.resetModules();
44
+ jest.resetAllMocks();
45
+
46
+ jest.mock('connection/database/index', function () {
47
+ return {
48
+ hasScreen: function hasScreen() {
49
+ return false;
50
+ },
51
+ databaseUsernameValue: jest.fn()
52
+ };
53
+ });
54
+
55
+ jest.mock('connection/database/actions', function () {
56
+ return {
57
+ cancelMFALogin: jest.fn(),
58
+ logIn: jest.fn()
59
+ };
60
+ });
61
+
62
+ jest.mock('core/signed_in_confirmation', function () {
63
+ return {
64
+ renderSignedInConfirmation: jest.fn()
65
+ };
66
+ });
67
+
68
+ jest.mock('connection/enterprise', function () {
69
+ return {
70
+ isHRDEmailValid: jest.fn(function () {
71
+ return false;
72
+ }),
73
+ isHRDDomain: jest.fn(function () {
74
+ return true;
75
+ })
76
+ };
77
+ });
78
+
79
+ jest.mock('core/index', function () {
80
+ return {
81
+ hasSomeConnections: jest.fn(function () {
82
+ return true;
83
+ }),
84
+ passwordlessCaptcha: jest.fn()
85
+ };
86
+ });
87
+ });
88
+
89
+ var defaultProps = {
90
+ i18n: {
91
+ str: function str() {
92
+ for (var _len = arguments.length, keys = Array(_len), _key = 0; _key < _len; _key++) {
93
+ keys[_key] = arguments[_key];
94
+ }
95
+
96
+ return keys.join(',');
97
+ },
98
+ html: function html() {
99
+ for (var _len2 = arguments.length, keys = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
100
+ keys[_key2] = arguments[_key2];
101
+ }
102
+
103
+ return keys.join(',');
104
+ }
105
+ },
106
+ model: 'model'
107
+ };
108
+
109
+ it('renders correctly', function () {
110
+ var Component = getComponent();
111
+
112
+ (0, _testUtils.expectComponent)(_react2.default.createElement(Component, defaultProps)).toMatchSnapshot();
113
+ });
114
+
115
+ it('renders a captcha', function () {
116
+ var Component = getComponent();
117
+
118
+ require('core/index').passwordlessCaptcha.mockReturnValue({
119
+ get: function get() {
120
+ return true;
121
+ }
122
+ });
123
+
124
+ (0, _testUtils.expectComponent)(_react2.default.createElement(Component, defaultProps)).toMatchSnapshot();
125
+ });
126
+ });
@@ -32,11 +32,14 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
32
32
  *
33
33
  * @param {Object} m model
34
34
  * @param {Number} id
35
+ * @param {Boolean} isPasswordless Whether the captcha is being rendered in a passwordless flow
35
36
  */
36
37
  function showMissingCaptcha(m, id) {
37
- var captchaConfig = l.captcha(m);
38
+ var isPasswordless = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
38
39
 
39
- var captchaError = captchaConfig.get('provider') === 'recaptcha_v2' ? 'invalid_recaptcha' : 'invalid_captcha';
40
+ var captchaConfig = isPasswordless ? l.passwordlessCaptcha(m) : l.captcha(m);
41
+
42
+ var captchaError = captchaConfig.get('provider') === 'recaptcha_v2' || captchaConfig.get('provider') === 'recaptcha_enterprise' ? 'invalid_recaptcha' : 'invalid_captcha';
40
43
 
41
44
  var errorMessage = i18n.html(m, ['error', 'login', captchaError]);
42
45
 
@@ -53,13 +56,14 @@ function showMissingCaptcha(m, id) {
53
56
  *
54
57
  * @param {Object} m model
55
58
  * @param {Object} params
59
+ * @param {Boolean} isPasswordless Whether the captcha is being rendered in a passwordless flow
56
60
  * @param {Object} fields
57
61
  *
58
62
  * @returns {Boolean} returns true if is required and missing the response from the user
59
63
  */
60
- function setCaptchaParams(m, params, fields) {
61
- var captchaConfig = l.captcha(m);
62
- var isCaptchaRequired = captchaConfig && l.captcha(m).get('required');
64
+ function setCaptchaParams(m, params, isPasswordless, fields) {
65
+ var captchaConfig = isPasswordless ? l.passwordlessCaptcha(m) : l.captcha(m);
66
+ var isCaptchaRequired = captchaConfig && captchaConfig.get('required');
63
67
 
64
68
  if (!isCaptchaRequired) {
65
69
  return true;
@@ -79,10 +83,21 @@ function setCaptchaParams(m, params, fields) {
79
83
  * Get a new challenge and display the new captcha image.
80
84
  *
81
85
  * @param {number} id The id of the Lock instance.
86
+ * @param {Boolean} isPasswordless Whether the captcha is being rendered in a passwordless flow.
82
87
  * @param {boolean} wasInvalid A boolean indicating if the previous captcha was invalid.
83
88
  * @param {Function} [next] A callback.
84
89
  */
85
- function swapCaptcha(id, wasInvalid, next) {
90
+ function swapCaptcha(id, isPasswordless, wasInvalid, next) {
91
+ if (isPasswordless) {
92
+ return _web_api2.default.getPasswordlessChallenge(id, function (err, newCaptcha) {
93
+ if (!err && newCaptcha) {
94
+ (0, _index3.swap)(_index3.updateEntity, 'lock', id, l.setPasswordlessCaptcha, newCaptcha, wasInvalid);
95
+ }
96
+ if (next) {
97
+ next();
98
+ }
99
+ });
100
+ }
86
101
  return _web_api2.default.getChallenge(id, function (err, newCaptcha) {
87
102
  if (!err && newCaptcha) {
88
103
  (0, _index3.swap)(_index3.updateEntity, 'lock', id, l.setCaptcha, newCaptcha, wasInvalid);
@@ -57,7 +57,7 @@ function logIn(id) {
57
57
  };
58
58
 
59
59
  var fields = [usernameField, 'password'];
60
- var isCaptchaValid = (0, _captcha.setCaptchaParams)(m, params, fields);
60
+ var isCaptchaValid = (0, _captcha.setCaptchaParams)(m, params, false, fields);
61
61
 
62
62
  if (!isCaptchaValid) {
63
63
  return (0, _captcha.showMissingCaptcha)(m, id);
@@ -77,7 +77,7 @@ function logIn(id) {
77
77
 
78
78
  if (error) {
79
79
  var wasInvalid = error && error.code === 'invalid_captcha';
80
- return (0, _captcha.swapCaptcha)(id, wasInvalid, next);
80
+ return (0, _captcha.swapCaptcha)(id, false, wasInvalid, next);
81
81
  }
82
82
 
83
83
  next();
@@ -114,7 +114,7 @@ function signUp(id) {
114
114
  autoLogin: (0, _index4.shouldAutoLogin)(m)
115
115
  };
116
116
 
117
- var isCaptchaValid = (0, _captcha.setCaptchaParams)(m, params, fields);
117
+ var isCaptchaValid = (0, _captcha.setCaptchaParams)(m, params, false, fields);
118
118
  if (!isCaptchaValid) {
119
119
  return (0, _captcha.showMissingCaptcha)(m, id);
120
120
  }
@@ -157,7 +157,7 @@ function signUp(id) {
157
157
 
158
158
  var wasInvalidCaptcha = error && error.code === 'invalid_captcha';
159
159
 
160
- (0, _captcha.swapCaptcha)(id, wasInvalidCaptcha, function () {
160
+ (0, _captcha.swapCaptcha)(id, false, wasInvalidCaptcha, function () {
161
161
  setTimeout(function () {
162
162
  return signUpError(id, error);
163
163
  }, 250);
@@ -257,7 +257,7 @@ function signUpError(id, error) {
257
257
 
258
258
  if (errorKey === 'invalid_captcha') {
259
259
  errorMessage = i18n.html(m, ['error', 'login', errorKey]);
260
- return (0, _captcha.swapCaptcha)(id, true, function () {
260
+ return (0, _captcha.swapCaptcha)(id, false, true, function () {
261
261
  (0, _index.swap)(_index.updateEntity, 'lock', id, l.setSubmitting, false, errorMessage);
262
262
  });
263
263
  }
@@ -73,7 +73,7 @@ function initDatabase(m, options) {
73
73
 
74
74
  function assertMaybeBoolean(opts, name) {
75
75
  var valid = opts[name] === undefined || typeof opts[name] === 'boolean';
76
- if (!valid) l.warn(opts, 'The `' + name + '` option will be ignored, because it is not a booelan.');
76
+ if (!valid) l.warn(opts, 'The `' + name + '` option will be ignored, because it is not a boolean.');
77
77
  return valid;
78
78
  }
79
79
 
@@ -112,7 +112,7 @@ var LoginPane = function (_React$Component) {
112
112
  });
113
113
 
114
114
  var captchaPane = l.captcha(lock) && l.captcha(lock).get('required') && ((0, _enterprise.isHRDDomain)(lock, (0, _database.databaseUsernameValue)(lock)) || !sso) ? _react2.default.createElement(_captcha_pane2.default, { i18n: i18n, lock: lock, onReload: function onReload() {
115
- return (0, _captcha.swapCaptcha)(l.id(lock), false);
115
+ return (0, _captcha.swapCaptcha)(l.id(lock), false, false);
116
116
  } }) : null;
117
117
 
118
118
  var dontRememberPassword = showForgotPasswordLink && (0, _index.hasScreen)(lock, 'forgotPassword') ? _react2.default.createElement(
@@ -70,7 +70,7 @@ function logIn(id) {
70
70
  return logInSSO(id, ssoConnection, params);
71
71
  }
72
72
 
73
- var isCaptchaValid = (0, _captcha.setCaptchaParams)(m, params, fields);
73
+ var isCaptchaValid = (0, _captcha.setCaptchaParams)(m, params, false, fields);
74
74
 
75
75
  if (!isCaptchaValid && !ssoConnection) {
76
76
  return (0, _captcha.showMissingCaptcha)(m, id);
@@ -95,7 +95,7 @@ function logInActiveFlow(id, params) {
95
95
  login_hint: username
96
96
  }), function (id, error, fields, next) {
97
97
  var wasCaptchaInvalid = error && error.code === 'invalid captcha';
98
- (0, _captcha.swapCaptcha)(id, wasCaptchaInvalid, next);
98
+ (0, _captcha.swapCaptcha)(id, false, wasCaptchaInvalid, next);
99
99
  });
100
100
  }
101
101
 
@@ -57,7 +57,7 @@ var HRDPane = function (_React$Component) {
57
57
 
58
58
 
59
59
  var captchaPane = l.captcha(model) && l.captcha(model).get('required') ? _react2.default.createElement(_captcha_pane2.default, { i18n: i18n, lock: model, onReload: function onReload() {
60
- return (0, _captcha.swapCaptcha)(l.id(model), false);
60
+ return (0, _captcha.swapCaptcha)(l.id(model), false, false);
61
61
  } }) : null;
62
62
 
63
63
  return _react2.default.createElement(
@@ -13,8 +13,6 @@ exports.logIn = logIn;
13
13
  exports.restart = restart;
14
14
  exports.toggleTermsAcceptance = toggleTermsAcceptance;
15
15
 
16
- var _immutable = require('immutable');
17
-
18
16
  var _index = require('../../store/index');
19
17
 
20
18
  var _actions = require('../../core/actions');
@@ -39,23 +37,35 @@ var _i18n = require('../../i18n');
39
37
 
40
38
  var i18n = _interopRequireWildcard(_i18n);
41
39
 
40
+ var _captcha = require('../captcha');
41
+
42
42
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
43
43
 
44
44
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
45
45
 
46
- function getErrorMessage(m, error) {
46
+ function getErrorMessage(m, id, error) {
47
47
  var key = error.error;
48
48
 
49
49
  if (error.error === 'sms_provider_error' && (error.description || '').indexOf('(Code: 21211)') > -1) {
50
50
  key = 'bad.phone_number';
51
51
  }
52
52
 
53
+ if (error.code === 'invalid_captcha') {
54
+ var captchaConfig = l.passwordlessCaptcha(m);
55
+ key = captchaConfig.get('provider') === 'recaptcha_v2' || captchaConfig.get('provider') === 'recaptcha_enterprise' ? 'invalid_recaptcha' : 'invalid_captcha';
56
+ }
57
+
53
58
  return i18n.html(m, ['error', 'passwordless', key]) || i18n.html(m, ['error', 'passwordless', 'lock.fallback']);
54
59
  }
55
60
 
61
+ function swapCaptchaAfterError(id, error) {
62
+ var wasCaptchaInvalid = error && error.code === 'invalid_captcha';
63
+ (0, _captcha.swapCaptcha)(id, true, wasCaptchaInvalid);
64
+ }
65
+
56
66
  function requestPasswordlessEmail(id) {
57
67
  (0, _actions.validateAndSubmit)(id, ['email'], function (m) {
58
- sendEmail(m, requestPasswordlessEmailSuccess, requestPasswordlessEmailError);
68
+ sendEmail(m, id, requestPasswordlessEmailSuccess, requestPasswordlessEmailError);
59
69
  });
60
70
  }
61
71
 
@@ -68,14 +78,15 @@ function requestPasswordlessEmailSuccess(id) {
68
78
 
69
79
  function requestPasswordlessEmailError(id, error) {
70
80
  var m = (0, _index.read)(_index.getEntity, 'lock', id);
71
- var errorMessage = getErrorMessage(m, error);
72
- return (0, _index.swap)(_index.updateEntity, 'lock', id, l.setSubmitting, false, errorMessage);
81
+ var errorMessage = getErrorMessage(m, id, error);
82
+ (0, _index.swap)(_index.updateEntity, 'lock', id, l.setSubmitting, false, errorMessage);
83
+ swapCaptchaAfterError(id, error);
73
84
  }
74
85
 
75
86
  function resendEmail(id) {
76
87
  (0, _index.swap)(_index.updateEntity, 'lock', id, _index4.resend);
77
88
  var m = (0, _index.read)(_index.getEntity, 'lock', id);
78
- sendEmail(m, resendEmailSuccess, resendEmailError);
89
+ sendEmail(m, id, resendEmailSuccess, resendEmailError);
79
90
  }
80
91
 
81
92
  function resendEmailSuccess(id) {
@@ -92,7 +103,7 @@ function getPasswordlessConnectionName(m, defaultPasswordlessConnection) {
92
103
  return connections.size > 0 && l.useCustomPasswordlessConnection(m) ? connections.first().get('name') : defaultPasswordlessConnection;
93
104
  }
94
105
 
95
- function sendEmail(m, successFn, errorFn) {
106
+ function sendEmail(m, id, successFn, errorFn) {
96
107
  var params = {
97
108
  connection: getPasswordlessConnectionName(m, 'email'),
98
109
  email: c.getFieldValue(m, 'email'),
@@ -102,6 +113,11 @@ function sendEmail(m, successFn, errorFn) {
102
113
  if ((0, _index4.isSendLink)(m) && !l.auth.params(m).isEmpty()) {
103
114
  params.authParams = l.auth.params(m).toJS();
104
115
  }
116
+ var isCaptchaValid = (0, _captcha.setCaptchaParams)(m, params, true, []);
117
+
118
+ if (!isCaptchaValid) {
119
+ return (0, _captcha.showMissingCaptcha)(m, id, true);
120
+ }
105
121
 
106
122
  _web_api2.default.startPasswordless(l.id(m), params, function (error) {
107
123
  if (error) {
@@ -121,6 +137,10 @@ function sendSMS(id) {
121
137
  phoneNumber: (0, _phone_number.phoneNumberWithDiallingCode)(m),
122
138
  send: (0, _index4.send)(m)
123
139
  };
140
+ var isCaptchaValid = (0, _captcha.setCaptchaParams)(m, params, true, []);
141
+ if (!isCaptchaValid) {
142
+ return (0, _captcha.showMissingCaptcha)(m, id, true);
143
+ }
124
144
  _web_api2.default.startPasswordless(id, params, function (error) {
125
145
  if (error) {
126
146
  setTimeout(function () {
@@ -143,9 +163,10 @@ function sendSMSSuccess(id) {
143
163
 
144
164
  function sendSMSError(id, error) {
145
165
  var m = (0, _index.read)(_index.getEntity, 'lock', id);
146
- var errorMessage = getErrorMessage(m, error);
166
+ var errorMessage = getErrorMessage(m, id, error);
147
167
  l.emitAuthorizationErrorEvent(m, error);
148
- return (0, _index.swap)(_index.updateEntity, 'lock', id, l.setSubmitting, false, errorMessage);
168
+ (0, _index.swap)(_index.updateEntity, 'lock', id, l.setSubmitting, false, errorMessage);
169
+ swapCaptchaAfterError(id, error);
149
170
  }
150
171
 
151
172
  function logIn(id) {
@@ -166,7 +187,7 @@ function logIn(id) {
166
187
  var errorMessage = void 0;
167
188
  if (error) {
168
189
  var _m = (0, _index.read)(_index.getEntity, 'lock', id);
169
- errorMessage = getErrorMessage(_m, error);
190
+ errorMessage = getErrorMessage(_m, id, error);
170
191
  if (error.logToConsole) {
171
192
  console.error(error.description);
172
193
  }
@@ -180,6 +201,7 @@ function logIn(id) {
180
201
 
181
202
  function restart(id) {
182
203
  (0, _index.swap)(_index.updateEntity, 'lock', id, _index4.restartPasswordless);
204
+ (0, _captcha.swapCaptcha)(id, true, false);
183
205
  }
184
206
 
185
207
  function toggleTermsAcceptance(id) {
package/lib/core/index.js CHANGED
@@ -39,7 +39,9 @@ exports.setLoggedIn = setLoggedIn;
39
39
  exports.loggedIn = loggedIn;
40
40
  exports.defaultADUsernameFromEmailPrefix = defaultADUsernameFromEmailPrefix;
41
41
  exports.setCaptcha = setCaptcha;
42
+ exports.setPasswordlessCaptcha = setPasswordlessCaptcha;
42
43
  exports.captcha = captcha;
44
+ exports.passwordlessCaptcha = passwordlessCaptcha;
43
45
  exports.prefill = prefill;
44
46
  exports.warn = warn;
45
47
  exports.error = error;
@@ -572,15 +574,19 @@ function setCaptcha(m, value, wasInvalid) {
572
574
  return set(m, 'captcha', _immutable2.default.fromJS(value));
573
575
  }
574
576
 
577
+ function setPasswordlessCaptcha(m, value, wasInvalid) {
578
+ m = captchaField.reset(m, wasInvalid);
579
+ return set(m, 'passwordlessCaptcha', _immutable2.default.fromJS(value));
580
+ }
581
+
575
582
  function captcha(m) {
576
- //some tests send an string as model.
577
- // https://github.com/auth0/lock/blob/82f56187698528699478bd429858cf91e387763c/src/__tests__/engine/classic/sign_up_pane.test.jsx#L28
578
- if ((typeof m === 'undefined' ? 'undefined' : _typeof(m)) !== 'object') {
579
- return;
580
- }
581
583
  return get(m, 'captcha');
582
584
  }
583
585
 
586
+ function passwordlessCaptcha(m) {
587
+ return get(m, 'passwordlessCaptcha');
588
+ }
589
+
584
590
  function prefill(m) {
585
591
  return get(m, 'prefill', {});
586
592
  }
@@ -779,7 +785,7 @@ function loginErrorMessage(m, error, type) {
779
785
 
780
786
  if (code === 'invalid_captcha') {
781
787
  var currentCaptcha = get(m, 'captcha');
782
- if (currentCaptcha && currentCaptcha.get('provider') === 'recaptcha_v2') {
788
+ if (currentCaptcha && (currentCaptcha.get('provider') === 'recaptcha_v2' || currentCaptcha.get('provider') === 'recaptcha_enterprise')) {
783
789
  code = 'invalid_recaptcha';
784
790
  }
785
791
  }
@@ -98,5 +98,14 @@ function syncRemoteData(m) {
98
98
  successFn: _index2.setCaptcha
99
99
  });
100
100
 
101
+ m = (0, _sync2.default)(m, 'passwordlessCaptcha', {
102
+ syncFn: function syncFn(m, cb) {
103
+ _web_api2.default.getPasswordlessChallenge(m.get('id'), function (err, r) {
104
+ cb(null, r);
105
+ });
106
+ },
107
+ successFn: _index2.setPasswordlessCaptcha
108
+ });
109
+
101
110
  return m;
102
111
  } // shouldn't depend on this
@@ -21,8 +21,8 @@ function normalizeError(error, domain) {
21
21
 
22
22
  // TODO: the following checks were copied from https://github.com/auth0/lock/blob/0a5abf1957c9bb746b0710b274d0feed9b399958/index.js#L1263-L1288
23
23
  // Some of the checks are missing because I couldn't reproduce them and I'm
24
- // affraid they'll break existent functionality if add them.
25
- // We need a better errror handling story in auth0.js.
24
+ // afraid they'll break existent functionality if add them.
25
+ // We need a better error handling story in auth0.js.
26
26
 
27
27
  if (error.status === 'User closed the popup window') {
28
28
  // {
@@ -176,5 +176,5 @@ function trimAuthParams() {
176
176
  }
177
177
 
178
178
  function getVersion() {
179
- return '11.34.1';
179
+ return '11.35.0';
180
180
  }
@@ -206,6 +206,12 @@ var Auth0APIClient = function () {
206
206
  return (_client$client2 = this.client.client).getChallenge.apply(_client$client2, arguments);
207
207
  };
208
208
 
209
+ Auth0APIClient.prototype.getPasswordlessChallenge = function getPasswordlessChallenge() {
210
+ var _client$client$passwo;
211
+
212
+ return (_client$client$passwo = this.client.client.passwordless).getChallenge.apply(_client$client$passwo, arguments);
213
+ };
214
+
209
215
  Auth0APIClient.prototype.getUserCountry = function getUserCountry(cb) {
210
216
  return this.client.client.getUserCountry(cb);
211
217
  };
@@ -75,6 +75,10 @@ var Auth0WebAPI = function () {
75
75
  return this.clients[lockID].getChallenge(callback);
76
76
  };
77
77
 
78
+ Auth0WebAPI.prototype.getPasswordlessChallenge = function getPasswordlessChallenge(lockID, callback) {
79
+ return this.clients[lockID].getPasswordlessChallenge(callback);
80
+ };
81
+
78
82
  Auth0WebAPI.prototype.getSSOData = function getSSOData(lockID) {
79
83
  var _clients$lockID;
80
84