auth0-lock 14.1.0 → 14.2.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/.github/workflows/claude-code-review.yml +18 -0
- package/.github/workflows/codeql.yml +3 -3
- package/.version +1 -1
- package/CHANGELOG.md +9 -0
- package/README.md +3 -2
- package/lib/__tests__/core/remote_data.js +133 -2
- package/lib/core/actions.js +1 -1
- package/lib/core/remote_data.js +20 -8
- package/lib/core/web_api/helper.js +1 -1
- package/lib/field/captcha/captcha_pane.js +5 -0
- package/lib/i18n.js +1 -1
- package/lib/lock.js +1 -1
- package/lib/passwordless.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Claude Code PR Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issue_comment:
|
|
5
|
+
types: [created]
|
|
6
|
+
pull_request_review_comment:
|
|
7
|
+
types: [created]
|
|
8
|
+
pull_request_review:
|
|
9
|
+
types: [submitted]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
claude-review:
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
issues: write
|
|
16
|
+
pull-requests: write
|
|
17
|
+
id-token: write
|
|
18
|
+
uses: auth0/auth0-ai-pr-analyzer-gh-action/.github/workflows/claude-code-review.yml@main
|
|
@@ -40,15 +40,15 @@ jobs:
|
|
|
40
40
|
uses: actions/checkout@v4
|
|
41
41
|
|
|
42
42
|
- name: Initialize CodeQL
|
|
43
|
-
uses: github/codeql-action/init@
|
|
43
|
+
uses: github/codeql-action/init@v4
|
|
44
44
|
with:
|
|
45
45
|
languages: ${{ matrix.language }}
|
|
46
46
|
queries: +security-and-quality
|
|
47
47
|
|
|
48
48
|
- name: Autobuild
|
|
49
|
-
uses: github/codeql-action/autobuild@
|
|
49
|
+
uses: github/codeql-action/autobuild@v4
|
|
50
50
|
|
|
51
51
|
- name: Perform CodeQL Analysis
|
|
52
|
-
uses: github/codeql-action/analyze@
|
|
52
|
+
uses: github/codeql-action/analyze@v4
|
|
53
53
|
with:
|
|
54
54
|
category: '/language:${{ matrix.language }}'
|
package/.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v14.
|
|
1
|
+
v14.2.0
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## [v14.2.0](https://github.com/auth0/lock/tree/v14.2.0) (2025-10-21)
|
|
4
|
+
[Full Changelog](https://github.com/auth0/lock/compare/v14.1.0...v14.2.0)
|
|
5
|
+
|
|
6
|
+
**Added**
|
|
7
|
+
- feat: add Claude Code PR Review workflow [\#2679](https://github.com/auth0/lock/pull/2679) ([ankita10119](https://github.com/ankita10119))
|
|
8
|
+
|
|
9
|
+
**Fixed**
|
|
10
|
+
- fix: captcha not rendering for initial signup screen in classic login [\#2677](https://github.com/auth0/lock/pull/2677) ([paebanks](https://github.com/paebanks))
|
|
11
|
+
|
|
3
12
|
## [v14.1.0](https://github.com/auth0/lock/tree/v14.1.0) (2025-09-12)
|
|
4
13
|
[Full Changelog](https://github.com/auth0/lock/compare/v14.0.0...v14.1.0)
|
|
5
14
|
|
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|

|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://github.com/auth0/lock/actions/workflows/test.yml)
|
|
6
|
+
[](https://deepwiki.com/auth0/lock)
|
|
6
7
|
|
|
7
8
|
> :warning: Lock is built using React 18 from v12 onwards. Getting issues? Please [submit a bug report](https://github.com/auth0/lock/issues/new?assignees=&labels=bug+report,v12&template=report_a_bug.md&title=).
|
|
8
9
|
|
|
@@ -30,7 +31,7 @@ From CDN
|
|
|
30
31
|
|
|
31
32
|
```html
|
|
32
33
|
<!-- Latest patch release (recommended for production) -->
|
|
33
|
-
<script src="https://cdn.auth0.com/js/lock/14.
|
|
34
|
+
<script src="https://cdn.auth0.com/js/lock/14.2.0/lock.min.js"></script>
|
|
34
35
|
```
|
|
35
36
|
|
|
36
37
|
### Configure Auth0
|
|
@@ -137,4 +138,4 @@ Please do not report security vulnerabilities on the public GitHub issue tracker
|
|
|
137
138
|
</p>
|
|
138
139
|
<p align="center">
|
|
139
140
|
This project is licensed under the MIT license. See the <a href="https://github.com/auth0/lock/blob/master/LICENSE"> LICENSE</a> file for more info.
|
|
140
|
-
</p>
|
|
141
|
+
</p>
|
|
@@ -13,7 +13,9 @@ var getSyncRemoteData = function getSyncRemoteData() {
|
|
|
13
13
|
return require('core/remote_data').syncRemoteData;
|
|
14
14
|
};
|
|
15
15
|
jest.mock('sync', function () {
|
|
16
|
-
return jest.fn()
|
|
16
|
+
return jest.fn(function (model, key, options) {
|
|
17
|
+
return model;
|
|
18
|
+
});
|
|
17
19
|
});
|
|
18
20
|
jest.mock('connection/enterprise', function () {
|
|
19
21
|
return {
|
|
@@ -30,7 +32,11 @@ jest.mock('core/index', function () {
|
|
|
30
32
|
id: function id() {
|
|
31
33
|
return 'id';
|
|
32
34
|
},
|
|
33
|
-
emitEvent: jest.fn()
|
|
35
|
+
emitEvent: jest.fn(),
|
|
36
|
+
setCaptcha: jest.fn(),
|
|
37
|
+
setPasswordlessCaptcha: jest.fn(),
|
|
38
|
+
setPasswordResetCaptcha: jest.fn(),
|
|
39
|
+
setSignupChallenge: jest.fn()
|
|
34
40
|
};
|
|
35
41
|
});
|
|
36
42
|
jest.mock('core/sso/data', function () {
|
|
@@ -40,6 +46,12 @@ jest.mock('core/sso/data', function () {
|
|
|
40
46
|
})
|
|
41
47
|
};
|
|
42
48
|
});
|
|
49
|
+
jest.mock('core/web_api', function () {
|
|
50
|
+
return {
|
|
51
|
+
getChallenge: jest.fn(),
|
|
52
|
+
getSignupChallenge: jest.fn()
|
|
53
|
+
};
|
|
54
|
+
});
|
|
43
55
|
describe('remote_data.syncRemoteData()', function () {
|
|
44
56
|
beforeEach(function () {
|
|
45
57
|
jest.clearAllMocks();
|
|
@@ -63,4 +75,123 @@ describe('remote_data.syncRemoteData()', function () {
|
|
|
63
75
|
});
|
|
64
76
|
});
|
|
65
77
|
});
|
|
78
|
+
describe('captcha syncing', function () {
|
|
79
|
+
it('should sync login captcha when initialScreen is login', function () {
|
|
80
|
+
var syncRemoteData = getSyncRemoteData();
|
|
81
|
+
syncRemoteData('mockModel', 'login');
|
|
82
|
+
var syncCalls = require('sync').mock.calls;
|
|
83
|
+
var captchaCall = syncCalls.find(function (c) {
|
|
84
|
+
return c[1] === 'captcha';
|
|
85
|
+
});
|
|
86
|
+
var signupCaptchaCall = syncCalls.find(function (c) {
|
|
87
|
+
return c[1] === 'signupCaptcha';
|
|
88
|
+
});
|
|
89
|
+
expect(captchaCall).toBeDefined();
|
|
90
|
+
expect(signupCaptchaCall).toBeUndefined();
|
|
91
|
+
});
|
|
92
|
+
it('should sync signup captcha when initialScreen is signUp', function () {
|
|
93
|
+
var syncRemoteData = getSyncRemoteData();
|
|
94
|
+
syncRemoteData('mockModel', 'signUp');
|
|
95
|
+
var syncCalls = require('sync').mock.calls;
|
|
96
|
+
var captchaCall = syncCalls.find(function (c) {
|
|
97
|
+
return c[1] === 'captcha';
|
|
98
|
+
});
|
|
99
|
+
var signupCaptchaCall = syncCalls.find(function (c) {
|
|
100
|
+
return c[1] === 'signupCaptcha';
|
|
101
|
+
});
|
|
102
|
+
expect(captchaCall).toBeUndefined();
|
|
103
|
+
expect(signupCaptchaCall).toBeDefined();
|
|
104
|
+
});
|
|
105
|
+
it('should call webApi.getChallenge when login captcha syncFn is executed', function () {
|
|
106
|
+
var mockModel = {
|
|
107
|
+
get: jest.fn().mockReturnValue('test-id')
|
|
108
|
+
};
|
|
109
|
+
var syncRemoteData = getSyncRemoteData();
|
|
110
|
+
require('core/web_api').getChallenge.mockClear();
|
|
111
|
+
syncRemoteData(mockModel, 'login');
|
|
112
|
+
var syncCalls = require('sync').mock.calls;
|
|
113
|
+
var captchaCall = syncCalls.find(function (c) {
|
|
114
|
+
return c[1] === 'captcha';
|
|
115
|
+
});
|
|
116
|
+
var mockCallback = jest.fn();
|
|
117
|
+
captchaCall[2].syncFn(mockModel, mockCallback);
|
|
118
|
+
expect(require('core/web_api').getChallenge).toHaveBeenCalledWith('test-id', expect.any(Function));
|
|
119
|
+
});
|
|
120
|
+
it('should call webApi.getSignupChallenge when signup captcha syncFn is executed', function () {
|
|
121
|
+
var mockModel = {
|
|
122
|
+
get: jest.fn().mockReturnValue('test-id')
|
|
123
|
+
};
|
|
124
|
+
var syncRemoteData = getSyncRemoteData();
|
|
125
|
+
require('core/web_api').getSignupChallenge.mockClear();
|
|
126
|
+
syncRemoteData(mockModel, 'signUp');
|
|
127
|
+
var syncCalls = require('sync').mock.calls;
|
|
128
|
+
var signupCaptchaCall = syncCalls.find(function (c) {
|
|
129
|
+
return c[1] === 'signupCaptcha';
|
|
130
|
+
});
|
|
131
|
+
var mockCallback = jest.fn();
|
|
132
|
+
signupCaptchaCall[2].syncFn(mockModel, mockCallback);
|
|
133
|
+
expect(require('core/web_api').getSignupChallenge).toHaveBeenCalledWith('test-id', expect.any(Function));
|
|
134
|
+
});
|
|
135
|
+
it('should default to login captcha when no initialScreen is provided', function () {
|
|
136
|
+
var syncRemoteData = getSyncRemoteData();
|
|
137
|
+
syncRemoteData('mockModel'); // No second parameter
|
|
138
|
+
|
|
139
|
+
var syncCalls = require('sync').mock.calls;
|
|
140
|
+
var captchaCall = syncCalls.find(function (c) {
|
|
141
|
+
return c[1] === 'captcha';
|
|
142
|
+
});
|
|
143
|
+
var signupCaptchaCall = syncCalls.find(function (c) {
|
|
144
|
+
return c[1] === 'signupCaptcha';
|
|
145
|
+
});
|
|
146
|
+
expect(captchaCall).toBeDefined();
|
|
147
|
+
expect(signupCaptchaCall).toBeUndefined();
|
|
148
|
+
});
|
|
149
|
+
it('should not sync any captcha for other initialScreen values', function () {
|
|
150
|
+
var syncRemoteData = getSyncRemoteData();
|
|
151
|
+
syncRemoteData('mockModel', 'forgotPassword');
|
|
152
|
+
var syncCalls = require('sync').mock.calls;
|
|
153
|
+
var captchaCall = syncCalls.find(function (c) {
|
|
154
|
+
return c[1] === 'captcha';
|
|
155
|
+
});
|
|
156
|
+
var signupCaptchaCall = syncCalls.find(function (c) {
|
|
157
|
+
return c[1] === 'signupCaptcha';
|
|
158
|
+
});
|
|
159
|
+
expect(captchaCall).toBeUndefined();
|
|
160
|
+
expect(signupCaptchaCall).toBeUndefined();
|
|
161
|
+
});
|
|
162
|
+
it('should handle webApi.getSignupChallenge errors gracefully', function () {
|
|
163
|
+
var mockModel = {
|
|
164
|
+
get: jest.fn().mockReturnValue('test-id')
|
|
165
|
+
};
|
|
166
|
+
var syncRemoteData = getSyncRemoteData();
|
|
167
|
+
syncRemoteData(mockModel, 'signUp');
|
|
168
|
+
var syncCalls = require('sync').mock.calls;
|
|
169
|
+
var signupCaptchaCall = syncCalls.find(function (c) {
|
|
170
|
+
return c[1] === 'signupCaptcha';
|
|
171
|
+
});
|
|
172
|
+
require('core/web_api').getSignupChallenge.mockImplementation(function (id, cb) {
|
|
173
|
+
cb(new Error('404 Not Found'), null);
|
|
174
|
+
});
|
|
175
|
+
var mockCallback = jest.fn();
|
|
176
|
+
signupCaptchaCall[2].syncFn(mockModel, mockCallback);
|
|
177
|
+
expect(mockCallback).toHaveBeenCalledWith(null, null);
|
|
178
|
+
});
|
|
179
|
+
it('should handle webApi.getChallenge errors gracefully', function () {
|
|
180
|
+
var mockModel = {
|
|
181
|
+
get: jest.fn().mockReturnValue('test-id')
|
|
182
|
+
};
|
|
183
|
+
var syncRemoteData = getSyncRemoteData();
|
|
184
|
+
syncRemoteData(mockModel, 'login');
|
|
185
|
+
var syncCalls = require('sync').mock.calls;
|
|
186
|
+
var captchaCall = syncCalls.find(function (c) {
|
|
187
|
+
return c[1] === 'captcha';
|
|
188
|
+
});
|
|
189
|
+
require('core/web_api').getChallenge.mockImplementation(function (id, cb) {
|
|
190
|
+
cb(new Error('Network error'), null);
|
|
191
|
+
});
|
|
192
|
+
var mockCallback = jest.fn();
|
|
193
|
+
captchaCall[2].syncFn(mockModel, mockCallback);
|
|
194
|
+
expect(mockCallback).toHaveBeenCalledWith(null, null);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
66
197
|
});
|
package/lib/core/actions.js
CHANGED
|
@@ -34,7 +34,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
|
|
|
34
34
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
35
35
|
function setupLock(id, clientID, domain, options, hookRunner, emitEventFn, handleEventFn) {
|
|
36
36
|
var m = l.setup(id, clientID, domain, options, hookRunner, emitEventFn, handleEventFn);
|
|
37
|
-
m = (0, _remote_data.syncRemoteData)(m);
|
|
37
|
+
m = (0, _remote_data.syncRemoteData)(m, options === null || options === void 0 ? void 0 : options.initialScreen);
|
|
38
38
|
(0, _preload_utils.img)(l.ui.logo(m) || _container.defaultProps.logo);
|
|
39
39
|
_web_api.default.setupClient(id, clientID, domain, l.withAuthOptions(m, _objectSpread(_objectSpread({}, options), {}, {
|
|
40
40
|
popupOptions: l.ui.popupOptions(m)
|
package/lib/core/remote_data.js
CHANGED
|
@@ -19,6 +19,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
19
19
|
// shouldn't depend on this
|
|
20
20
|
|
|
21
21
|
function syncRemoteData(m) {
|
|
22
|
+
var initialScreen = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'login';
|
|
22
23
|
if (l.useTenantInfo(m)) {
|
|
23
24
|
m = (0, _sync.default)(m, 'client', {
|
|
24
25
|
syncFn: function syncFn(m, cb) {
|
|
@@ -69,13 +70,24 @@ function syncRemoteData(m) {
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
});
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
if (initialScreen === 'login') {
|
|
74
|
+
m = (0, _sync.default)(m, 'captcha', {
|
|
75
|
+
syncFn: function syncFn(m, cb) {
|
|
76
|
+
_web_api.default.getChallenge(m.get('id'), function (err, r) {
|
|
77
|
+
cb(null, r);
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
successFn: _index2.setCaptcha
|
|
81
|
+
});
|
|
82
|
+
} else if (initialScreen === 'signUp') {
|
|
83
|
+
m = (0, _sync.default)(m, 'signupCaptcha', {
|
|
84
|
+
syncFn: function syncFn(m, cb) {
|
|
85
|
+
_web_api.default.getSignupChallenge(m.get('id'), function (err, r) {
|
|
86
|
+
cb(null, r);
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
successFn: _index2.setSignupChallenge
|
|
90
|
+
});
|
|
91
|
+
}
|
|
80
92
|
return m;
|
|
81
93
|
}
|
|
@@ -46,6 +46,11 @@ var CaptchaPane = exports.default = /*#__PURE__*/function (_React$Component) {
|
|
|
46
46
|
var captcha = (0, _captcha2.getCaptchaConfig)(lock, flow);
|
|
47
47
|
var value = (0, _index3.getFieldValue)(lock, 'captcha');
|
|
48
48
|
var isValid = !(0, _index3.isFieldVisiblyInvalid)(lock, 'captcha');
|
|
49
|
+
|
|
50
|
+
// If no captcha config, don't render anything
|
|
51
|
+
if (!captcha) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
49
54
|
var provider = captcha.get('provider');
|
|
50
55
|
if ((0, _third_party_captcha.isThirdPartyCaptcha)(provider)) {
|
|
51
56
|
function handleChange(value) {
|
package/lib/i18n.js
CHANGED
|
@@ -90,7 +90,7 @@ function assertLanguage(m, language, base) {
|
|
|
90
90
|
function syncLang(m, language, _cb) {
|
|
91
91
|
(0, _cdn_utils.load)({
|
|
92
92
|
method: 'registerLanguageDictionary',
|
|
93
|
-
url: "".concat(l.languageBaseUrl(m), "/js/lock/").concat("14.
|
|
93
|
+
url: "".concat(l.languageBaseUrl(m), "/js/lock/").concat("14.2.0", "/").concat(language, ".js"),
|
|
94
94
|
check: function check(str) {
|
|
95
95
|
return str && str === language;
|
|
96
96
|
},
|
package/lib/lock.js
CHANGED
|
@@ -36,7 +36,7 @@ var Auth0Lock = exports.default = /*#__PURE__*/function (_Core) {
|
|
|
36
36
|
_inherits(Auth0Lock, _Core);
|
|
37
37
|
return _createClass(Auth0Lock);
|
|
38
38
|
}(_core.default); // telemetry
|
|
39
|
-
Auth0Lock.version = "14.
|
|
39
|
+
Auth0Lock.version = "14.2.0";
|
|
40
40
|
|
|
41
41
|
// TODO: should we have different telemetry for classic/passwordless?
|
|
42
42
|
// TODO: should we set telemetry info before each request?
|
package/lib/passwordless.js
CHANGED
|
@@ -36,4 +36,4 @@ var Auth0LockPasswordless = exports.default = /*#__PURE__*/function (_Core) {
|
|
|
36
36
|
_inherits(Auth0LockPasswordless, _Core);
|
|
37
37
|
return _createClass(Auth0LockPasswordless);
|
|
38
38
|
}(_core.default);
|
|
39
|
-
Auth0LockPasswordless.version = "14.
|
|
39
|
+
Auth0LockPasswordless.version = "14.2.0";
|