From 8605c63fceb3e1cf39d57375698f0b84b9a36b60 Mon Sep 17 00:00:00 2001 From: ghanjra Date: Sun, 12 Jan 2020 17:27:15 -0800 Subject: [PATCH] Fixes reset password flow fails due to incorrect policy #6 --- package.json | 4 ++-- src/ADService.js | 9 +++------ src/EditView.js | 2 +- src/LoginView.js | 4 +++- tests/ADService.test.js | 16 ++++------------ tests/EditView.test.js | 15 +++++++-------- tests/LoginView.test.js | 17 ++++++++++++++--- tests/__snapshots__/EditView.test.js.snap | 6 ++++++ 8 files changed, 40 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 38541fb..d4fcd7c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ad-b2c-react-native", - "version": "1.1.0", + "version": "1.1.1", "description": "React Native Azure B2C auth using JS. This doesn't require eject from expo.", "main": "index.js", "files": [ @@ -58,7 +58,7 @@ "react-addons-test-utils": "^15.6.2", "react-dom": "^16.9.0", "react-native": "^0.60.5", - "react-native-webview": "^7.1.0", + "react-native-webview": "^7.0.1", "react-test-renderer": "^16.9.0" } } diff --git a/src/ADService.js b/src/ADService.js index 7f90790..eb2052e 100644 --- a/src/ADService.js +++ b/src/ADService.js @@ -67,7 +67,7 @@ class ADService { if (!this._isTokenValid(this.tokenResult)) { const result = await this.fetchAndSetTokenAsync( this.tokenResult.refreshToken, - false, + this.loginPolicy, true ); @@ -84,7 +84,7 @@ class ADService { getIdToken = () => this.tokenResult.idToken; - fetchAndSetTokenAsync = async (authCode, isProfileEdit, isRefreshTokenGrant) => { + fetchAndSetTokenAsync = async (authCode, policy, isRefreshTokenGrant) => { if (!authCode) { return Result(false, 'Empty auth code'); } @@ -105,10 +105,7 @@ class ADService { } const body = this.getFormUrlEncoded(params); - const url = this._getStaticURI( - isProfileEdit ? this.profileEditPolicy : this.loginPolicy, - 'token', - ); + const url = this._getStaticURI(policy, 'token'); const response = await fetch(url, { method: 'POST', headers: { diff --git a/src/EditView.js b/src/EditView.js index 6d8cd3d..c44554a 100644 --- a/src/EditView.js +++ b/src/EditView.js @@ -52,7 +52,7 @@ export default class EditView extends React.PureComponent { if (result.requestType === RequestType.Code) { const reqResult = await adService.fetchAndSetTokenAsync( result.data, - true, + adService.profileEditPolicy, ); if (reqResult.isValid) { this.props.onSuccess(); diff --git a/src/LoginView.js b/src/LoginView.js index 020cb8c..ca85229 100644 --- a/src/LoginView.js +++ b/src/LoginView.js @@ -82,7 +82,9 @@ export default class LoginView extends PureComponent { } if (result.requestType === RequestType.Code) { - const reqResult = await adService.fetchAndSetTokenAsync(result.data); + const policy = currentUri.indexOf(adService.passwordResetPolicy) > -1 ? + adService.passwordResetPolicy : adService.loginPolicy; + const reqResult = await adService.fetchAndSetTokenAsync(result.data, policy); if (reqResult.isValid) { this.props.onSuccess(); } else { diff --git a/tests/ADService.test.js b/tests/ADService.test.js index c74fe6d..e01470e 100644 --- a/tests/ADService.test.js +++ b/tests/ADService.test.js @@ -229,25 +229,17 @@ describe('ADService', ()=>{ await testInvalidAuthCode(null); }); - test('calls fetch with correct parms when isProfileEdit not set', async ()=>{ - await adService.fetchAndSetTokenAsync("testCode"); - - const expectedUrl = "https://testtenant.b2clogin.com/testtenant.onmicrosoft.com/testloginPolicy/oauth2/v2.0/token?"; - const expectedArg2 = {"body": "client_id=testId&scope=testId%20offline_access&redirect_uri=test%2520redirectURI&grant_type=authorization_code&code=testCode", "headers": {"Content-Type": "application/x-www-form-urlencoded"}, "method": "POST"} - - expect(fetch).toHaveBeenCalledTimes(1); - expect(fetch).toHaveBeenCalledWith(expectedUrl,expectedArg2); - }); - test('calls fetch with correct parms when isProfileEdit set', async ()=>{ - await adService.fetchAndSetTokenAsync("testCode", true); + const policy = "testProfileEditPolicy"; + await adService.fetchAndSetTokenAsync("testCode", policy); - const expectedUrl = "https://testtenant.b2clogin.com/testtenant.onmicrosoft.com/testProfileEditPolicy/oauth2/v2.0/token?"; + const expectedUrl = `https://testtenant.b2clogin.com/testtenant.onmicrosoft.com/${policy}/oauth2/v2.0/token?`; const expectedArg2 = {"body": "client_id=testId&scope=testId%20offline_access&redirect_uri=test%2520redirectURI&grant_type=authorization_code&code=testCode", "headers": {"Content-Type": "application/x-www-form-urlencoded"}, "method": "POST"} expect(fetch).toHaveBeenCalledTimes(1); expect(fetch).toHaveBeenCalledWith(expectedUrl,expectedArg2); }); + test('calls secureStore.setItemAsync with correct params', async ()=>{ const fetchResult = { token_type:"testType", diff --git a/tests/EditView.test.js b/tests/EditView.test.js index 6b9c924..a7ec7a1 100644 --- a/tests/EditView.test.js +++ b/tests/EditView.test.js @@ -7,19 +7,18 @@ import adService from '../src/ADService'; describe('EditView',()=>{ const props = { - onSuccess: jest.fn(), - onFail: jest.fn(), - renderLoading:()=>loading - }; - - adService.init({ appId:"testAppId", redirectURI:"test//redirectURI", tenant:"TestTenant", loginPolicy:"testLoginPolicy", passwordResetPolicy:"testPasswordReset", profileEditPolicy:"testProfileEditPolicy", - }); + onSuccess: jest.fn(), + onFail: jest.fn(), + renderLoading:()=>loading + }; + + adService.init(props); test('renders correctly', () => { const wrapper = shallow(); @@ -182,7 +181,7 @@ describe('EditView',()=>{ await callbackAsync({url:"doesNotMatter"}); expect(adService.fetchAndSetTokenAsync).toHaveBeenCalledTimes(1); - expect(adService.fetchAndSetTokenAsync).toHaveBeenCalledWith(expectedResult.data, true); + expect(adService.fetchAndSetTokenAsync).toHaveBeenCalledWith(expectedResult.data, props.profileEditPolicy); }); test('calls props.success correctly when fetchAndSetTokenAsync returns valid', async ()=> { diff --git a/tests/LoginView.test.js b/tests/LoginView.test.js index 5d4f0c2..e30aeb0 100644 --- a/tests/LoginView.test.js +++ b/tests/LoginView.test.js @@ -358,16 +358,27 @@ describe('LoginView',() => { adService.getLoginFlowResult.mockReturnValue(expectedResult); }); - test('calls fetchAndSetTokenAsync correctly', async ()=> { + test('calls fetchAndSetTokenAsync correctly when login uri', async ()=> { adService.fetchAndSetTokenAsync = jest.fn(); adService.fetchAndSetTokenAsync.mockResolvedValue({isValid:true}); - + instance.state.uri = props.loginPolicy; + await callbackAsync({url:"doesNotMatter"}); expect(adService.fetchAndSetTokenAsync).toHaveBeenCalledTimes(1); - expect(adService.fetchAndSetTokenAsync).toHaveBeenCalledWith(expectedResult.data); + expect(adService.fetchAndSetTokenAsync).toHaveBeenCalledWith(expectedResult.data, props.loginPolicy); }); + test('calls fetchAndSetTokenAsync correctly when password reset uri', async ()=> { + adService.fetchAndSetTokenAsync = jest.fn(); + adService.fetchAndSetTokenAsync.mockResolvedValue({isValid:true}); + instance.state.uri = props.passwordResetPolicy; + + await callbackAsync({url:"doesNotMatter"}); + + expect(adService.fetchAndSetTokenAsync).toHaveBeenCalledTimes(1); + expect(adService.fetchAndSetTokenAsync).toHaveBeenCalledWith(expectedResult.data, props.passwordResetPolicy); + }); test('calls props.success correctly when fetchAndSetTokenAsync returns valid', async ()=> { props.onSuccess.mockClear(); adService.fetchAndSetTokenAsync = jest.fn(); diff --git a/tests/__snapshots__/EditView.test.js.snap b/tests/__snapshots__/EditView.test.js.snap index 06b246f..8546e00 100644 --- a/tests/__snapshots__/EditView.test.js.snap +++ b/tests/__snapshots__/EditView.test.js.snap @@ -2,8 +2,10 @@ exports[`EditView renders correctly 1`] = ` `;