-
Notifications
You must be signed in to change notification settings - Fork 556
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[IAMRISK-2916] Added support for Auth0 v2 captcha provider (#2503)
### Changes Added support for Auth0 v2 (Cloudflare turnstile) captcha provider. ### References https://auth0team.atlassian.net/browse/IAMRISK-2916 ### Testing * [x] This change adds unit test coverage * [x] This change adds integration test coverage * [x] This change has been tested on the latest version of the platform/language ### Checklist * [x] I have read the [Auth0 general contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md) * [x] I have read the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md) * [x] All code quality tools/guidelines have been run/followed * [x] All relevant assets have been compiled --------- Co-authored-by: Frederik Prijck <frederik.prijck@auth0.com>
- Loading branch information
1 parent
003339c
commit ea1c9fc
Showing
9 changed files
with
352 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
src/__tests__/field/captcha/__snapshots__/auth0_v2.test.jsx.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Auth0 V2 should match the snapshot 1`] = ` | ||
<div | ||
className="auth0-lock-auth0-v2-block auth0-lock-auth0-v2-block-error" | ||
> | ||
<div | ||
className="auth0-lock-auth0-v2" | ||
/> | ||
</div> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from 'react'; | ||
import { expectComponent } from 'testUtils'; | ||
import { ThirdPartyCaptcha } from '../../../field/captcha/third_party_captcha'; | ||
|
||
describe('Auth0 V2', () => { | ||
const component = <ThirdPartyCaptcha provider={'auth0_v2'} hl="en" sitekey={'mySiteKey'} />; | ||
|
||
it('should match the snapshot', () => { | ||
expectComponent(component).toMatchSnapshot(); | ||
}); | ||
|
||
it('injects the script', () => { | ||
const script = [...window.document.querySelectorAll('script')].find(s => | ||
s.src.startsWith( | ||
'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=' | ||
) | ||
); | ||
expect(script).not.toBeUndefined(); | ||
}); | ||
}); |
244 changes: 244 additions & 0 deletions
244
src/__tests__/field/captcha/third_party_captcha.test.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import { act } from 'react-dom/test-utils'; | ||
import I from 'immutable'; | ||
import * as l from '../../../core/index'; | ||
import { ThirdPartyCaptcha } from '../../../field/captcha/third_party_captcha'; | ||
|
||
const createLockMock = ({ | ||
provider = 'auth0', | ||
required = true, | ||
siteKey = '', | ||
clientSubdomain = '' | ||
} = {}) => | ||
I.fromJS({ | ||
id: '__lock-id__', | ||
core: { | ||
captcha: { provider, siteKey, clientSubdomain, required: required } | ||
} | ||
}); | ||
|
||
describe('ThirdPartyCaptcha', () => { | ||
let prevWindow; | ||
beforeAll(() => { | ||
prevWindow = global.window; | ||
global.window.grecaptcha = { | ||
render: jest.fn(), | ||
enterprise: { | ||
render: jest.fn() | ||
} | ||
}; | ||
global.window.hcaptcha = { | ||
render: jest.fn() | ||
}; | ||
global.window.friendlyChallenge = { | ||
WidgetInstance: jest.fn().mockImplementation((...args) => { | ||
return jest.fn(...args); | ||
}) | ||
}; | ||
global.window.turnstile = { | ||
render: jest.fn() | ||
}; | ||
}); | ||
afterAll(() => { | ||
global.window = prevWindow; | ||
}); | ||
describe('recaptchav2', () => { | ||
let wrapper; | ||
beforeAll(() => { | ||
const lockMock = createLockMock({ | ||
provider: 'recaptcha_v2', | ||
siteKey: 'mySiteKey' | ||
}); | ||
|
||
const captcha = l.captcha(lockMock); | ||
wrapper = mount( | ||
<ThirdPartyCaptcha | ||
provider={captcha.get('provider')} | ||
sitekey={captcha.get('siteKey')} | ||
clientSubdomain={captcha.get('clientSubdomain')} | ||
hl={'en'} | ||
isValid={true} | ||
value={undefined} | ||
/> | ||
).instance(); | ||
act(() => { | ||
const injectCaptchaScriptSpy = jest.spyOn(wrapper, 'injectCaptchaScript'); | ||
|
||
wrapper.componentDidMount(); | ||
|
||
injectCaptchaScriptSpy.mock.calls[0][0](); | ||
}); | ||
}); | ||
|
||
it('should call render with the correct renderParams', () => { | ||
const renderParams = global.window.grecaptcha.render.mock.calls[0][1]; | ||
|
||
expect(renderParams).toEqual({ | ||
sitekey: 'mySiteKey', | ||
callback: expect.any(Function), | ||
'expired-callback': expect.any(Function), | ||
'error-callback': expect.any(Function) | ||
}); | ||
}); | ||
}); | ||
|
||
describe('friendly captcha', () => { | ||
let wrapper; | ||
beforeAll(() => { | ||
const lockMock = createLockMock({ | ||
provider: 'friendly_captcha', | ||
siteKey: 'mySiteKey' | ||
}); | ||
|
||
const captcha = l.captcha(lockMock); | ||
wrapper = mount( | ||
<ThirdPartyCaptcha | ||
provider={captcha.get('provider')} | ||
sitekey={captcha.get('siteKey')} | ||
clientSubdomain={captcha.get('clientSubdomain')} | ||
hl={'en'} | ||
isValid={true} | ||
value={undefined} | ||
/> | ||
).instance(); | ||
act(() => { | ||
const injectCaptchaScriptSpy = jest.spyOn(wrapper, 'injectCaptchaScript'); | ||
|
||
wrapper.componentDidMount(); | ||
jest.spyOn(global.window.friendlyChallenge, 'WidgetInstance'); | ||
|
||
injectCaptchaScriptSpy.mock.calls[0][0](); | ||
}); | ||
}); | ||
|
||
it('should call WidgetInstance constructor with the correct renderParams', () => { | ||
const renderParams = global.window.friendlyChallenge.WidgetInstance.mock.calls[0][1]; | ||
expect(renderParams).toEqual({ | ||
sitekey: 'mySiteKey', | ||
doneCallback: expect.any(Function), | ||
errorCallback: expect.any(Function), | ||
language: 'en' | ||
}); | ||
}); | ||
}); | ||
|
||
describe('hcaptcha', () => { | ||
let wrapper; | ||
beforeAll(() => { | ||
const lockMock = createLockMock({ | ||
provider: 'hcaptcha', | ||
siteKey: 'mySiteKey' | ||
}); | ||
|
||
const captcha = l.captcha(lockMock); | ||
wrapper = mount( | ||
<ThirdPartyCaptcha | ||
provider={captcha.get('provider')} | ||
sitekey={captcha.get('siteKey')} | ||
clientSubdomain={captcha.get('clientSubdomain')} | ||
hl={'en'} | ||
isValid={true} | ||
value={undefined} | ||
/> | ||
).instance(); | ||
act(() => { | ||
const injectCaptchaScriptSpy = jest.spyOn(wrapper, 'injectCaptchaScript'); | ||
|
||
wrapper.componentDidMount(); | ||
|
||
injectCaptchaScriptSpy.mock.calls[0][0](); | ||
}); | ||
}); | ||
|
||
it('should call render with the correct renderParams', () => { | ||
const renderParams = global.window.hcaptcha.render.mock.calls[0][1]; | ||
expect(renderParams).toEqual({ | ||
sitekey: 'mySiteKey', | ||
callback: expect.any(Function), | ||
'expired-callback': expect.any(Function), | ||
'error-callback': expect.any(Function) | ||
}); | ||
}); | ||
}); | ||
|
||
describe('auth0_v2', () => { | ||
let wrapper; | ||
beforeAll(() => { | ||
const lockMock = createLockMock({ | ||
provider: 'auth0_v2', | ||
siteKey: 'mySiteKey' | ||
}); | ||
|
||
const captcha = l.captcha(lockMock); | ||
wrapper = mount( | ||
<ThirdPartyCaptcha | ||
provider={captcha.get('provider')} | ||
sitekey={captcha.get('siteKey')} | ||
clientSubdomain={captcha.get('clientSubdomain')} | ||
hl={'en'} | ||
isValid={true} | ||
value={undefined} | ||
/> | ||
).instance(); | ||
act(() => { | ||
const injectCaptchaScriptSpy = jest.spyOn(wrapper, 'injectCaptchaScript'); | ||
|
||
wrapper.componentDidMount(); | ||
|
||
injectCaptchaScriptSpy.mock.calls[0][0](); | ||
}); | ||
}); | ||
|
||
it('should call render with the correct renderParams', () => { | ||
const renderParams = global.window.turnstile.render.mock.calls[0][1]; | ||
expect(renderParams).toEqual({ | ||
sitekey: 'mySiteKey', | ||
callback: expect.any(Function), | ||
'expired-callback': expect.any(Function), | ||
'error-callback': expect.any(Function), | ||
language: 'en', | ||
theme: 'light' | ||
}); | ||
}); | ||
}); | ||
|
||
describe('recaptcha enterprise', () => { | ||
let wrapper; | ||
beforeAll(() => { | ||
const lockMock = createLockMock({ | ||
provider: 'recaptcha_enterprise', | ||
siteKey: 'mySiteKey' | ||
}); | ||
|
||
const captcha = l.captcha(lockMock); | ||
wrapper = mount( | ||
<ThirdPartyCaptcha | ||
provider={captcha.get('provider')} | ||
sitekey={captcha.get('siteKey')} | ||
clientSubdomain={captcha.get('clientSubdomain')} | ||
hl={'en'} | ||
isValid={true} | ||
value={undefined} | ||
/> | ||
).instance(); | ||
act(() => { | ||
const injectCaptchaScriptSpy = jest.spyOn(wrapper, 'injectCaptchaScript'); | ||
|
||
wrapper.componentDidMount(); | ||
|
||
injectCaptchaScriptSpy.mock.calls[0][0](); | ||
}); | ||
}); | ||
|
||
it('should call render with the correct renderParams', () => { | ||
const renderParams = global.window.grecaptcha.enterprise.render.mock.calls[0][1]; | ||
expect(renderParams).toEqual({ | ||
sitekey: 'mySiteKey', | ||
callback: expect.any(Function), | ||
'expired-callback': expect.any(Function), | ||
'error-callback': expect.any(Function) | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.