Diff
checker
Text
Text
Images
Documents
Excel
Folders
Legal
Enterprise
Desktop
Pricing
Sign in
Download Diffchecker Desktop
Compare text
Find the difference between two text files
Tools
History
Real-time editor
Hide whitespace changes
Hide unchanged lines
Disable line wrap
Layout
Split
Unified
Diff precision
Smart
Word
Char
Text styles
Change appearance
Syntax highlighting
Choose syntax
Ignore
Transform text
Go to first change
Edit input
Diffchecker Desktop
The most secure way to run Diffchecker. Get the Diffchecker Desktop app: your diffs never leave your computer!
Get Desktop
index.js (react-native-app-auth@7.1.3)
Created
2 years ago
Diff never expires
Clear
Export
Share
Explain
0 removals
Lines
Total
Removed
Characters
Total
Removed
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
391 lines
Copy
6 additions
Lines
Total
Added
Characters
Total
Added
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
397 lines
Copy
import invariant from 'invariant';
import invariant from 'invariant';
import { NativeModules, Platform } from 'react-native';
import { NativeModules, Platform } from 'react-native';
import base64 from 'react-native-base64';
import base64 from 'react-native-base64';
const { RNAppAuth } = NativeModules;
const { RNAppAuth } = NativeModules;
const validateIssuerOrServiceConfigurationEndpoints = (issuer, serviceConfiguration) =>
const validateIssuerOrServiceConfigurationEndpoints = (issuer, serviceConfiguration) =>
invariant(
invariant(
typeof issuer === 'string' ||
typeof issuer === 'string' ||
(serviceConfiguration &&
(serviceConfiguration &&
typeof serviceConfiguration.authorizationEndpoint === 'string' &&
typeof serviceConfiguration.authorizationEndpoint === 'string' &&
typeof serviceConfiguration.tokenEndpoint === 'string'),
typeof serviceConfiguration.tokenEndpoint === 'string'),
'Config error: you must provide either an issuer or a service endpoints'
'Config error: you must provide either an issuer or a service endpoints'
);
);
const validateIssuerOrServiceConfigurationRegistrationEndpoint = (issuer, serviceConfiguration) =>
const validateIssuerOrServiceConfigurationRegistrationEndpoint = (issuer, serviceConfiguration) =>
invariant(
invariant(
typeof issuer === 'string' ||
typeof issuer === 'string' ||
(serviceConfiguration && typeof serviceConfiguration.registrationEndpoint === 'string'),
(serviceConfiguration && typeof serviceConfiguration.registrationEndpoint === 'string'),
'Config error: you must provide either an issuer or a registration endpoint'
'Config error: you must provide either an issuer or a registration endpoint'
);
);
const validateIssuerOrServiceConfigurationRevocationEndpoint = (issuer, serviceConfiguration) =>
const validateIssuerOrServiceConfigurationRevocationEndpoint = (issuer, serviceConfiguration) =>
invariant(
invariant(
typeof issuer === 'string' ||
typeof issuer === 'string' ||
(serviceConfiguration && typeof serviceConfiguration.revocationEndpoint === 'string'),
(serviceConfiguration && typeof serviceConfiguration.revocationEndpoint === 'string'),
'Config error: you must provide either an issuer or a revocation endpoint'
'Config error: you must provide either an issuer or a revocation endpoint'
);
);
const validateIssuerOrServiceConfigurationEndSessionEndpoint = (issuer, serviceConfiguration) =>
const validateIssuerOrServiceConfigurationEndSessionEndpoint = (issuer, serviceConfiguration) =>
invariant(
invariant(
typeof issuer === 'string' ||
typeof issuer === 'string' ||
(serviceConfiguration && typeof serviceConfiguration.endSessionEndpoint === 'string'),
(serviceConfiguration && typeof serviceConfiguration.endSessionEndpoint === 'string'),
'Config error: you must provide either an issuer or an end session endpoint'
'Config error: you must provide either an issuer or an end session endpoint'
);
);
const validateClientId = clientId =>
const validateClientId = clientId =>
invariant(typeof clientId === 'string', 'Config error: clientId must be a string');
invariant(typeof clientId === 'string', 'Config error: clientId must be a string');
const validateRedirectUrl = redirectUrl =>
const validateRedirectUrl = redirectUrl =>
invariant(typeof redirectUrl === 'string', 'Config error: redirectUrl must be a string');
invariant(typeof redirectUrl === 'string', 'Config error: redirectUrl must be a string');
const validateHeaders = headers => {
const validateHeaders = headers => {
if (!headers) {
if (!headers) {
return;
return;
}
}
const customHeaderTypeErrorMessage =
const customHeaderTypeErrorMessage =
'Config error: customHeaders type must be { token?: { [key: string]: string }, authorize?: { [key: string]: string }, register: { [key: string]: string }}';
'Config error: customHeaders type must be { token?: { [key: string]: string }, authorize?: { [key: string]: string }, register: { [key: string]: string }}';
const authorizedKeys = ['token', 'authorize', 'register'];
const authorizedKeys = ['token', 'authorize', 'register'];
const keys = Object.keys(headers);
const keys = Object.keys(headers);
const correctKeys = keys.filter(key => authorizedKeys.includes(key));
const correctKeys = keys.filter(key => authorizedKeys.includes(key));
invariant(
invariant(
keys.length <= authorizedKeys.length &&
keys.length <= authorizedKeys.length &&
correctKeys.length > 0 &&
correctKeys.length > 0 &&
correctKeys.length === keys.length,
correctKeys.length === keys.length,
customHeaderTypeErrorMessage
customHeaderTypeErrorMessage
);
);
Object.values(headers).forEach(value => {
Object.values(headers).forEach(value => {
invariant(typeof value === 'object', customHeaderTypeErrorMessage);
invariant(typeof value === 'object', customHeaderTypeErrorMessage);
invariant(
invariant(
Object.values(value).filter(key => typeof key !== 'string').length === 0,
Object.values(value).filter(key => typeof key !== 'string').length === 0,
customHeaderTypeErrorMessage
customHeaderTypeErrorMessage
);
);
});
});
};
};
const validateAdditionalHeaders = headers => {
const validateAdditionalHeaders = headers => {
if (!headers) {
if (!headers) {
return;
return;
}
}
const errorMessage = 'Config error: additionalHeaders must be { [key: string]: string }';
const errorMessage = 'Config error: additionalHeaders must be { [key: string]: string }';
invariant(typeof headers === 'object', errorMessage);
invariant(typeof headers === 'object', errorMessage);
invariant(
invariant(
Object.values(headers).filter(key => typeof key !== 'string').length === 0,
Object.values(headers).filter(key => typeof key !== 'string').length === 0,
errorMessage
errorMessage
);
);
};
};
const validateConnectionTimeoutSeconds = timeout => {
const validateConnectionTimeoutSeconds = timeout => {
if (!timeout) {
if (!timeout) {
return;
return;
}
}
invariant(typeof timeout === 'number', 'Config error: connectionTimeoutSeconds must be a number');
invariant(typeof timeout === 'number', 'Config error: connectionTimeoutSeconds must be a number');
};
};
export const SECOND_IN_MS = 1000;
export const SECOND_IN_MS = 1000;
export const DEFAULT_TIMEOUT_IOS = 60;
export const DEFAULT_TIMEOUT_IOS = 60;
export const DEFAULT_TIMEOUT_ANDROID = 15;
export const DEFAULT_TIMEOUT_ANDROID = 15;
const convertTimeoutForPlatform = (
const convertTimeoutForPlatform = (
platform,
platform,
connectionTimeout = Platform.OS === 'ios' ? DEFAULT_TIMEOUT_IOS : DEFAULT_TIMEOUT_ANDROID
connectionTimeout = Platform.OS === 'ios' ? DEFAULT_TIMEOUT_IOS : DEFAULT_TIMEOUT_ANDROID
) => (platform === 'android' ? connectionTimeout * SECOND_IN_MS : connectionTimeout);
) => (platform === 'android' ? connectionTimeout * SECOND_IN_MS : connectionTimeout);
export const prefetchConfiguration = async ({
export const prefetchConfiguration = async ({
warmAndPrefetchChrome = false,
warmAndPrefetchChrome = false,
issuer,
issuer,
redirectUrl,
redirectUrl,
clientId,
clientId,
scopes,
scopes,
serviceConfiguration,
serviceConfiguration,
dangerouslyAllowInsecureHttpRequests = false,
dangerouslyAllowInsecureHttpRequests = false,
customHeaders,
customHeaders,
connectionTimeoutSeconds,
connectionTimeoutSeconds,
}) => {
}) => {
if (Platform.OS === 'android') {
if (Platform.OS === 'android') {
validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration);
validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration);
validateClientId(clientId);
validateClientId(clientId);
validateRedirectUrl(redirectUrl);
validateRedirectUrl(redirectUrl);
validateHeaders(customHeaders);
validateHeaders(customHeaders);
validateConnectionTimeoutSeconds(connectionTimeoutSeconds);
validateConnectionTimeoutSeconds(connectionTimeoutSeconds);
const nativeMethodArguments = [
const nativeMethodArguments = [
warmAndPrefetchChrome,
warmAndPrefetchChrome,
issuer,
issuer,
redirectUrl,
redirectUrl,
clientId,
clientId,
scopes,
scopes,
serviceConfiguration,
serviceConfiguration,
dangerouslyAllowInsecureHttpRequests,
dangerouslyAllowInsecureHttpRequests,
customHeaders,
customHeaders,
convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds),
convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds),
];
];
RNAppAuth.prefetchConfiguration(...nativeMethodArguments);
RNAppAuth.prefetchConfiguration(...nativeMethodArguments);
}
}
};
};
export const register = ({
export const register = ({
issuer,
issuer,
redirectUrls,
redirectUrls,
responseTypes,
responseTypes,
grantTypes,
grantTypes,
subjectType,
subjectType,
tokenEndpointAuthMethod,
tokenEndpointAuthMethod,
additionalParameters,
additionalParameters,
serviceConfiguration,
serviceConfiguration,
dangerouslyAllowInsecureHttpRequests = false,
dangerouslyAllowInsecureHttpRequests = false,
customHeaders,
customHeaders,
additionalHeaders,
additionalHeaders,
connectionTimeoutSeconds,
connectionTimeoutSeconds,
}) => {
}) => {
validateIssuerOrServiceConfigurationRegistrationEndpoint(issuer, serviceConfiguration);
validateIssuerOrServiceConfigurationRegistrationEndpoint(issuer, serviceConfiguration);
validateHeaders(customHeaders);
validateHeaders(customHeaders);
validateAdditionalHeaders(additionalHeaders);
validateAdditionalHeaders(additionalHeaders);
validateConnectionTimeoutSeconds(connectionTimeoutSeconds);
validateConnectionTimeoutSeconds(connectionTimeoutSeconds);
invariant(
invariant(
Array.isArray(redirectUrls) && redirectUrls.every(url => typeof url === 'string'),
Array.isArray(redirectUrls) && redirectUrls.every(url => typeof url === 'string'),
'Config error: redirectUrls must be an Array of strings'
'Config error: redirectUrls must be an Array of strings'
);
);
invariant(
invariant(
responseTypes == null ||
responseTypes == null ||
(Array.isArray(responseTypes) && responseTypes.every(rt => typeof rt === 'string')),
(Array.isArray(responseTypes) && responseTypes.every(rt => typeof rt === 'string')),
'Config error: if provided, responseTypes must be an Array of strings'
'Config error: if provided, responseTypes must be an Array of strings'
);
);
invariant(
invariant(
grantTypes == null ||
grantTypes == null ||
(Array.isArray(grantTypes) && grantTypes.every(gt => typeof gt === 'string')),
(Array.isArray(grantTypes) && grantTypes.every(gt => typeof gt === 'string')),
'Config error: if provided, grantTypes must be an Array of strings'
'Config error: if provided, grantTypes must be an Array of strings'
);
);
invariant(
invariant(
subjectType == null || typeof subjectType === 'string',
subjectType == null || typeof subjectType === 'string',
'Config error: if provided, subjectType must be a string'
'Config error: if provided, subjectType must be a string'
);
);
invariant(
invariant(
tokenEndpointAuthMethod == null || typeof tokenEndpointAuthMethod === 'string',
tokenEndpointAuthMethod == null || typeof tokenEndpointAuthMethod === 'string',
'Config error: if provided, tokenEndpointAuthMethod must be a string'
'Config error: if provided, tokenEndpointAuthMethod must be a string'
);
);
const nativeMethodArguments = [
const nativeMethodArguments = [
issuer,
issuer,
redirectUrls,
redirectUrls,
responseTypes,
responseTypes,
grantTypes,
grantTypes,
subjectType,
subjectType,
tokenEndpointAuthMethod,
tokenEndpointAuthMethod,
additionalParameters,
additionalParameters,
serviceConfiguration,
serviceConfiguration,
convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds),
convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds),
];
];
if (Platform.OS === 'android') {
if (Platform.OS === 'android') {
nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests);
nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests);
nativeMethodArguments.push(customHeaders);
nativeMethodArguments.push(customHeaders);
}
}
if (Platform.OS === 'ios') {
if (Platform.OS === 'ios') {
nativeMethodArguments.push(additionalHeaders);
nativeMethodArguments.push(additionalHeaders);
}
}
return RNAppAuth.register(...nativeMethodArguments);
return RNAppAuth.register(...nativeMethodArguments);
};
};
export const authorize = ({
export const authorize = ({
issuer,
issuer,
redirectUrl,
redirectUrl,
clientId,
clientId,
clientSecret,
clientSecret,
scopes,
scopes,
useNonce = true,
useNonce = true,
usePKCE = true,
usePKCE = true,
additionalParameters,
additionalParameters,
serviceConfiguration,
serviceConfiguration,
clientAuthMethod = 'basic',
clientAuthMethod = 'basic',
dangerouslyAllowInsecureHttpRequests = false,
dangerouslyAllowInsecureHttpRequests = false,
customHeaders,
customHeaders,
additionalHeaders,
additionalHeaders,
skipCodeExchange = false,
skipCodeExchange = false,
iosCustomBrowser = null,
iosCustomBrowser = null,
androidAllowCustomBrowsers = null,
androidAllowCustomBrowsers = null,
androidTrustedWebActivity = false,
androidTrustedWebActivity = false,
connectionTimeoutSeconds,
connectionTimeoutSeconds,
iosPrefersEphemeralSession = false,
iosPrefersEphemeralSession = false,
}) => {
}) => {
validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration);
validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration);
validateClientId(clientId);
validateClientId(clientId);
validateRedirectUrl(redirectUrl);
validateRedirectUrl(redirectUrl);
validateHeaders(customHeaders);
validateHeaders(customHeaders);
validateAdditionalHeaders(additionalHeaders);
validateAdditionalHeaders(additionalHeaders);
validateConnectionTimeoutSeconds(connectionTimeoutSeconds);
validateConnectionTimeoutSeconds(connectionTimeoutSeconds);
// TODO: validateAdditionalParameters
// TODO: validateAdditionalParameters
const nativeMethodArguments = [
const nativeMethodArguments = [
issuer,
issuer,
redirectUrl,
redirectUrl,
clientId,
clientId,
clientSecret,
clientSecret,
scopes,
scopes,
additionalParameters,
additionalParameters,
serviceConfiguration,
serviceConfiguration,
skipCodeExchange,
skipCodeExchange,
convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds),
convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds),
];
];
if (Platform.OS === 'android') {
if (Platform.OS === 'android') {
nativeMethodArguments.push(useNonce);
nativeMethodArguments.push(useNonce);
nativeMethodArguments.push(usePKCE);
nativeMethodArguments.push(usePKCE);
nativeMethodArguments.push(clientAuthMethod);
nativeMethodArguments.push(clientAuthMethod);
nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests);
nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests);
nativeMethodArguments.push(customHeaders);
nativeMethodArguments.push(customHeaders);
nativeMethodArguments.push(androidAllowCustomBrowsers);
nativeMethodArguments.push(androidAllowCustomBrowsers);
nativeMethodArguments.push(androidTrustedWebActivity);
nativeMethodArguments.push(androidTrustedWebActivity);
}
}
if (Platform.OS === 'ios') {
if (Platform.OS === 'ios') {
nativeMethodArguments.push(additionalHeaders);
nativeMethodArguments.push(additionalHeaders);
nativeMethodArguments.push(useNonce);
nativeMethodArguments.push(useNonce);
nativeMethodArguments.push(usePKCE);
nativeMethodArguments.push(usePKCE);
nativeMethodArguments.push(iosCustomBrowser);
nativeMethodArguments.push(iosCustomBrowser);
nativeMethodArguments.push(iosPrefersEphemeralSession);
nativeMethodArguments.push(iosPrefersEphemeralSession);
}
}
return RNAppAuth.authorize(...nativeMethodArguments);
return RNAppAuth.authorize(...nativeMethodArguments);
};
};
export const refresh = (
export const refresh = (
{
{
issuer,
issuer,
redirectUrl,
redirectUrl,
clientId,
clientId,
clientSecret,
clientSecret,
scopes,
scopes,
additionalParameters = {},
additionalParameters = {},
serviceConfiguration,
serviceConfiguration,
clientAuthMethod = 'basic',
clientAuthMethod = 'basic',
dangerouslyAllowInsecureHttpRequests = false,
dangerouslyAllowInsecureHttpRequests = false,
customHeaders,
customHeaders,
additionalHeaders,
additionalHeaders,
iosCustomBrowser = null,
iosCustomBrowser = null,
androidAllowCustomBrowsers = null,
androidAllowCustomBrowsers = null,
connectionTimeoutSeconds,
connectionTimeoutSeconds,
},
},
{ refreshToken }
{ refreshToken }
) => {
) => {
validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration);
validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration);
validateClientId(clientId);
validateClientId(clientId);
validateRedirectUrl(redirectUrl);
validateRedirectUrl(redirectUrl);
validateHeaders(customHeaders);
validateHeaders(customHeaders);
validateAdditionalHeaders(additionalHeaders);
validateAdditionalHeaders(additionalHeaders);
validateConnectionTimeoutSeconds(connectionTimeoutSeconds);
validateConnectionTimeoutSeconds(connectionTimeoutSeconds);
invariant(refreshToken, 'Please pass in a refresh token');
invariant(refreshToken, 'Please pass in a refresh token');
// TODO: validateAdditionalParameters
// TODO: validateAdditionalParameters
const nativeMethodArguments = [
const nativeMethodArguments = [
issuer,
issuer,
redirectUrl,
redirectUrl,
clientId,
clientId,
clientSecret,
clientSecret,
refreshToken,
refreshToken,
scopes,
scopes,
additionalParameters,
additionalParameters,
serviceConfiguration,
serviceConfiguration,
convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds),
convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds),
];
];
if (Platform.OS === 'android') {
if (Platform.OS === 'android') {
nativeMethodArguments.push(clientAuthMethod);
nativeMethodArguments.push(clientAuthMethod);
nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests);
nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests);
nativeMethodArguments.push(customHeaders);
nativeMethodArguments.push(customHeaders);
nativeMethodArguments.push(androidAllowCustomBrowsers);
nativeMethodArguments.push(androidAllowCustomBrowsers);
}
}
if (Platform.OS === 'ios') {
if (Platform.OS === 'ios') {
nativeMethodArguments.push(additionalHeaders);
nativeMethodArguments.push(additionalHeaders);
nativeMethodArguments.push(iosCustomBrowser);
nativeMethodArguments.push(iosCustomBrowser);
}
}
return RNAppAuth.refresh(...nativeMethodArguments);
return RNAppAuth.refresh(...nativeMethodArguments);
};
};
export const revoke = async (
export const revoke = async (
{ clientId, issuer, serviceConfiguration, clientSecret },
{ clientId, issuer, serviceConfiguration, clientSecret },
{ tokenToRevoke, sendClientId = false, includeBasicAuth = false }
{ tokenToRevoke, sendClientId = false, includeBasicAuth = false }
) => {
) => {
invariant(tokenToRevoke, 'Please include the token to revoke');
invariant(tokenToRevoke, 'Please include the token to revoke');
validateClientId(clientId);
validateClientId(clientId);
validateIssuerOrServiceConfigurationRevocationEndpoint(issuer, serviceConfiguration);
validateIssuerOrServiceConfigurationRevocationEndpoint(issuer, serviceConfiguration);
let revocationEndpoint;
let revocationEndpoint;
if (serviceConfiguration && serviceConfiguration.revocationEndpoint) {
if (serviceConfiguration && serviceConfiguration.revocationEndpoint) {
revocationEndpoint = serviceConfiguration.revocationEndpoint;
revocationEndpoint = serviceConfiguration.revocationEndpoint;
} else {
} else {
const response = await fetch(`${issuer}/.well-known/openid-configuration`);
const response = await fetch(`${issuer}/.well-known/openid-configuration`);
const openidConfig = await response.json();
const openidConfig = await response.json();
invariant(
invariant(
openidConfig.revocation_endpoint,
openidConfig.revocation_endpoint,
'The openid config does not specify a revocation endpoint'
'The openid config does not specify a revocation endpoint'
);
);
revocationEndpoint = openidConfig.revocation_endpoint;
revocationEndpoint = openidConfig.revocation_endpoint;
}
}
const headers = {
const headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Type': 'application/x-www-form-urlencoded',
};
};
if (includeBasicAuth) {
if (includeBasicAuth) {
headers.Authorization = `Basic ${base64.encode(`${clientId}:${clientSecret}`)}`;
headers.Authorization = `Basic ${base64.encode(`${clientId}:${clientSecret}`)}`;
}
}
/**
/**
Identity Server insists on client_id being passed in the body,
Identity Server insists on client_id being passed in the body,
but Google does not. According to the spec, Google is right
but Google does not. According to the spec, Google is right
so defaulting to no client_id
so defaulting to no client_id
https://tools.ietf.org/html/rfc7009#section-2.1
https://tools.ietf.org/html/rfc7009#section-2.1
**/
**/
return await fetch(revocationEndpoint, {
return await fetch(revocationEndpoint, {
method: 'POST',
method: 'POST',
headers,
headers,
body: `token=${tokenToRevoke}${sendClientId ? `&client_id=${clientId}` : ''}`,
body: `token=${tokenToRevoke}${sendClientId ? `&client_id=${clientId}` : ''}`,
}).catch(error => {
}).catch(error => {
throw new Error('Failed to revoke token', error);
throw new Error('Failed to revoke token', error);
});
});
};
};
export const logout = (
export const logout = (
{
{
issuer,
issuer,
serviceConfiguration,
serviceConfiguration,
additionalParameters,
additionalParameters,
dangerouslyAllowInsecureHttpRequests = false,
dangerouslyAllowInsecureHttpRequests = false,
iosCustomBrowser = null,
iosCustomBrowser = null,
iosPrefersEphemeralSession = false,
iosPrefersEphemeralSession = false,
androidAllowCustomBrowsers = null,
androidAllowCustomBrowsers = null,
},
},
{ idToken, postLogoutRedirectUrl }
{ idToken, postLogoutRedirectUrl }
) => {
) => {
validateIssuerOrServiceConfigurationEndSessionEndpoint(issuer, serviceConfiguration);
validateIssuerOrServiceConfigurationEndSessionEndpoint(issuer, serviceConfiguration);
validateRedirectUrl(postLogoutRedirectUrl);
validateRedirectUrl(postLogoutRedirectUrl);
invariant(idToken, 'Please pass in the ID token');
invariant(idToken, 'Please pass in the ID token');
const nativeMethodArguments = [
const nativeMethodArguments = [
issuer,
issuer,
idToken,
idToken,
postLogoutRedirectUrl,
postLogoutRedirectUrl,
serviceConfiguration,
serviceConfiguration,
additionalParameters,
additionalParameters,
];
];
if (Platform.OS === 'android') {
if (Platform.OS === 'android') {
nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests);
nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests);
nativeMethodArguments.push(androidAllowCustomBrowsers);
nativeMethodArguments.push(androidAllowCustomBrowsers);
}
}
if (Platform.OS === 'ios') {
if (Platform.OS === 'ios') {
nativeMethodArguments.push(iosCustomBrowser);
nativeMethodArguments.push(iosCustomBrowser);
nativeMethodArguments.push(iosPrefersEphemeralSession);
nativeMethodArguments.push(iosPrefersEphemeralSession);
}
}
return RNAppAuth.logout(...nativeMethodArguments);
return RNAppAuth.logout(...nativeMethodArguments);
};
};
Copy
Copied
Copy
Copied
export const close = () => {
if(Platform.OS === 'ios') return RNAppAuth.cancelAuthorizationFlow();
return new Promise((resolve) => resolve());
}
Saved diffs
Original text
Open file
import invariant from 'invariant'; import { NativeModules, Platform } from 'react-native'; import base64 from 'react-native-base64'; const { RNAppAuth } = NativeModules; const validateIssuerOrServiceConfigurationEndpoints = (issuer, serviceConfiguration) => invariant( typeof issuer === 'string' || (serviceConfiguration && typeof serviceConfiguration.authorizationEndpoint === 'string' && typeof serviceConfiguration.tokenEndpoint === 'string'), 'Config error: you must provide either an issuer or a service endpoints' ); const validateIssuerOrServiceConfigurationRegistrationEndpoint = (issuer, serviceConfiguration) => invariant( typeof issuer === 'string' || (serviceConfiguration && typeof serviceConfiguration.registrationEndpoint === 'string'), 'Config error: you must provide either an issuer or a registration endpoint' ); const validateIssuerOrServiceConfigurationRevocationEndpoint = (issuer, serviceConfiguration) => invariant( typeof issuer === 'string' || (serviceConfiguration && typeof serviceConfiguration.revocationEndpoint === 'string'), 'Config error: you must provide either an issuer or a revocation endpoint' ); const validateIssuerOrServiceConfigurationEndSessionEndpoint = (issuer, serviceConfiguration) => invariant( typeof issuer === 'string' || (serviceConfiguration && typeof serviceConfiguration.endSessionEndpoint === 'string'), 'Config error: you must provide either an issuer or an end session endpoint' ); const validateClientId = clientId => invariant(typeof clientId === 'string', 'Config error: clientId must be a string'); const validateRedirectUrl = redirectUrl => invariant(typeof redirectUrl === 'string', 'Config error: redirectUrl must be a string'); const validateHeaders = headers => { if (!headers) { return; } const customHeaderTypeErrorMessage = 'Config error: customHeaders type must be { token?: { [key: string]: string }, authorize?: { [key: string]: string }, register: { [key: string]: string }}'; const authorizedKeys = ['token', 'authorize', 'register']; const keys = Object.keys(headers); const correctKeys = keys.filter(key => authorizedKeys.includes(key)); invariant( keys.length <= authorizedKeys.length && correctKeys.length > 0 && correctKeys.length === keys.length, customHeaderTypeErrorMessage ); Object.values(headers).forEach(value => { invariant(typeof value === 'object', customHeaderTypeErrorMessage); invariant( Object.values(value).filter(key => typeof key !== 'string').length === 0, customHeaderTypeErrorMessage ); }); }; const validateAdditionalHeaders = headers => { if (!headers) { return; } const errorMessage = 'Config error: additionalHeaders must be { [key: string]: string }'; invariant(typeof headers === 'object', errorMessage); invariant( Object.values(headers).filter(key => typeof key !== 'string').length === 0, errorMessage ); }; const validateConnectionTimeoutSeconds = timeout => { if (!timeout) { return; } invariant(typeof timeout === 'number', 'Config error: connectionTimeoutSeconds must be a number'); }; export const SECOND_IN_MS = 1000; export const DEFAULT_TIMEOUT_IOS = 60; export const DEFAULT_TIMEOUT_ANDROID = 15; const convertTimeoutForPlatform = ( platform, connectionTimeout = Platform.OS === 'ios' ? DEFAULT_TIMEOUT_IOS : DEFAULT_TIMEOUT_ANDROID ) => (platform === 'android' ? connectionTimeout * SECOND_IN_MS : connectionTimeout); export const prefetchConfiguration = async ({ warmAndPrefetchChrome = false, issuer, redirectUrl, clientId, scopes, serviceConfiguration, dangerouslyAllowInsecureHttpRequests = false, customHeaders, connectionTimeoutSeconds, }) => { if (Platform.OS === 'android') { validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration); validateClientId(clientId); validateRedirectUrl(redirectUrl); validateHeaders(customHeaders); validateConnectionTimeoutSeconds(connectionTimeoutSeconds); const nativeMethodArguments = [ warmAndPrefetchChrome, issuer, redirectUrl, clientId, scopes, serviceConfiguration, dangerouslyAllowInsecureHttpRequests, customHeaders, convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds), ]; RNAppAuth.prefetchConfiguration(...nativeMethodArguments); } }; export const register = ({ issuer, redirectUrls, responseTypes, grantTypes, subjectType, tokenEndpointAuthMethod, additionalParameters, serviceConfiguration, dangerouslyAllowInsecureHttpRequests = false, customHeaders, additionalHeaders, connectionTimeoutSeconds, }) => { validateIssuerOrServiceConfigurationRegistrationEndpoint(issuer, serviceConfiguration); validateHeaders(customHeaders); validateAdditionalHeaders(additionalHeaders); validateConnectionTimeoutSeconds(connectionTimeoutSeconds); invariant( Array.isArray(redirectUrls) && redirectUrls.every(url => typeof url === 'string'), 'Config error: redirectUrls must be an Array of strings' ); invariant( responseTypes == null || (Array.isArray(responseTypes) && responseTypes.every(rt => typeof rt === 'string')), 'Config error: if provided, responseTypes must be an Array of strings' ); invariant( grantTypes == null || (Array.isArray(grantTypes) && grantTypes.every(gt => typeof gt === 'string')), 'Config error: if provided, grantTypes must be an Array of strings' ); invariant( subjectType == null || typeof subjectType === 'string', 'Config error: if provided, subjectType must be a string' ); invariant( tokenEndpointAuthMethod == null || typeof tokenEndpointAuthMethod === 'string', 'Config error: if provided, tokenEndpointAuthMethod must be a string' ); const nativeMethodArguments = [ issuer, redirectUrls, responseTypes, grantTypes, subjectType, tokenEndpointAuthMethod, additionalParameters, serviceConfiguration, convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds), ]; if (Platform.OS === 'android') { nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests); nativeMethodArguments.push(customHeaders); } if (Platform.OS === 'ios') { nativeMethodArguments.push(additionalHeaders); } return RNAppAuth.register(...nativeMethodArguments); }; export const authorize = ({ issuer, redirectUrl, clientId, clientSecret, scopes, useNonce = true, usePKCE = true, additionalParameters, serviceConfiguration, clientAuthMethod = 'basic', dangerouslyAllowInsecureHttpRequests = false, customHeaders, additionalHeaders, skipCodeExchange = false, iosCustomBrowser = null, androidAllowCustomBrowsers = null, androidTrustedWebActivity = false, connectionTimeoutSeconds, iosPrefersEphemeralSession = false, }) => { validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration); validateClientId(clientId); validateRedirectUrl(redirectUrl); validateHeaders(customHeaders); validateAdditionalHeaders(additionalHeaders); validateConnectionTimeoutSeconds(connectionTimeoutSeconds); // TODO: validateAdditionalParameters const nativeMethodArguments = [ issuer, redirectUrl, clientId, clientSecret, scopes, additionalParameters, serviceConfiguration, skipCodeExchange, convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds), ]; if (Platform.OS === 'android') { nativeMethodArguments.push(useNonce); nativeMethodArguments.push(usePKCE); nativeMethodArguments.push(clientAuthMethod); nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests); nativeMethodArguments.push(customHeaders); nativeMethodArguments.push(androidAllowCustomBrowsers); nativeMethodArguments.push(androidTrustedWebActivity); } if (Platform.OS === 'ios') { nativeMethodArguments.push(additionalHeaders); nativeMethodArguments.push(useNonce); nativeMethodArguments.push(usePKCE); nativeMethodArguments.push(iosCustomBrowser); nativeMethodArguments.push(iosPrefersEphemeralSession); } return RNAppAuth.authorize(...nativeMethodArguments); }; export const refresh = ( { issuer, redirectUrl, clientId, clientSecret, scopes, additionalParameters = {}, serviceConfiguration, clientAuthMethod = 'basic', dangerouslyAllowInsecureHttpRequests = false, customHeaders, additionalHeaders, iosCustomBrowser = null, androidAllowCustomBrowsers = null, connectionTimeoutSeconds, }, { refreshToken } ) => { validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration); validateClientId(clientId); validateRedirectUrl(redirectUrl); validateHeaders(customHeaders); validateAdditionalHeaders(additionalHeaders); validateConnectionTimeoutSeconds(connectionTimeoutSeconds); invariant(refreshToken, 'Please pass in a refresh token'); // TODO: validateAdditionalParameters const nativeMethodArguments = [ issuer, redirectUrl, clientId, clientSecret, refreshToken, scopes, additionalParameters, serviceConfiguration, convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds), ]; if (Platform.OS === 'android') { nativeMethodArguments.push(clientAuthMethod); nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests); nativeMethodArguments.push(customHeaders); nativeMethodArguments.push(androidAllowCustomBrowsers); } if (Platform.OS === 'ios') { nativeMethodArguments.push(additionalHeaders); nativeMethodArguments.push(iosCustomBrowser); } return RNAppAuth.refresh(...nativeMethodArguments); }; export const revoke = async ( { clientId, issuer, serviceConfiguration, clientSecret }, { tokenToRevoke, sendClientId = false, includeBasicAuth = false } ) => { invariant(tokenToRevoke, 'Please include the token to revoke'); validateClientId(clientId); validateIssuerOrServiceConfigurationRevocationEndpoint(issuer, serviceConfiguration); let revocationEndpoint; if (serviceConfiguration && serviceConfiguration.revocationEndpoint) { revocationEndpoint = serviceConfiguration.revocationEndpoint; } else { const response = await fetch(`${issuer}/.well-known/openid-configuration`); const openidConfig = await response.json(); invariant( openidConfig.revocation_endpoint, 'The openid config does not specify a revocation endpoint' ); revocationEndpoint = openidConfig.revocation_endpoint; } const headers = { 'Content-Type': 'application/x-www-form-urlencoded', }; if (includeBasicAuth) { headers.Authorization = `Basic ${base64.encode(`${clientId}:${clientSecret}`)}`; } /** Identity Server insists on client_id being passed in the body, but Google does not. According to the spec, Google is right so defaulting to no client_id https://tools.ietf.org/html/rfc7009#section-2.1 **/ return await fetch(revocationEndpoint, { method: 'POST', headers, body: `token=${tokenToRevoke}${sendClientId ? `&client_id=${clientId}` : ''}`, }).catch(error => { throw new Error('Failed to revoke token', error); }); }; export const logout = ( { issuer, serviceConfiguration, additionalParameters, dangerouslyAllowInsecureHttpRequests = false, iosCustomBrowser = null, iosPrefersEphemeralSession = false, androidAllowCustomBrowsers = null, }, { idToken, postLogoutRedirectUrl } ) => { validateIssuerOrServiceConfigurationEndSessionEndpoint(issuer, serviceConfiguration); validateRedirectUrl(postLogoutRedirectUrl); invariant(idToken, 'Please pass in the ID token'); const nativeMethodArguments = [ issuer, idToken, postLogoutRedirectUrl, serviceConfiguration, additionalParameters, ]; if (Platform.OS === 'android') { nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests); nativeMethodArguments.push(androidAllowCustomBrowsers); } if (Platform.OS === 'ios') { nativeMethodArguments.push(iosCustomBrowser); nativeMethodArguments.push(iosPrefersEphemeralSession); } return RNAppAuth.logout(...nativeMethodArguments); };
Changed text
Open file
import invariant from 'invariant'; import { NativeModules, Platform } from 'react-native'; import base64 from 'react-native-base64'; const { RNAppAuth } = NativeModules; const validateIssuerOrServiceConfigurationEndpoints = (issuer, serviceConfiguration) => invariant( typeof issuer === 'string' || (serviceConfiguration && typeof serviceConfiguration.authorizationEndpoint === 'string' && typeof serviceConfiguration.tokenEndpoint === 'string'), 'Config error: you must provide either an issuer or a service endpoints' ); const validateIssuerOrServiceConfigurationRegistrationEndpoint = (issuer, serviceConfiguration) => invariant( typeof issuer === 'string' || (serviceConfiguration && typeof serviceConfiguration.registrationEndpoint === 'string'), 'Config error: you must provide either an issuer or a registration endpoint' ); const validateIssuerOrServiceConfigurationRevocationEndpoint = (issuer, serviceConfiguration) => invariant( typeof issuer === 'string' || (serviceConfiguration && typeof serviceConfiguration.revocationEndpoint === 'string'), 'Config error: you must provide either an issuer or a revocation endpoint' ); const validateIssuerOrServiceConfigurationEndSessionEndpoint = (issuer, serviceConfiguration) => invariant( typeof issuer === 'string' || (serviceConfiguration && typeof serviceConfiguration.endSessionEndpoint === 'string'), 'Config error: you must provide either an issuer or an end session endpoint' ); const validateClientId = clientId => invariant(typeof clientId === 'string', 'Config error: clientId must be a string'); const validateRedirectUrl = redirectUrl => invariant(typeof redirectUrl === 'string', 'Config error: redirectUrl must be a string'); const validateHeaders = headers => { if (!headers) { return; } const customHeaderTypeErrorMessage = 'Config error: customHeaders type must be { token?: { [key: string]: string }, authorize?: { [key: string]: string }, register: { [key: string]: string }}'; const authorizedKeys = ['token', 'authorize', 'register']; const keys = Object.keys(headers); const correctKeys = keys.filter(key => authorizedKeys.includes(key)); invariant( keys.length <= authorizedKeys.length && correctKeys.length > 0 && correctKeys.length === keys.length, customHeaderTypeErrorMessage ); Object.values(headers).forEach(value => { invariant(typeof value === 'object', customHeaderTypeErrorMessage); invariant( Object.values(value).filter(key => typeof key !== 'string').length === 0, customHeaderTypeErrorMessage ); }); }; const validateAdditionalHeaders = headers => { if (!headers) { return; } const errorMessage = 'Config error: additionalHeaders must be { [key: string]: string }'; invariant(typeof headers === 'object', errorMessage); invariant( Object.values(headers).filter(key => typeof key !== 'string').length === 0, errorMessage ); }; const validateConnectionTimeoutSeconds = timeout => { if (!timeout) { return; } invariant(typeof timeout === 'number', 'Config error: connectionTimeoutSeconds must be a number'); }; export const SECOND_IN_MS = 1000; export const DEFAULT_TIMEOUT_IOS = 60; export const DEFAULT_TIMEOUT_ANDROID = 15; const convertTimeoutForPlatform = ( platform, connectionTimeout = Platform.OS === 'ios' ? DEFAULT_TIMEOUT_IOS : DEFAULT_TIMEOUT_ANDROID ) => (platform === 'android' ? connectionTimeout * SECOND_IN_MS : connectionTimeout); export const prefetchConfiguration = async ({ warmAndPrefetchChrome = false, issuer, redirectUrl, clientId, scopes, serviceConfiguration, dangerouslyAllowInsecureHttpRequests = false, customHeaders, connectionTimeoutSeconds, }) => { if (Platform.OS === 'android') { validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration); validateClientId(clientId); validateRedirectUrl(redirectUrl); validateHeaders(customHeaders); validateConnectionTimeoutSeconds(connectionTimeoutSeconds); const nativeMethodArguments = [ warmAndPrefetchChrome, issuer, redirectUrl, clientId, scopes, serviceConfiguration, dangerouslyAllowInsecureHttpRequests, customHeaders, convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds), ]; RNAppAuth.prefetchConfiguration(...nativeMethodArguments); } }; export const register = ({ issuer, redirectUrls, responseTypes, grantTypes, subjectType, tokenEndpointAuthMethod, additionalParameters, serviceConfiguration, dangerouslyAllowInsecureHttpRequests = false, customHeaders, additionalHeaders, connectionTimeoutSeconds, }) => { validateIssuerOrServiceConfigurationRegistrationEndpoint(issuer, serviceConfiguration); validateHeaders(customHeaders); validateAdditionalHeaders(additionalHeaders); validateConnectionTimeoutSeconds(connectionTimeoutSeconds); invariant( Array.isArray(redirectUrls) && redirectUrls.every(url => typeof url === 'string'), 'Config error: redirectUrls must be an Array of strings' ); invariant( responseTypes == null || (Array.isArray(responseTypes) && responseTypes.every(rt => typeof rt === 'string')), 'Config error: if provided, responseTypes must be an Array of strings' ); invariant( grantTypes == null || (Array.isArray(grantTypes) && grantTypes.every(gt => typeof gt === 'string')), 'Config error: if provided, grantTypes must be an Array of strings' ); invariant( subjectType == null || typeof subjectType === 'string', 'Config error: if provided, subjectType must be a string' ); invariant( tokenEndpointAuthMethod == null || typeof tokenEndpointAuthMethod === 'string', 'Config error: if provided, tokenEndpointAuthMethod must be a string' ); const nativeMethodArguments = [ issuer, redirectUrls, responseTypes, grantTypes, subjectType, tokenEndpointAuthMethod, additionalParameters, serviceConfiguration, convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds), ]; if (Platform.OS === 'android') { nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests); nativeMethodArguments.push(customHeaders); } if (Platform.OS === 'ios') { nativeMethodArguments.push(additionalHeaders); } return RNAppAuth.register(...nativeMethodArguments); }; export const authorize = ({ issuer, redirectUrl, clientId, clientSecret, scopes, useNonce = true, usePKCE = true, additionalParameters, serviceConfiguration, clientAuthMethod = 'basic', dangerouslyAllowInsecureHttpRequests = false, customHeaders, additionalHeaders, skipCodeExchange = false, iosCustomBrowser = null, androidAllowCustomBrowsers = null, androidTrustedWebActivity = false, connectionTimeoutSeconds, iosPrefersEphemeralSession = false, }) => { validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration); validateClientId(clientId); validateRedirectUrl(redirectUrl); validateHeaders(customHeaders); validateAdditionalHeaders(additionalHeaders); validateConnectionTimeoutSeconds(connectionTimeoutSeconds); // TODO: validateAdditionalParameters const nativeMethodArguments = [ issuer, redirectUrl, clientId, clientSecret, scopes, additionalParameters, serviceConfiguration, skipCodeExchange, convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds), ]; if (Platform.OS === 'android') { nativeMethodArguments.push(useNonce); nativeMethodArguments.push(usePKCE); nativeMethodArguments.push(clientAuthMethod); nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests); nativeMethodArguments.push(customHeaders); nativeMethodArguments.push(androidAllowCustomBrowsers); nativeMethodArguments.push(androidTrustedWebActivity); } if (Platform.OS === 'ios') { nativeMethodArguments.push(additionalHeaders); nativeMethodArguments.push(useNonce); nativeMethodArguments.push(usePKCE); nativeMethodArguments.push(iosCustomBrowser); nativeMethodArguments.push(iosPrefersEphemeralSession); } return RNAppAuth.authorize(...nativeMethodArguments); }; export const refresh = ( { issuer, redirectUrl, clientId, clientSecret, scopes, additionalParameters = {}, serviceConfiguration, clientAuthMethod = 'basic', dangerouslyAllowInsecureHttpRequests = false, customHeaders, additionalHeaders, iosCustomBrowser = null, androidAllowCustomBrowsers = null, connectionTimeoutSeconds, }, { refreshToken } ) => { validateIssuerOrServiceConfigurationEndpoints(issuer, serviceConfiguration); validateClientId(clientId); validateRedirectUrl(redirectUrl); validateHeaders(customHeaders); validateAdditionalHeaders(additionalHeaders); validateConnectionTimeoutSeconds(connectionTimeoutSeconds); invariant(refreshToken, 'Please pass in a refresh token'); // TODO: validateAdditionalParameters const nativeMethodArguments = [ issuer, redirectUrl, clientId, clientSecret, refreshToken, scopes, additionalParameters, serviceConfiguration, convertTimeoutForPlatform(Platform.OS, connectionTimeoutSeconds), ]; if (Platform.OS === 'android') { nativeMethodArguments.push(clientAuthMethod); nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests); nativeMethodArguments.push(customHeaders); nativeMethodArguments.push(androidAllowCustomBrowsers); } if (Platform.OS === 'ios') { nativeMethodArguments.push(additionalHeaders); nativeMethodArguments.push(iosCustomBrowser); } return RNAppAuth.refresh(...nativeMethodArguments); }; export const revoke = async ( { clientId, issuer, serviceConfiguration, clientSecret }, { tokenToRevoke, sendClientId = false, includeBasicAuth = false } ) => { invariant(tokenToRevoke, 'Please include the token to revoke'); validateClientId(clientId); validateIssuerOrServiceConfigurationRevocationEndpoint(issuer, serviceConfiguration); let revocationEndpoint; if (serviceConfiguration && serviceConfiguration.revocationEndpoint) { revocationEndpoint = serviceConfiguration.revocationEndpoint; } else { const response = await fetch(`${issuer}/.well-known/openid-configuration`); const openidConfig = await response.json(); invariant( openidConfig.revocation_endpoint, 'The openid config does not specify a revocation endpoint' ); revocationEndpoint = openidConfig.revocation_endpoint; } const headers = { 'Content-Type': 'application/x-www-form-urlencoded', }; if (includeBasicAuth) { headers.Authorization = `Basic ${base64.encode(`${clientId}:${clientSecret}`)}`; } /** Identity Server insists on client_id being passed in the body, but Google does not. According to the spec, Google is right so defaulting to no client_id https://tools.ietf.org/html/rfc7009#section-2.1 **/ return await fetch(revocationEndpoint, { method: 'POST', headers, body: `token=${tokenToRevoke}${sendClientId ? `&client_id=${clientId}` : ''}`, }).catch(error => { throw new Error('Failed to revoke token', error); }); }; export const logout = ( { issuer, serviceConfiguration, additionalParameters, dangerouslyAllowInsecureHttpRequests = false, iosCustomBrowser = null, iosPrefersEphemeralSession = false, androidAllowCustomBrowsers = null, }, { idToken, postLogoutRedirectUrl } ) => { validateIssuerOrServiceConfigurationEndSessionEndpoint(issuer, serviceConfiguration); validateRedirectUrl(postLogoutRedirectUrl); invariant(idToken, 'Please pass in the ID token'); const nativeMethodArguments = [ issuer, idToken, postLogoutRedirectUrl, serviceConfiguration, additionalParameters, ]; if (Platform.OS === 'android') { nativeMethodArguments.push(dangerouslyAllowInsecureHttpRequests); nativeMethodArguments.push(androidAllowCustomBrowsers); } if (Platform.OS === 'ios') { nativeMethodArguments.push(iosCustomBrowser); nativeMethodArguments.push(iosPrefersEphemeralSession); } return RNAppAuth.logout(...nativeMethodArguments); }; export const close = () => { if(Platform.OS === 'ios') return RNAppAuth.cancelAuthorizationFlow(); return new Promise((resolve) => resolve()); }
Find difference