Skip to content

Commit

Permalink
Add skipLegacyListener (#404)
Browse files Browse the repository at this point in the history
  • Loading branch information
Widcket committed Sep 9, 2021
1 parent 7277f15 commit 1d9a7c4
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 27 deletions.
1 change: 1 addition & 0 deletions src/webauth/__mocks__/auth0.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default class A0Auth0 {

reset() {
this.url = null;
this.ephemeralSession = false;
this.error = null;
this.hidden = true;
this.parameters = null;
Expand Down
4 changes: 4 additions & 0 deletions src/webauth/__mocks__/linking.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ export default class Linking {
removeEventListener(event, fn) {
this.emitter.removeListener(event, fn);
}

removeAllListeners() {
this.emitter.removeAllListeners();
}
}
24 changes: 13 additions & 11 deletions src/webauth/__tests__/agent.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ describe('Agent', () => {
describe('show', () => {
beforeEach(() => {
NativeModules.A0Auth0 = A0Auth0;
Linking.removeAllListeners();
A0Auth0.reset();
A0Auth0.onUrl = () => {
Linking.emitter.emit('url', {url: 'https://auth0.com'});
};
});

it('should fail if native module is not linked', async () => {
Expand All @@ -19,12 +23,6 @@ describe('Agent', () => {
});

describe('complete web flow', () => {
beforeEach(() => {
A0Auth0.onUrl = () => {
Linking.emitter.emit('url', {url: 'https://auth0.com'});
};
});

it('should resolve promise with url result', async () => {
expect.assertions(1);
await expect(
Expand All @@ -40,10 +38,11 @@ describe('Agent', () => {
});

it('should not pass ephemeral session parameter', async () => {
Platform.OS = 'android';
expect.assertions(1);
const url = 'https://auth0.com';
await agent.show(url);
expect(A0Auth0.ephemeralSession).toBeUndefined();
expect(A0Auth0.ephemeralSession).toEqual(false);
});

it('should not use ephemeral session by default', async () => {
Expand Down Expand Up @@ -71,10 +70,13 @@ describe('Agent', () => {
expect(Linking.emitter.listenerCount('url')).toEqual(1);
});

it('should not register url listeners', () => {
const url = 'https://auth0.com/authorize';
agent.show(url, false, true);
expect(Linking.emitter.listenerCount('url')).toEqual(0);
});

it('should remove url listeners when done', async () => {
A0Auth0.onUrl = () => {
Linking.emitter.emit('url', {url: 'https://auth0.com'});
};
expect.assertions(1);
const url = 'https://auth0.com/authorize';
await agent.show(url);
Expand All @@ -92,7 +94,7 @@ describe('Agent', () => {
it('should remove url listeners on first load', async () => {
expect.assertions(1);
const url = 'https://auth0.com/authorize';
await agent.show(url, false, true);
await agent.show(url, false, false, true);
expect(Linking.emitter.listenerCount('url')).toEqual(0);
});
});
Expand Down
4 changes: 2 additions & 2 deletions src/webauth/__tests__/webauth.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ describe('WebAuth', () => {
});

it('should build the callback URL with a custom scheme when logging out', async () => {
const options = {customScheme: 'custom-scheme'};
await webauth.clearSession(options);
const parameters = {customScheme: 'custom-scheme'};
await webauth.clearSession(parameters);

const parsedUrl = new URL(A0Auth0.url);
const urlQuery = parsedUrl.searchParams;
Expand Down
13 changes: 9 additions & 4 deletions src/webauth/agent.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import {NativeModules, Linking, Platform} from 'react-native';

export default class Agent {
show(url, ephemeralSession = false, closeOnLoad = false) {
show(
url,
ephemeralSession = false,
skipLegacyListener = false,
closeOnLoad = false,
) {
if (!NativeModules.A0Auth0) {
return Promise.reject(
new Error(
'Missing NativeModule. React Native versions 0.60 and up perform auto-linking. Please see https://github.com/react-native-community/cli/blob/master/docs/autolinking.md.'
'Missing NativeModule. React Native versions 0.60 and up perform auto-linking. Please see https://github.com/react-native-community/cli/blob/master/docs/autolinking.md.',
),
);
}
Expand All @@ -18,9 +23,9 @@ export default class Agent {
};
const params =
Platform.OS === 'ios' ? [ephemeralSession, closeOnLoad] : [closeOnLoad];
Linking.addEventListener('url', urlHandler);
if (!skipLegacyListener) Linking.addEventListener('url', urlHandler);
NativeModules.A0Auth0.showUrl(url, ...params, (error, redirectURL) => {
Linking.removeEventListener('url', urlHandler);
if (!skipLegacyListener) Linking.removeEventListener('url', urlHandler);
if (error) {
reject(error);
} else if (redirectURL) {
Expand Down
29 changes: 19 additions & 10 deletions src/webauth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export default class WebAuth {
/**
* Starts the AuthN/AuthZ transaction against the AS in the in-app browser.
*
* In iOS it will use `SFSafariViewController` and in Android Chrome Custom Tabs.
* In iOS <11 it will use `SFSafariViewController`, in iOS 11 `SFAuthenticationSession` and in iOS >11 `ASWebAuthenticationSession`.
* In Android it will use Chrome Custom Tabs.
*
* To learn more about how to customize the authorize call, check the Universal Login Page
* article at https://auth0.com/docs/hosted-pages/login
Expand All @@ -58,8 +59,9 @@ export default class WebAuth {
* @param {String} [parameters.invitationUrl] the invitation URL to join an organization. Takes precedence over the "organization" parameter.
* @param {Object} options Other configuration options.
* @param {Number} [options.leeway] The amount of leeway, in seconds, to accommodate potential clock skew when validating an ID token's claims. Defaults to 60 seconds if not specified.
* @param {Boolean} [options.ephemeralSession] Disable Single-Sign-On (SSO). It only affects iOS with versions 13 and above.
* @param {Boolean} [options.ephemeralSession] Disable Single-Sign-On (SSO). It only affects iOS with versions 13 and above. Defaults to `false`.
* @param {String} [options.customScheme] Custom scheme to build the callback URL with.
* @param {String} [options.skipLegacyListener] Whether to register the event listener necessary for the SDK to work on iOS <11 or not. Defaults to `false`.
* @returns {Promise}
* @see https://auth0.com/docs/api/authentication#authorize-client
*
Expand Down Expand Up @@ -96,7 +98,11 @@ export default class WebAuth {
};
const authorizeUrl = this.client.authorizeUrl(query);
return agent
.show(authorizeUrl, options.ephemeralSession)
.show(
authorizeUrl,
options.ephemeralSession,
options.skipLegacyListener,
)
.then(redirectUrl => {
if (!redirectUrl || !redirectUrl.startsWith(redirectUri)) {
throw new AuthError({
Expand Down Expand Up @@ -142,22 +148,25 @@ export default class WebAuth {
/**
* Removes Auth0 session and optionally remove the Identity Provider session.
*
* In iOS it will use `SFSafariViewController` and in Android Chrome Custom Tabs.
* In iOS <11 it will use `SFSafariViewController`, in iOS 11 `SFAuthenticationSession` and in iOS >11 `ASWebAuthenticationSession`.
* In Android it will use Chrome Custom Tabs.
*
* @param {Object} parameters Parameters to send
* @param {Bool} [parameters.federated] Optionally remove the IdP session.
* @param {String} [parameters.customScheme] Custom scheme to build the callback URL with.
* @param {Object} options Other configuration options.
* @param {String} [options.skipLegacyListener] Whether to register the event listener necessary for the SDK to work on iOS <11 or not. Defaults to `false`.
* @returns {Promise}
* @see https://auth0.com/docs/logout
*
* @memberof WebAuth
*/
clearSession(options = {}) {
clearSession(parameters = {}, options = {}) {
const {client, agent, domain, clientId} = this;
options.clientId = clientId;
options.returnTo = callbackUri(domain, options.customScheme);
options.federated = options.federated || false;
const logoutUrl = client.logoutUrl(options);
return agent.show(logoutUrl, false, true);
parameters.clientId = clientId;
parameters.returnTo = callbackUri(domain, parameters.customScheme);
parameters.federated = parameters.federated || false;
const logoutUrl = client.logoutUrl(parameters);
return agent.show(logoutUrl, false, options.skipLegacyListener, true);
}
}

0 comments on commit 1d9a7c4

Please sign in to comment.