diff --git a/docs/react-oidc-context.api.md b/docs/react-oidc-context.api.md index d2876ff8..12314714 100644 --- a/docs/react-oidc-context.api.md +++ b/docs/react-oidc-context.api.md @@ -132,11 +132,24 @@ export const hasAuthParams: (location?: Location) => boolean; // @public (undocumented) export const useAuth: () => AuthContextProps; -// Warning: (ae-forgotten-export) The symbol "UseAutoSignInProps" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "UseAutoSignInReturn" needs to be exported by the entry point index.d.ts // // @public -export const useAutoSignin: (input?: UseAutoSignInProps) => UseAutoSignInReturn; +export function useAutoSignin(options: { + signinMethod: "signinPopup"; + args?: SigninPopupArgs; +}): UseAutoSignInReturn; + +// @public +export function useAutoSignin(options: { + signinMethod: "signinRedirect"; + args?: SigninRedirectArgs; +}): UseAutoSignInReturn; + +// @public +export function useAutoSignin(options?: { + args?: SigninRedirectArgs; +}): UseAutoSignInReturn; // @public export function withAuth

(Component: React_2.ComponentType

): React_2.ComponentType>; diff --git a/src/useAutoSignin.ts b/src/useAutoSignin.ts index 215124e8..db91b79a 100644 --- a/src/useAutoSignin.ts +++ b/src/useAutoSignin.ts @@ -1,34 +1,76 @@ import React from "react"; import { useAuth } from "./useAuth"; import { hasAuthParams } from "./utils"; -import type { AuthContextProps } from "./AuthContext"; import type { AuthState } from "./AuthState"; - -type UseAutoSignInProps = { - signinMethod?: keyof Pick; -} +import type { + SigninPopupArgs, SigninRedirectArgs, +} from "oidc-client-ts"; type UseAutoSignInReturn = Pick /** * @public * - * Automatically attempts to sign in a user based on the provided sign-in method and authentication state. + * Automatically attempts to sign in a user using popup method. + * + * This hook manages automatic sign-in behavior for a user. It uses the popup sign-in + * method, the current authentication state, and ensures the sign-in attempt is made only once + * in the application context. + * + * Does not support the `signinResourceOwnerCredentials` method! + * + * @param options - Configuration object with `signinMethod: "signinPopup"` and optional `args` for popup-specific settings (popup window features, redirect_uri, etc.). + * + * @returns The current status of the authentication process. + */ +export function useAutoSignin(options: { + signinMethod: "signinPopup"; + args?: SigninPopupArgs; +}): UseAutoSignInReturn; + +/** + * @public + * + * Automatically attempts to sign in a user using redirect method. * - * This hook manages automatic sign-in behavior for a user. It uses the specified sign-in + * This hook manages automatic sign-in behavior for a user. It uses the redirect sign-in * method, the current authentication state, and ensures the sign-in attempt is made only once * in the application context. * * Does not support the `signinResourceOwnerCredentials` method! * - * @param options - (Optional) Configuration object for the sign-in method. Default to `{ signinMethod: "signinRedirect" }`. - * Possible values for `signinMethod` are: - * - `"signinRedirect"`: Redirects the user to the sign-in page (default). - * - `"signinPopup"`: Signs in the user through a popup. + * @param options - Configuration object with `signinMethod: "signinRedirect"` and optional `args` for redirect-specific settings (redirect_uri, state, extraQueryParams, etc.). * * @returns The current status of the authentication process. */ -export const useAutoSignin = ({ signinMethod = "signinRedirect" }: UseAutoSignInProps = {}): UseAutoSignInReturn => { +export function useAutoSignin(options: { + signinMethod: "signinRedirect"; + args?: SigninRedirectArgs; +}): UseAutoSignInReturn; + +/** + * @public + * + * Automatically attempts to sign in a user using the default redirect method. + * + * This hook manages automatic sign-in behavior for a user. It uses the redirect sign-in + * method by default, the current authentication state, and ensures the sign-in attempt is made only once + * in the application context. + * + * Does not support the `signinResourceOwnerCredentials` method! + * + * @param options - (Optional) Configuration object. Defaults to `{ signinMethod: "signinRedirect" }`. May include optional `args` for redirect-specific settings (redirect_uri, state, extraQueryParams, etc.). + * + * @returns The current status of the authentication process. + */ +export function useAutoSignin(options?: { + args?: SigninRedirectArgs; +}): UseAutoSignInReturn; + +export function useAutoSignin({ signinMethod = "signinRedirect", args }: { + signinMethod?: "signinRedirect" | "signinPopup"; + args?: SigninPopupArgs | SigninRedirectArgs; +} = {}): UseAutoSignInReturn { const auth = useAuth(); const [hasTriedSignin, setHasTriedSignin] = React.useState(false); @@ -39,17 +81,17 @@ export const useAutoSignin = ({ signinMethod = "signinRedirect" }: UseAutoSignIn if (shouldAttemptSignin) { switch (signinMethod) { case "signinPopup": - void auth.signinPopup(); + void auth.signinPopup(args); break; case "signinRedirect": default: - void auth.signinRedirect(); + void auth.signinRedirect(args); break; } setHasTriedSignin(true); } - }, [auth, hasTriedSignin, shouldAttemptSignin, signinMethod]); + }, [args, auth, hasTriedSignin, shouldAttemptSignin, signinMethod]); return { isLoading: auth.isLoading, diff --git a/test/useAutoSignin.test.tsx b/test/useAutoSignin.test.tsx index 9ba965e7..9754256d 100644 --- a/test/useAutoSignin.test.tsx +++ b/test/useAutoSignin.test.tsx @@ -52,4 +52,77 @@ describe("useAutoSignin", () => { expect(UserManager.prototype.getUser).toHaveBeenCalled(); }); + it("should pass args to signinRedirect when provided", async () => { + const wrapper = createWrapper({ ...settingsStub }); + const redirectArgs = { + redirect_uri: "custom_redirect", + state: "custom_state", + }; + const { result } = renderHook(() => useAutoSignin({ + signinMethod: "signinRedirect", + args: redirectArgs, + }), { wrapper }); + + await waitFor(() => expect(result.current).toBeDefined()); + + expect(UserManager.prototype.signinRedirect).toHaveBeenCalledWith(redirectArgs); + }); + + it("should pass args to signinPopup when provided", async () => { + const wrapper = createWrapper({ ...settingsStub }); + const popupArgs = { + redirect_uri: "custom_popup_redirect", + popupWindowFeatures: { + width: 500, + height: 600, + }, + extraQueryParams: { foo: "bar" }, + }; + const { result } = renderHook(() => useAutoSignin({ + signinMethod: "signinPopup", + args: popupArgs, + }), { wrapper }); + + await waitFor(() => expect(result.current).toBeDefined()); + + expect(UserManager.prototype.signinPopup).toHaveBeenCalledWith(popupArgs); + }); + + it("should pass args to signinRedirect when using default method", async () => { + const wrapper = createWrapper({ ...settingsStub }); + const redirectArgs = { + redirect_uri: "default_method_redirect", + extraQueryParams: { foo: "bar" }, + }; + const { result } = renderHook(() => useAutoSignin({ + args: redirectArgs, + }), { wrapper }); + + await waitFor(() => expect(result.current).toBeDefined()); + + expect(UserManager.prototype.signinRedirect).toHaveBeenCalledWith(redirectArgs); + }); + + it("should call signinRedirect without args when no args provided", async () => { + const wrapper = createWrapper({ ...settingsStub }); + const { result } = renderHook(() => useAutoSignin({ + signinMethod: "signinRedirect", + }), { wrapper }); + + await waitFor(() => expect(result.current).toBeDefined()); + + expect(UserManager.prototype.signinRedirect).toHaveBeenCalledWith(undefined); + }); + + it("should call signinPopup without args when no args provided", async () => { + const wrapper = createWrapper({ ...settingsStub }); + const { result } = renderHook(() => useAutoSignin({ + signinMethod: "signinPopup", + }), { wrapper }); + + await waitFor(() => expect(result.current).toBeDefined()); + + expect(UserManager.prototype.signinPopup).toHaveBeenCalledWith(undefined); + }); + });