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