1import { useCallback, useMemo, useEffect, useState } from 'react'; 2import { AuthRequest } from './AuthRequest'; 3import { resolveDiscoveryAsync } from './Discovery'; 4// @needsAudit 5/** 6 * Given an OpenID Connect issuer URL, this will fetch and return the [`DiscoveryDocument`](#discoverydocument) 7 * (a collection of URLs) from the resource provider. 8 * 9 * @param issuerOrDiscovery URL using the `https` scheme with no query or fragment component that the OP asserts as its Issuer Identifier. 10 * @return Returns `null` until the [`DiscoveryDocument`](#discoverydocument) has been fetched from the provided issuer URL. 11 * 12 * @example 13 * ```ts 14 * const discovery = useAutoDiscovery('https://example.com/auth'); 15 * ``` 16 */ 17export function useAutoDiscovery(issuerOrDiscovery) { 18 const [discovery, setDiscovery] = useState(null); 19 useEffect(() => { 20 let isAllowed = true; 21 resolveDiscoveryAsync(issuerOrDiscovery).then((discovery) => { 22 if (isAllowed) { 23 setDiscovery(discovery); 24 } 25 }); 26 return () => { 27 isAllowed = false; 28 }; 29 }, [issuerOrDiscovery]); 30 return discovery; 31} 32export function useLoadedAuthRequest(config, discovery, AuthRequestInstance) { 33 const [request, setRequest] = useState(null); 34 const scopeString = useMemo(() => config.scopes?.join(','), [config.scopes]); 35 const extraParamsString = useMemo(() => JSON.stringify(config.extraParams || {}), [config.extraParams]); 36 useEffect(() => { 37 let isMounted = true; 38 if (discovery) { 39 const request = new AuthRequestInstance(config); 40 request.makeAuthUrlAsync(discovery).then(() => { 41 if (isMounted) { 42 setRequest(request); 43 } 44 }); 45 } 46 return () => { 47 isMounted = false; 48 }; 49 }, [ 50 discovery?.authorizationEndpoint, 51 config.clientId, 52 config.redirectUri, 53 config.responseType, 54 config.prompt, 55 config.clientSecret, 56 config.codeChallenge, 57 config.state, 58 config.usePKCE, 59 scopeString, 60 extraParamsString, 61 ]); 62 return request; 63} 64export function useAuthRequestResult(request, discovery, customOptions = {}) { 65 const [result, setResult] = useState(null); 66 const promptAsync = useCallback(async ({ windowFeatures = {}, ...options } = {}) => { 67 if (!discovery || !request) { 68 throw new Error('Cannot prompt to authenticate until the request has finished loading.'); 69 } 70 const inputOptions = { 71 ...customOptions, 72 ...options, 73 windowFeatures: { 74 ...(customOptions.windowFeatures ?? {}), 75 ...windowFeatures, 76 }, 77 }; 78 const result = await request?.promptAsync(discovery, inputOptions); 79 setResult(result); 80 return result; 81 }, [request?.url, discovery?.authorizationEndpoint]); 82 return [result, promptAsync]; 83} 84// @needsAudit 85/** 86 * Load an authorization request for a code. When the prompt method completes then the response will be fulfilled. 87 * 88 * > In order to close the popup window on web, you need to invoke `WebBrowser.maybeCompleteAuthSession()`. 89 * > See the [Identity example](/guides/authentication#identityserver-4) for more info. 90 * 91 * If an Implicit grant flow was used, you can pass the `response.params` to `TokenResponse.fromQueryParams()` 92 * to get a `TokenResponse` instance which you can use to easily refresh the token. 93 * 94 * @param config A valid [`AuthRequestConfig`](#authrequestconfig) that specifies what provider to use. 95 * @param discovery A loaded [`DiscoveryDocument`](#discoverydocument) with endpoints used for authenticating. 96 * Only `authorizationEndpoint` is required for requesting an authorization code. 97 * 98 * @return Returns a loaded request, a response, and a prompt method in a single array in the following order: 99 * - `request` - An instance of [`AuthRequest`](#authrequest) that can be used to prompt the user for authorization. 100 * This will be `null` until the auth request has finished loading. 101 * - `response` - This is `null` until `promptAsync` has been invoked. Once fulfilled it will return information about the authorization. 102 * - `promptAsync` - When invoked, a web browser will open up and prompt the user for authentication. 103 * Accepts an [`AuthRequestPromptOptions`](#authrequestpromptoptions) object with options about how the prompt will execute. 104 * 105 * @example 106 * ```ts 107 * const [request, response, promptAsync] = useAuthRequest({ ... }, { ... }); 108 * ``` 109 */ 110export function useAuthRequest(config, discovery) { 111 const request = useLoadedAuthRequest(config, discovery, AuthRequest); 112 const [result, promptAsync] = useAuthRequestResult(request, discovery); 113 return [request, result, promptAsync]; 114} 115//# sourceMappingURL=AuthRequestHooks.js.map