1import Constants, { ExecutionEnvironment } from 'expo-constants'; 2import * as Linking from 'expo-linking'; 3import { Platform } from 'expo-modules-core'; 4import { dismissAuthSession } from 'expo-web-browser'; 5 6import { AuthRequest } from './AuthRequest'; 7import { 8 AuthRequestConfig, 9 AuthRequestPromptOptions, 10 CodeChallengeMethod, 11 Prompt, 12 ResponseType, 13} from './AuthRequest.types'; 14import { 15 AuthSessionOptions, 16 AuthSessionRedirectUriOptions, 17 AuthSessionResult, 18} from './AuthSession.types'; 19import { 20 DiscoveryDocument, 21 fetchDiscoveryAsync, 22 Issuer, 23 IssuerOrDiscovery, 24 ProviderMetadata, 25 resolveDiscoveryAsync, 26} from './Discovery'; 27import { generateHexStringAsync } from './PKCE'; 28import sessionUrlProvider from './SessionUrlProvider'; 29 30// @needsAudit 31/** 32 * Cancels an active `AuthSession` if there is one. 33 */ 34export function dismiss() { 35 dismissAuthSession(); 36} 37 38export const getDefaultReturnUrl = sessionUrlProvider.getDefaultReturnUrl; 39 40// @needsAudit @docsMissing 41/** 42 * Get the URL that your authentication provider needs to redirect to. For example: `https://auth.expo.io/@your-username/your-app-slug`. You can pass an additional path component to be appended to the default redirect URL. 43 * > **Note** This method will throw an exception if you're using the bare workflow on native. 44 * 45 * @param path 46 * @return 47 * 48 * @example 49 * ```ts 50 * const url = AuthSession.getRedirectUrl('redirect'); 51 * 52 * // Managed: https://auth.expo.io/@your-username/your-app-slug/redirect 53 * // Web: https://localhost:19006/redirect 54 * ``` 55 * 56 * @deprecated Use `makeRedirectUri()` instead. 57 */ 58export function getRedirectUrl(path?: string): string { 59 return sessionUrlProvider.getRedirectUrl({ urlPath: path }); 60} 61 62// @needsAudit 63/** 64 * Create a redirect url for the current platform and environment. You need to manually define the redirect that will be used in 65 * a bare workflow React Native app, or an Expo standalone app, this is because it cannot be inferred automatically. 66 * - **Web:** Generates a path based on the current `window.location`. For production web apps, you should hard code the URL as well. 67 * - **Managed workflow:** Uses the `scheme` property of your app config. 68 * - **Bare workflow:** Will fallback to using the `native` option for bare workflow React Native apps. 69 * 70 * @param options Additional options for configuring the path. 71 * @return The `redirectUri` to use in an authentication request. 72 * 73 * @example 74 * ```ts 75 * const redirectUri = makeRedirectUri({ 76 * scheme: 'my-scheme', 77 * path: 'redirect' 78 * }); 79 * // Development Build: my-scheme://redirect 80 * // Expo Go: exp://127.0.0.1:8081/--/redirect 81 * // Web dev: https://localhost:19006/redirect 82 * // Web prod: https://yourwebsite.com/redirect 83 * 84 * const redirectUri2 = makeRedirectUri({ 85 * scheme: 'scheme2', 86 * preferLocalhost: true, 87 * isTripleSlashed: true, 88 * }); 89 * // Development Build: scheme2:/// 90 * // Expo Go: exp://localhost:8081 91 * // Web dev: https://localhost:19006 92 * // Web prod: https://yourwebsite.com 93 * ``` 94 */ 95export function makeRedirectUri({ 96 native, 97 scheme, 98 isTripleSlashed, 99 queryParams, 100 path, 101 preferLocalhost, 102}: AuthSessionRedirectUriOptions = {}): string { 103 if ( 104 Platform.OS !== 'web' && 105 native && 106 [ExecutionEnvironment.Standalone, ExecutionEnvironment.Bare].includes( 107 Constants.executionEnvironment 108 ) 109 ) { 110 // Should use the user-defined native scheme in standalone builds 111 return native; 112 } 113 const url = Linking.createURL(path || '', { 114 isTripleSlashed, 115 scheme, 116 queryParams, 117 }); 118 119 if (preferLocalhost) { 120 const ipAddress = url.match( 121 /\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/ 122 ); 123 // Only replace if an IP address exists 124 if (ipAddress?.length) { 125 const [protocol, path] = url.split(ipAddress[0]); 126 return `${protocol}localhost${path}`; 127 } 128 } 129 130 return url; 131} 132 133// @needsAudit 134/** 135 * Build an `AuthRequest` and load it before returning. 136 * 137 * @param config A valid [`AuthRequestConfig`](#authrequestconfig) that specifies what provider to use. 138 * @param issuerOrDiscovery A loaded [`DiscoveryDocument`](#discoverydocument) or issuer URL. 139 * (Only `authorizationEndpoint` is required for requesting an authorization code). 140 * @return Returns an instance of `AuthRequest` that can be used to prompt the user for authorization. 141 */ 142export async function loadAsync( 143 config: AuthRequestConfig, 144 issuerOrDiscovery: IssuerOrDiscovery 145): Promise<AuthRequest> { 146 const request = new AuthRequest(config); 147 const discovery = await resolveDiscoveryAsync(issuerOrDiscovery); 148 await request.makeAuthUrlAsync(discovery); 149 return request; 150} 151 152export { useAutoDiscovery, useAuthRequest } from './AuthRequestHooks'; 153export { AuthError, TokenError } from './Errors'; 154 155export { 156 AuthSessionOptions, 157 AuthSessionRedirectUriOptions, 158 AuthSessionResult, 159 AuthRequest, 160 AuthRequestConfig, 161 AuthRequestPromptOptions, 162 CodeChallengeMethod, 163 DiscoveryDocument, 164 Issuer, 165 IssuerOrDiscovery, 166 Prompt, 167 ProviderMetadata, 168 ResponseType, 169 resolveDiscoveryAsync, 170 fetchDiscoveryAsync, 171 generateHexStringAsync, 172}; 173 174export { 175 // Token classes 176 TokenResponse, 177 AccessTokenRequest, 178 RefreshTokenRequest, 179 RevokeTokenRequest, 180 // Token methods 181 revokeAsync, 182 refreshAsync, 183 exchangeCodeAsync, 184 fetchUserInfoAsync, 185} from './TokenRequest'; 186 187// Token types 188export * from './TokenRequest.types'; 189 190// Provider specific types 191export { GoogleAuthRequestConfig } from './providers/Google'; 192export { FacebookAuthRequestConfig } from './providers/Facebook'; 193