@monocloud/auth-nextjs 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- const require_client = require('../client-BjnSJS59.cjs');
1
+ const require_client = require('../client-Be6A2vEn.cjs');
2
2
 
3
3
  exports.protectPage = require_client.protectPage;
4
4
  exports.useAuth = require_client.useAuth;
@@ -1,4 +1,4 @@
1
- import { i as ExtraAuthParams, o as GroupOptions } from "../types-BleaXQUP.mjs";
1
+ import { a as GroupOptions, i as ExtraAuthParams } from "../types-DOfZTKa6.mjs";
2
2
  import { MonoCloudUser } from "@monocloud/auth-node-core";
3
3
  import React, { ComponentType, JSX } from "react";
4
4
 
@@ -25,11 +25,88 @@ interface AuthState {
25
25
  user?: MonoCloudUser;
26
26
  /**
27
27
  * Function to refetch the authentication state.
28
+ *
28
29
  */
29
- refetch?: () => void;
30
+ refetch: (refresh?: boolean) => void;
30
31
  }
31
32
  /**
33
+ *
34
+ * Hook for getting the user's profile on client components
35
+ *
32
36
  * @returns Authentication State
37
+ *
38
+ * @example App Router
39
+ *
40
+ * ```tsx
41
+ * "use client";
42
+ *
43
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
44
+ *
45
+ * export default function Home() {
46
+ * const { user } = useAuth();
47
+ *
48
+ * return <>User Id: {user?.sub}</>;
49
+ * }
50
+ * ```
51
+ *
52
+ * @example App Router - Refetch user from Userinfo endpoint
53
+ *
54
+ * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.
55
+ * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`
56
+ *
57
+ * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**
58
+ *
59
+ * ```tsx
60
+ * "use client";
61
+ *
62
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
63
+ *
64
+ * export default function Home() {
65
+ * const { user, refetch } = useAuth();
66
+ *
67
+ * return (
68
+ * <>
69
+ * <pre>{JSON.stringify(user)}</pre>
70
+ * <button onClick={() => refetch(true)}>Refresh</button>
71
+ * </>
72
+ * );
73
+ * }
74
+ * ```
75
+ *
76
+ * @example Pages Router
77
+ *
78
+ * ```tsx
79
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
80
+ *
81
+ * export default function Home() {
82
+ * const { user } = useAuth();
83
+ *
84
+ * return <>User Id: {user?.sub}</>;
85
+ * }
86
+ * ```
87
+ *
88
+ * @example Pages Router - Refetch user from Userinfo endpoint
89
+ *
90
+ * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.
91
+ * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`
92
+ *
93
+ * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**
94
+ *
95
+ * ```tsx
96
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
97
+ *
98
+ * export default function Home() {
99
+ * const { user, refetch } = useAuth();
100
+ *
101
+ * return (
102
+ * <>
103
+ * <pre>{JSON.stringify(user)}</pre>
104
+ * <button onClick={() => refetch(true)}>Refresh</button>
105
+ * </>
106
+ * );
107
+ * }
108
+ * ```
109
+ *
33
110
  */
34
111
  declare const useAuth: () => AuthState;
35
112
  //#endregion
@@ -63,10 +140,66 @@ type ProtectPageOptions = {
63
140
  * Function to protect a client rendered page component.
64
141
  * Ensures that only authenticated users can access the component.
65
142
  *
143
+ * **Note⚠️: Since `window.location` is set as `returnUrl` query param by default, you need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for returning to the same page.**
144
+ *
66
145
  * @param Component - The component to protect.
67
146
  * @param options - The options.
68
147
  *
69
- * @returns Protected clinet rendered page component.
148
+ * @returns Protected client rendered page component.
149
+ *
150
+ * @example App Router
151
+ *
152
+ * ```tsx
153
+ * "use client";
154
+ *
155
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
156
+ *
157
+ * export default protectPage(function Home() {
158
+ * return <>You are signed in</>;
159
+ * });
160
+ * ```
161
+ *
162
+ * @example App Router with options
163
+ *
164
+ * See {@link ProtectPageOptions} for more options.
165
+ *
166
+ * ```tsx
167
+ * "use client";
168
+ *
169
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
170
+ *
171
+ * export default protectPage(
172
+ * function Home() {
173
+ * return <>You are signed in</>;
174
+ * },
175
+ * { returnUrl: "/dashboard", authParams: { loginHint: "username" } }
176
+ * );
177
+ * ```
178
+
179
+ * @example Pages Router
180
+ *
181
+ * ```tsx
182
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
183
+ *
184
+ * export default protectPage(function Home() {
185
+ * return <>You are signed in</>;
186
+ * });
187
+ * ```
188
+ *
189
+ * @example Pages Router with options
190
+ *
191
+ * See {@link ProtectPageOptions} for more options.
192
+ *
193
+ * ```tsx
194
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
195
+ *
196
+ * export default protectPage(
197
+ * function Home() {
198
+ * return <>You are signed in</>;
199
+ * },
200
+ * { returnUrl: "/dashboard", authParams: { loginHint: "username" } }
201
+ * );
202
+ * ```
70
203
  */
71
204
  declare const protectPage: <P extends object>(Component: ComponentType<P & {
72
205
  user: MonoCloudUser;
@@ -1,3 +1,3 @@
1
- import { r as useAuth, t as protectPage } from "../client-0gaUvMR7.mjs";
1
+ import { r as useAuth, t as protectPage } from "../client-CnvBgZM-.mjs";
2
2
 
3
3
  export { protectPage, useAuth };
@@ -6,29 +6,112 @@ let react = require("react");
6
6
  react = require_chunk.__toESM(react);
7
7
 
8
8
  //#region src/client/use-auth.tsx
9
+ const fetchUser = async (url) => {
10
+ const res = await fetch(url, { credentials: "include" });
11
+ if (res.status === 204) return;
12
+ if (res.ok) return res.json();
13
+ throw new Error("Failed to fetch user");
14
+ };
9
15
  /**
16
+ *
17
+ * Hook for getting the user's profile on client components
18
+ *
10
19
  * @returns Authentication State
20
+ *
21
+ * @example App Router
22
+ *
23
+ * ```tsx
24
+ * "use client";
25
+ *
26
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
27
+ *
28
+ * export default function Home() {
29
+ * const { user } = useAuth();
30
+ *
31
+ * return <>User Id: {user?.sub}</>;
32
+ * }
33
+ * ```
34
+ *
35
+ * @example App Router - Refetch user from Userinfo endpoint
36
+ *
37
+ * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.
38
+ * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`
39
+ *
40
+ * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**
41
+ *
42
+ * ```tsx
43
+ * "use client";
44
+ *
45
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
46
+ *
47
+ * export default function Home() {
48
+ * const { user, refetch } = useAuth();
49
+ *
50
+ * return (
51
+ * <>
52
+ * <pre>{JSON.stringify(user)}</pre>
53
+ * <button onClick={() => refetch(true)}>Refresh</button>
54
+ * </>
55
+ * );
56
+ * }
57
+ * ```
58
+ *
59
+ * @example Pages Router
60
+ *
61
+ * ```tsx
62
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
63
+ *
64
+ * export default function Home() {
65
+ * const { user } = useAuth();
66
+ *
67
+ * return <>User Id: {user?.sub}</>;
68
+ * }
69
+ * ```
70
+ *
71
+ * @example Pages Router - Refetch user from Userinfo endpoint
72
+ *
73
+ * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.
74
+ * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`
75
+ *
76
+ * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**
77
+ *
78
+ * ```tsx
79
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
80
+ *
81
+ * export default function Home() {
82
+ * const { user, refetch } = useAuth();
83
+ *
84
+ * return (
85
+ * <>
86
+ * <pre>{JSON.stringify(user)}</pre>
87
+ * <button onClick={() => refetch(true)}>Refresh</button>
88
+ * </>
89
+ * );
90
+ * }
91
+ * ```
92
+ *
11
93
  */
12
94
  const useAuth = () => {
13
- const { data, error, isLoading, mutate } = (0, swr.default)(process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_USER_INFO_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/api/auth/userinfo`, async (url) => {
14
- const res = await fetch(url, { credentials: "include" });
15
- if (res.status === 204) return;
16
- if (res.ok) return res.json();
17
- throw new Error("Failed to fetch user");
18
- });
95
+ const key = process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_USER_INFO_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/api/auth/userinfo`;
96
+ const { data, error, isLoading, mutate } = (0, swr.default)(key, fetchUser);
97
+ const refetch = (refresh) => {
98
+ const url = new URL(key, "https://dummy");
99
+ if (refresh) url.searchParams.set("refresh", "true");
100
+ mutate(async () => await fetchUser(url.pathname + url.search), { revalidate: false });
101
+ };
19
102
  if (error) return {
20
103
  user: void 0,
21
104
  isLoading: false,
22
105
  isAuthenticated: false,
23
106
  error,
24
- refetch: () => mutate()
107
+ refetch
25
108
  };
26
109
  if (data) return {
27
110
  user: data,
28
111
  isLoading,
29
112
  isAuthenticated: !!data && Object.keys(data).length > 0,
30
113
  error: void 0,
31
- refetch: () => mutate()
114
+ refetch
32
115
  };
33
116
  return {
34
117
  user: void 0,
@@ -64,11 +147,67 @@ const handlePageError = (error, options) => {
64
147
  /**
65
148
  * Function to protect a client rendered page component.
66
149
  * Ensures that only authenticated users can access the component.
150
+ *
151
+ * **Note⚠️: Since `window.location` is set as `returnUrl` query param by default, you need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for returning to the same page.**
67
152
  *
68
153
  * @param Component - The component to protect.
69
154
  * @param options - The options.
70
155
  *
71
- * @returns Protected clinet rendered page component.
156
+ * @returns Protected client rendered page component.
157
+ *
158
+ * @example App Router
159
+ *
160
+ * ```tsx
161
+ * "use client";
162
+ *
163
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
164
+ *
165
+ * export default protectPage(function Home() {
166
+ * return <>You are signed in</>;
167
+ * });
168
+ * ```
169
+ *
170
+ * @example App Router with options
171
+ *
172
+ * See {@link ProtectPageOptions} for more options.
173
+ *
174
+ * ```tsx
175
+ * "use client";
176
+ *
177
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
178
+ *
179
+ * export default protectPage(
180
+ * function Home() {
181
+ * return <>You are signed in</>;
182
+ * },
183
+ * { returnUrl: "/dashboard", authParams: { loginHint: "username" } }
184
+ * );
185
+ * ```
186
+
187
+ * @example Pages Router
188
+ *
189
+ * ```tsx
190
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
191
+ *
192
+ * export default protectPage(function Home() {
193
+ * return <>You are signed in</>;
194
+ * });
195
+ * ```
196
+ *
197
+ * @example Pages Router with options
198
+ *
199
+ * See {@link ProtectPageOptions} for more options.
200
+ *
201
+ * ```tsx
202
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
203
+ *
204
+ * export default protectPage(
205
+ * function Home() {
206
+ * return <>You are signed in</>;
207
+ * },
208
+ * { returnUrl: "/dashboard", authParams: { loginHint: "username" } }
209
+ * );
210
+ * ```
72
211
  */
73
212
  const protectPage = (Component, options) => {
74
213
  return (props) => {
@@ -122,4 +261,4 @@ Object.defineProperty(exports, 'useAuth', {
122
261
  return useAuth;
123
262
  }
124
263
  });
125
- //# sourceMappingURL=client-BjnSJS59.cjs.map
264
+ //# sourceMappingURL=client-Be6A2vEn.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-Be6A2vEn.cjs","names":[],"sources":["../src/client/use-auth.tsx","../src/client/protect.tsx"],"sourcesContent":["'use client';\n\nimport type { MonoCloudUser } from '@monocloud/auth-node-core';\nimport useSWR from 'swr';\n\n/**\n * Authentication State returned by `useAuth` hook.\n */\nexport interface AuthState {\n /**\n * Flag indicating if the authentication state is still loading.\n */\n isLoading: boolean;\n /**\n * Flag indicating if the user is authenticated.\n */\n isAuthenticated: boolean;\n /**\n * Error encountered during authentication, if any.\n */\n error?: Error;\n /**\n * The authenticated user's information, if available.\n */\n user?: MonoCloudUser;\n /**\n * Function to refetch the authentication state.\n *\n */\n refetch: (refresh?: boolean) => void;\n}\n\nconst fetchUser = async (url: string): Promise<MonoCloudUser | undefined> => {\n const res = await fetch(url, { credentials: 'include' });\n\n if (res.status === 204) {\n return undefined;\n }\n\n if (res.ok) {\n return res.json();\n }\n\n throw new Error('Failed to fetch user');\n};\n\n/**\n *\n * Hook for getting the user's profile on client components\n *\n * @returns Authentication State\n *\n * @example App Router\n *\n * ```tsx\n * \"use client\";\n *\n * import { useAuth } from \"@monocloud/auth-nextjs/client\";\n *\n * export default function Home() {\n * const { user } = useAuth();\n *\n * return <>User Id: {user?.sub}</>;\n * }\n * ```\n *\n * @example App Router - Refetch user from Userinfo endpoint\n *\n * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.\n * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`\n *\n * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**\n *\n * ```tsx\n * \"use client\";\n *\n * import { useAuth } from \"@monocloud/auth-nextjs/client\";\n *\n * export default function Home() {\n * const { user, refetch } = useAuth();\n *\n * return (\n * <>\n * <pre>{JSON.stringify(user)}</pre>\n * <button onClick={() => refetch(true)}>Refresh</button>\n * </>\n * );\n * }\n * ```\n *\n * @example Pages Router\n *\n * ```tsx\n * import { useAuth } from \"@monocloud/auth-nextjs/client\";\n *\n * export default function Home() {\n * const { user } = useAuth();\n *\n * return <>User Id: {user?.sub}</>;\n * }\n * ```\n *\n * @example Pages Router - Refetch user from Userinfo endpoint\n *\n * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.\n * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`\n *\n * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**\n *\n * ```tsx\n * import { useAuth } from \"@monocloud/auth-nextjs/client\";\n *\n * export default function Home() {\n * const { user, refetch } = useAuth();\n *\n * return (\n * <>\n * <pre>{JSON.stringify(user)}</pre>\n * <button onClick={() => refetch(true)}>Refresh</button>\n * </>\n * );\n * }\n * ```\n *\n */\nexport const useAuth = (): AuthState => {\n const key =\n process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_USER_INFO_URL ??\n // eslint-disable-next-line no-underscore-dangle\n `${process.env.__NEXT_ROUTER_BASEPATH ?? ''}/api/auth/userinfo`;\n\n const { data, error, isLoading, mutate } = useSWR<MonoCloudUser | undefined>(\n key,\n fetchUser\n );\n\n const refetch = (refresh?: boolean): void => {\n const url = new URL(key, 'https://dummy');\n if (refresh) {\n url.searchParams.set('refresh', 'true');\n }\n\n void mutate(async () => await fetchUser(url.pathname + url.search), {\n revalidate: false,\n });\n };\n\n if (error) {\n return {\n user: undefined,\n isLoading: false,\n isAuthenticated: false,\n error: error as Error,\n refetch,\n };\n }\n\n if (data) {\n return {\n user: data,\n isLoading,\n isAuthenticated: !!data && Object.keys(data).length > 0,\n error: undefined,\n refetch,\n };\n }\n\n return {\n user: undefined,\n isLoading,\n isAuthenticated: false,\n error: undefined,\n /* v8 ignore next -- @preserve */\n refetch: (): void => {},\n };\n};\n","/* eslint-disable react/display-name */\n'use client';\n\nimport React, { ComponentType, JSX, useEffect } from 'react';\nimport type { MonoCloudUser } from '@monocloud/auth-node-core';\nimport { isUserInGroup } from '@monocloud/auth-node-core/utils';\nimport { useAuth } from './use-auth';\nimport { ExtraAuthParams, GroupOptions } from '../types';\n\n/**\n * Options for configuring page protection.\n */\nexport type ProtectPageOptions = {\n /**\n *The url where the user will be redirected to after sign in\n */\n returnUrl?: string;\n\n /**\n * A custom react element to render when the user is not authenticated or is not a member of the specified groups.\n */\n onAccessDenied?: (user?: MonoCloudUser) => JSX.Element;\n\n /**\n * Authorization parameters to be used during authentication.\n */\n authParams?: ExtraAuthParams;\n\n /**\n * Callback function to handle errors.\n * If not provided, errors will be thrown.\n *\n * @param error - The error object.\n * @returns JSX element to handle the error.\n */\n onError?: (error: Error) => JSX.Element;\n} & GroupOptions;\n\nexport const redirectToSignIn = (\n options: { returnUrl?: string } & ExtraAuthParams\n): void => {\n const searchParams = new URLSearchParams(window.location.search);\n searchParams.set(\n 'return_url',\n options.returnUrl ?? window.location.toString()\n );\n\n if (options?.scopes) {\n searchParams.set('scope', options.scopes);\n }\n if (options?.resource) {\n searchParams.set('resource', options.resource);\n }\n\n if (options?.acrValues) {\n searchParams.set('acr_values', options.acrValues.join(' '));\n }\n\n if (options?.display) {\n searchParams.set('display', options.display);\n }\n\n if (options?.prompt) {\n searchParams.set('prompt', options.prompt);\n }\n\n if (options?.authenticatorHint) {\n searchParams.set('authenticator_hint', options.authenticatorHint);\n }\n\n if (options?.uiLocales) {\n searchParams.set('ui_locales', options.uiLocales);\n }\n\n if (options?.maxAge) {\n searchParams.set('max_age', options.maxAge.toString());\n }\n\n if (options?.loginHint) {\n searchParams.set('login_hint', options.loginHint);\n }\n\n window.location.assign(\n // eslint-disable-next-line no-underscore-dangle\n `${process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_SIGNIN_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ''}/api/auth/signin`}?${searchParams.toString()}`\n );\n};\n\nconst handlePageError = (\n error: Error,\n options?: ProtectPageOptions\n): JSX.Element => {\n /* v8 ignore else -- @preserve */\n if (options?.onError) {\n return options.onError(error);\n }\n\n /* v8 ignore next -- @preserve */\n throw error;\n};\n\n/**\n * Function to protect a client rendered page component.\n * Ensures that only authenticated users can access the component.\n * \n * **Note⚠️: Since `window.location` is set as `returnUrl` query param by default, you need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for returning to the same page.**\n *\n * @param Component - The component to protect.\n * @param options - The options.\n *\n * @returns Protected client rendered page component.\n *\n * @example App Router\n *\n * ```tsx\n * \"use client\";\n *\n * import { protectPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectPage(function Home() {\n * return <>You are signed in</>;\n * });\n * ```\n *\n * @example App Router with options\n * \n * See {@link ProtectPageOptions} for more options.\n *\n * ```tsx\n * \"use client\";\n *\n * import { protectPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectPage(\n * function Home() {\n * return <>You are signed in</>;\n * },\n * { returnUrl: \"/dashboard\", authParams: { loginHint: \"username\" } }\n * );\n * ```\n\n* @example Pages Router\n *\n * ```tsx\n * import { protectPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectPage(function Home() {\n * return <>You are signed in</>;\n * });\n * ```\n *\n * @example Pages Router with options\n * \n * See {@link ProtectPageOptions} for more options.\n *\n * ```tsx\n * import { protectPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectPage(\n * function Home() {\n * return <>You are signed in</>;\n * },\n * { returnUrl: \"/dashboard\", authParams: { loginHint: \"username\" } }\n * );\n * ```\n */\nexport const protectPage = <P extends object>(\n Component: ComponentType<P & { user: MonoCloudUser }>,\n options?: ProtectPageOptions\n): React.FC<P> => {\n return props => {\n const { user, error, isLoading } = useAuth();\n\n useEffect(() => {\n if (!user && !isLoading && !error) {\n if (options?.onAccessDenied) {\n return;\n }\n\n const authParams = options?.authParams ?? {};\n redirectToSignIn({\n returnUrl: options?.returnUrl,\n ...authParams,\n });\n }\n }, [user, isLoading, error]);\n\n if (error) {\n return handlePageError(error, options);\n }\n\n if (!user && !isLoading && options?.onAccessDenied) {\n return options.onAccessDenied();\n }\n\n if (user) {\n if (\n options?.groups &&\n !isUserInGroup(\n user,\n options.groups,\n options.groupsClaim ??\n process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n const { onAccessDenied = (): JSX.Element => <div>Access Denied</div> } =\n options;\n return onAccessDenied(user);\n }\n\n return <Component user={user} {...props} />;\n }\n\n return null;\n };\n};\n"],"mappings":"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"}
@@ -0,0 +1,244 @@
1
+ import { isUserInGroup } from "@monocloud/auth-node-core/utils";
2
+ import useSWR from "swr";
3
+ import React, { useEffect } from "react";
4
+
5
+ //#region src/client/use-auth.tsx
6
+ const fetchUser = async (url) => {
7
+ const res = await fetch(url, { credentials: "include" });
8
+ if (res.status === 204) return;
9
+ if (res.ok) return res.json();
10
+ throw new Error("Failed to fetch user");
11
+ };
12
+ /**
13
+ *
14
+ * Hook for getting the user's profile on client components
15
+ *
16
+ * @returns Authentication State
17
+ *
18
+ * @example App Router
19
+ *
20
+ * ```tsx
21
+ * "use client";
22
+ *
23
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
24
+ *
25
+ * export default function Home() {
26
+ * const { user } = useAuth();
27
+ *
28
+ * return <>User Id: {user?.sub}</>;
29
+ * }
30
+ * ```
31
+ *
32
+ * @example App Router - Refetch user from Userinfo endpoint
33
+ *
34
+ * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.
35
+ * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`
36
+ *
37
+ * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**
38
+ *
39
+ * ```tsx
40
+ * "use client";
41
+ *
42
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
43
+ *
44
+ * export default function Home() {
45
+ * const { user, refetch } = useAuth();
46
+ *
47
+ * return (
48
+ * <>
49
+ * <pre>{JSON.stringify(user)}</pre>
50
+ * <button onClick={() => refetch(true)}>Refresh</button>
51
+ * </>
52
+ * );
53
+ * }
54
+ * ```
55
+ *
56
+ * @example Pages Router
57
+ *
58
+ * ```tsx
59
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
60
+ *
61
+ * export default function Home() {
62
+ * const { user } = useAuth();
63
+ *
64
+ * return <>User Id: {user?.sub}</>;
65
+ * }
66
+ * ```
67
+ *
68
+ * @example Pages Router - Refetch user from Userinfo endpoint
69
+ *
70
+ * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.
71
+ * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`
72
+ *
73
+ * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**
74
+ *
75
+ * ```tsx
76
+ * import { useAuth } from "@monocloud/auth-nextjs/client";
77
+ *
78
+ * export default function Home() {
79
+ * const { user, refetch } = useAuth();
80
+ *
81
+ * return (
82
+ * <>
83
+ * <pre>{JSON.stringify(user)}</pre>
84
+ * <button onClick={() => refetch(true)}>Refresh</button>
85
+ * </>
86
+ * );
87
+ * }
88
+ * ```
89
+ *
90
+ */
91
+ const useAuth = () => {
92
+ const key = process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_USER_INFO_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/api/auth/userinfo`;
93
+ const { data, error, isLoading, mutate } = useSWR(key, fetchUser);
94
+ const refetch = (refresh) => {
95
+ const url = new URL(key, "https://dummy");
96
+ if (refresh) url.searchParams.set("refresh", "true");
97
+ mutate(async () => await fetchUser(url.pathname + url.search), { revalidate: false });
98
+ };
99
+ if (error) return {
100
+ user: void 0,
101
+ isLoading: false,
102
+ isAuthenticated: false,
103
+ error,
104
+ refetch
105
+ };
106
+ if (data) return {
107
+ user: data,
108
+ isLoading,
109
+ isAuthenticated: !!data && Object.keys(data).length > 0,
110
+ error: void 0,
111
+ refetch
112
+ };
113
+ return {
114
+ user: void 0,
115
+ isLoading,
116
+ isAuthenticated: false,
117
+ error: void 0,
118
+ refetch: () => {}
119
+ };
120
+ };
121
+
122
+ //#endregion
123
+ //#region src/client/protect.tsx
124
+ const redirectToSignIn = (options) => {
125
+ const searchParams = new URLSearchParams(window.location.search);
126
+ searchParams.set("return_url", options.returnUrl ?? window.location.toString());
127
+ if (options === null || options === void 0 ? void 0 : options.scopes) searchParams.set("scope", options.scopes);
128
+ if (options === null || options === void 0 ? void 0 : options.resource) searchParams.set("resource", options.resource);
129
+ if (options === null || options === void 0 ? void 0 : options.acrValues) searchParams.set("acr_values", options.acrValues.join(" "));
130
+ if (options === null || options === void 0 ? void 0 : options.display) searchParams.set("display", options.display);
131
+ if (options === null || options === void 0 ? void 0 : options.prompt) searchParams.set("prompt", options.prompt);
132
+ if (options === null || options === void 0 ? void 0 : options.authenticatorHint) searchParams.set("authenticator_hint", options.authenticatorHint);
133
+ if (options === null || options === void 0 ? void 0 : options.uiLocales) searchParams.set("ui_locales", options.uiLocales);
134
+ if (options === null || options === void 0 ? void 0 : options.maxAge) searchParams.set("max_age", options.maxAge.toString());
135
+ if (options === null || options === void 0 ? void 0 : options.loginHint) searchParams.set("login_hint", options.loginHint);
136
+ window.location.assign(`${process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_SIGNIN_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/api/auth/signin`}?${searchParams.toString()}`);
137
+ };
138
+ const handlePageError = (error, options) => {
139
+ /* v8 ignore else -- @preserve */
140
+ if (options === null || options === void 0 ? void 0 : options.onError) return options.onError(error);
141
+ /* v8 ignore next -- @preserve */
142
+ throw error;
143
+ };
144
+ /**
145
+ * Function to protect a client rendered page component.
146
+ * Ensures that only authenticated users can access the component.
147
+ *
148
+ * **Note⚠️: Since `window.location` is set as `returnUrl` query param by default, you need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for returning to the same page.**
149
+ *
150
+ * @param Component - The component to protect.
151
+ * @param options - The options.
152
+ *
153
+ * @returns Protected client rendered page component.
154
+ *
155
+ * @example App Router
156
+ *
157
+ * ```tsx
158
+ * "use client";
159
+ *
160
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
161
+ *
162
+ * export default protectPage(function Home() {
163
+ * return <>You are signed in</>;
164
+ * });
165
+ * ```
166
+ *
167
+ * @example App Router with options
168
+ *
169
+ * See {@link ProtectPageOptions} for more options.
170
+ *
171
+ * ```tsx
172
+ * "use client";
173
+ *
174
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
175
+ *
176
+ * export default protectPage(
177
+ * function Home() {
178
+ * return <>You are signed in</>;
179
+ * },
180
+ * { returnUrl: "/dashboard", authParams: { loginHint: "username" } }
181
+ * );
182
+ * ```
183
+
184
+ * @example Pages Router
185
+ *
186
+ * ```tsx
187
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
188
+ *
189
+ * export default protectPage(function Home() {
190
+ * return <>You are signed in</>;
191
+ * });
192
+ * ```
193
+ *
194
+ * @example Pages Router with options
195
+ *
196
+ * See {@link ProtectPageOptions} for more options.
197
+ *
198
+ * ```tsx
199
+ * import { protectPage } from "@monocloud/auth-nextjs/client";
200
+ *
201
+ * export default protectPage(
202
+ * function Home() {
203
+ * return <>You are signed in</>;
204
+ * },
205
+ * { returnUrl: "/dashboard", authParams: { loginHint: "username" } }
206
+ * );
207
+ * ```
208
+ */
209
+ const protectPage = (Component, options) => {
210
+ return (props) => {
211
+ const { user, error, isLoading } = useAuth();
212
+ useEffect(() => {
213
+ if (!user && !isLoading && !error) {
214
+ if (options === null || options === void 0 ? void 0 : options.onAccessDenied) return;
215
+ const authParams = (options === null || options === void 0 ? void 0 : options.authParams) ?? {};
216
+ redirectToSignIn({
217
+ returnUrl: options === null || options === void 0 ? void 0 : options.returnUrl,
218
+ ...authParams
219
+ });
220
+ }
221
+ }, [
222
+ user,
223
+ isLoading,
224
+ error
225
+ ]);
226
+ if (error) return handlePageError(error, options);
227
+ if (!user && !isLoading && (options === null || options === void 0 ? void 0 : options.onAccessDenied)) return options.onAccessDenied();
228
+ if (user) {
229
+ if ((options === null || options === void 0 ? void 0 : options.groups) && !isUserInGroup(user, options.groups, options.groupsClaim ?? process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_GROUPS_CLAIM, options.matchAll)) {
230
+ const { onAccessDenied = () => /* @__PURE__ */ React.createElement("div", null, "Access Denied") } = options;
231
+ return onAccessDenied(user);
232
+ }
233
+ return /* @__PURE__ */ React.createElement(Component, {
234
+ user,
235
+ ...props
236
+ });
237
+ }
238
+ return null;
239
+ };
240
+ };
241
+
242
+ //#endregion
243
+ export { redirectToSignIn as n, useAuth as r, protectPage as t };
244
+ //# sourceMappingURL=client-CnvBgZM-.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-CnvBgZM-.mjs","names":[],"sources":["../src/client/use-auth.tsx","../src/client/protect.tsx"],"sourcesContent":["'use client';\n\nimport type { MonoCloudUser } from '@monocloud/auth-node-core';\nimport useSWR from 'swr';\n\n/**\n * Authentication State returned by `useAuth` hook.\n */\nexport interface AuthState {\n /**\n * Flag indicating if the authentication state is still loading.\n */\n isLoading: boolean;\n /**\n * Flag indicating if the user is authenticated.\n */\n isAuthenticated: boolean;\n /**\n * Error encountered during authentication, if any.\n */\n error?: Error;\n /**\n * The authenticated user's information, if available.\n */\n user?: MonoCloudUser;\n /**\n * Function to refetch the authentication state.\n *\n */\n refetch: (refresh?: boolean) => void;\n}\n\nconst fetchUser = async (url: string): Promise<MonoCloudUser | undefined> => {\n const res = await fetch(url, { credentials: 'include' });\n\n if (res.status === 204) {\n return undefined;\n }\n\n if (res.ok) {\n return res.json();\n }\n\n throw new Error('Failed to fetch user');\n};\n\n/**\n *\n * Hook for getting the user's profile on client components\n *\n * @returns Authentication State\n *\n * @example App Router\n *\n * ```tsx\n * \"use client\";\n *\n * import { useAuth } from \"@monocloud/auth-nextjs/client\";\n *\n * export default function Home() {\n * const { user } = useAuth();\n *\n * return <>User Id: {user?.sub}</>;\n * }\n * ```\n *\n * @example App Router - Refetch user from Userinfo endpoint\n *\n * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.\n * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`\n *\n * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**\n *\n * ```tsx\n * \"use client\";\n *\n * import { useAuth } from \"@monocloud/auth-nextjs/client\";\n *\n * export default function Home() {\n * const { user, refetch } = useAuth();\n *\n * return (\n * <>\n * <pre>{JSON.stringify(user)}</pre>\n * <button onClick={() => refetch(true)}>Refresh</button>\n * </>\n * );\n * }\n * ```\n *\n * @example Pages Router\n *\n * ```tsx\n * import { useAuth } from \"@monocloud/auth-nextjs/client\";\n *\n * export default function Home() {\n * const { user } = useAuth();\n *\n * return <>User Id: {user?.sub}</>;\n * }\n * ```\n *\n * @example Pages Router - Refetch user from Userinfo endpoint\n *\n * Calling `refetch(true)` will force refresh the user's profile from the userinfo endpoint.\n * If you do not intent to refersh from your tenants userinfo endpoint, use just `refetch()`\n *\n * **Note⚠️: You need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for force refresh to work**\n *\n * ```tsx\n * import { useAuth } from \"@monocloud/auth-nextjs/client\";\n *\n * export default function Home() {\n * const { user, refetch } = useAuth();\n *\n * return (\n * <>\n * <pre>{JSON.stringify(user)}</pre>\n * <button onClick={() => refetch(true)}>Refresh</button>\n * </>\n * );\n * }\n * ```\n *\n */\nexport const useAuth = (): AuthState => {\n const key =\n process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_USER_INFO_URL ??\n // eslint-disable-next-line no-underscore-dangle\n `${process.env.__NEXT_ROUTER_BASEPATH ?? ''}/api/auth/userinfo`;\n\n const { data, error, isLoading, mutate } = useSWR<MonoCloudUser | undefined>(\n key,\n fetchUser\n );\n\n const refetch = (refresh?: boolean): void => {\n const url = new URL(key, 'https://dummy');\n if (refresh) {\n url.searchParams.set('refresh', 'true');\n }\n\n void mutate(async () => await fetchUser(url.pathname + url.search), {\n revalidate: false,\n });\n };\n\n if (error) {\n return {\n user: undefined,\n isLoading: false,\n isAuthenticated: false,\n error: error as Error,\n refetch,\n };\n }\n\n if (data) {\n return {\n user: data,\n isLoading,\n isAuthenticated: !!data && Object.keys(data).length > 0,\n error: undefined,\n refetch,\n };\n }\n\n return {\n user: undefined,\n isLoading,\n isAuthenticated: false,\n error: undefined,\n /* v8 ignore next -- @preserve */\n refetch: (): void => {},\n };\n};\n","/* eslint-disable react/display-name */\n'use client';\n\nimport React, { ComponentType, JSX, useEffect } from 'react';\nimport type { MonoCloudUser } from '@monocloud/auth-node-core';\nimport { isUserInGroup } from '@monocloud/auth-node-core/utils';\nimport { useAuth } from './use-auth';\nimport { ExtraAuthParams, GroupOptions } from '../types';\n\n/**\n * Options for configuring page protection.\n */\nexport type ProtectPageOptions = {\n /**\n *The url where the user will be redirected to after sign in\n */\n returnUrl?: string;\n\n /**\n * A custom react element to render when the user is not authenticated or is not a member of the specified groups.\n */\n onAccessDenied?: (user?: MonoCloudUser) => JSX.Element;\n\n /**\n * Authorization parameters to be used during authentication.\n */\n authParams?: ExtraAuthParams;\n\n /**\n * Callback function to handle errors.\n * If not provided, errors will be thrown.\n *\n * @param error - The error object.\n * @returns JSX element to handle the error.\n */\n onError?: (error: Error) => JSX.Element;\n} & GroupOptions;\n\nexport const redirectToSignIn = (\n options: { returnUrl?: string } & ExtraAuthParams\n): void => {\n const searchParams = new URLSearchParams(window.location.search);\n searchParams.set(\n 'return_url',\n options.returnUrl ?? window.location.toString()\n );\n\n if (options?.scopes) {\n searchParams.set('scope', options.scopes);\n }\n if (options?.resource) {\n searchParams.set('resource', options.resource);\n }\n\n if (options?.acrValues) {\n searchParams.set('acr_values', options.acrValues.join(' '));\n }\n\n if (options?.display) {\n searchParams.set('display', options.display);\n }\n\n if (options?.prompt) {\n searchParams.set('prompt', options.prompt);\n }\n\n if (options?.authenticatorHint) {\n searchParams.set('authenticator_hint', options.authenticatorHint);\n }\n\n if (options?.uiLocales) {\n searchParams.set('ui_locales', options.uiLocales);\n }\n\n if (options?.maxAge) {\n searchParams.set('max_age', options.maxAge.toString());\n }\n\n if (options?.loginHint) {\n searchParams.set('login_hint', options.loginHint);\n }\n\n window.location.assign(\n // eslint-disable-next-line no-underscore-dangle\n `${process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_SIGNIN_URL ?? `${process.env.__NEXT_ROUTER_BASEPATH ?? ''}/api/auth/signin`}?${searchParams.toString()}`\n );\n};\n\nconst handlePageError = (\n error: Error,\n options?: ProtectPageOptions\n): JSX.Element => {\n /* v8 ignore else -- @preserve */\n if (options?.onError) {\n return options.onError(error);\n }\n\n /* v8 ignore next -- @preserve */\n throw error;\n};\n\n/**\n * Function to protect a client rendered page component.\n * Ensures that only authenticated users can access the component.\n * \n * **Note⚠️: Since `window.location` is set as `returnUrl` query param by default, you need to set the env `MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES=true` or `allowQueryParamOverrides` should be `true` in the client initialization for returning to the same page.**\n *\n * @param Component - The component to protect.\n * @param options - The options.\n *\n * @returns Protected client rendered page component.\n *\n * @example App Router\n *\n * ```tsx\n * \"use client\";\n *\n * import { protectPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectPage(function Home() {\n * return <>You are signed in</>;\n * });\n * ```\n *\n * @example App Router with options\n * \n * See {@link ProtectPageOptions} for more options.\n *\n * ```tsx\n * \"use client\";\n *\n * import { protectPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectPage(\n * function Home() {\n * return <>You are signed in</>;\n * },\n * { returnUrl: \"/dashboard\", authParams: { loginHint: \"username\" } }\n * );\n * ```\n\n* @example Pages Router\n *\n * ```tsx\n * import { protectPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectPage(function Home() {\n * return <>You are signed in</>;\n * });\n * ```\n *\n * @example Pages Router with options\n * \n * See {@link ProtectPageOptions} for more options.\n *\n * ```tsx\n * import { protectPage } from \"@monocloud/auth-nextjs/client\";\n *\n * export default protectPage(\n * function Home() {\n * return <>You are signed in</>;\n * },\n * { returnUrl: \"/dashboard\", authParams: { loginHint: \"username\" } }\n * );\n * ```\n */\nexport const protectPage = <P extends object>(\n Component: ComponentType<P & { user: MonoCloudUser }>,\n options?: ProtectPageOptions\n): React.FC<P> => {\n return props => {\n const { user, error, isLoading } = useAuth();\n\n useEffect(() => {\n if (!user && !isLoading && !error) {\n if (options?.onAccessDenied) {\n return;\n }\n\n const authParams = options?.authParams ?? {};\n redirectToSignIn({\n returnUrl: options?.returnUrl,\n ...authParams,\n });\n }\n }, [user, isLoading, error]);\n\n if (error) {\n return handlePageError(error, options);\n }\n\n if (!user && !isLoading && options?.onAccessDenied) {\n return options.onAccessDenied();\n }\n\n if (user) {\n if (\n options?.groups &&\n !isUserInGroup(\n user,\n options.groups,\n options.groupsClaim ??\n process.env.NEXT_PUBLIC_MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n const { onAccessDenied = (): JSX.Element => <div>Access Denied</div> } =\n options;\n return onAccessDenied(user);\n }\n\n return <Component user={user} {...props} />;\n }\n\n return null;\n };\n};\n"],"mappings":"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"}