Skip to content

Commit e3b2e03

Browse files
committed
feat: integrate user retrieval and authentication state management; add getUserAction and isSignedIn actions; refactor AsgardeoNextClient and AsgardeoProvider components
1 parent f5739d1 commit e3b2e03

File tree

5 files changed

+58
-41
lines changed

5 files changed

+58
-41
lines changed

packages/nextjs/src/AsgardeoNextClient.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
generateUserProfile,
3737
flattenUserSchema,
3838
getScim2Me,
39+
getSchemas,
3940
} from '@asgardeo/node';
4041
import {NextRequest, NextResponse} from 'next/server';
4142
import {AsgardeoNextConfig} from './models/config';
@@ -131,8 +132,19 @@ class AsgardeoNextClient<T extends AsgardeoNextConfig = AsgardeoNextConfig> exte
131132
const configData = await this.asgardeo.getConfigData();
132133
const baseUrl = configData?.baseUrl;
133134

134-
const profile = await getScim2Me({baseUrl});
135-
const schemas = await getSchemas({url: `${baseUrl}/scim2/Schemas`});
135+
const profile = await getScim2Me({
136+
baseUrl,
137+
headers: {
138+
Authorization: `Bearer ${await this.getAccessToken(userId)}`,
139+
},
140+
});
141+
142+
const schemas = await getSchemas({
143+
baseUrl,
144+
headers: {
145+
Authorization: `Bearer ${await this.getAccessToken(userId)}`,
146+
},
147+
});
136148

137149
return generateUserProfile(profile, flattenUserSchema(schemas));
138150
} catch (error) {
@@ -164,6 +176,10 @@ class AsgardeoNextClient<T extends AsgardeoNextConfig = AsgardeoNextConfig> exte
164176
return this.asgardeo.isSignedIn(sessionId as string);
165177
}
166178

179+
getAccessToken(sessionId?: string): Promise<string> {
180+
return this.asgardeo.getAccessToken(sessionId as string);
181+
}
182+
167183
override getConfiguration(): T {
168184
return this.asgardeo.getConfigData() as unknown as T;
169185
}

packages/nextjs/src/client/contexts/Asgardeo/AsgardeoProvider.tsx

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import {I18nProvider, FlowProvider, UserProvider, ThemeProvider, AsgardeoProvide
2323
import {FC, PropsWithChildren, useEffect, useMemo, useState} from 'react';
2424
import {useRouter} from 'next/navigation';
2525
import AsgardeoContext, {AsgardeoContextProps} from './AsgardeoContext';
26-
import {getUserAction} from '../../../server/actions/authActions';
2726

2827
/**
2928
* Props interface of {@link AsgardeoClientProvider}
@@ -33,6 +32,7 @@ export type AsgardeoClientProviderProps = Partial<Omit<AsgardeoProviderProps, 'b
3332
signOut: AsgardeoContextProps['signOut'];
3433
signIn: AsgardeoContextProps['signIn'];
3534
isSignedIn: boolean;
35+
user: User | null;
3636
};
3737

3838
const AsgardeoClientProvider: FC<PropsWithChildren<AsgardeoClientProviderProps>> = ({
@@ -42,10 +42,10 @@ const AsgardeoClientProvider: FC<PropsWithChildren<AsgardeoClientProviderProps>>
4242
preferences,
4343
isSignedIn,
4444
signInUrl,
45+
user
4546
}: PropsWithChildren<AsgardeoClientProviderProps>) => {
4647
const router = useRouter();
4748
const [isDarkMode, setIsDarkMode] = useState(false);
48-
const [user, setUser] = useState<User | null>(null);
4949
const [isLoading, setIsLoading] = useState(true);
5050

5151
useEffect(() => {
@@ -57,30 +57,9 @@ const AsgardeoClientProvider: FC<PropsWithChildren<AsgardeoClientProviderProps>>
5757
}, [preferences?.theme?.mode]);
5858

5959
useEffect(() => {
60-
if (!isSignedIn) {
61-
return;
62-
}
63-
64-
(async () => {
65-
try {
66-
setIsLoading(true);
67-
68-
if (isSignedIn) {
69-
console.log('[AsgardeoClientProvider] Fetching user data...');
70-
const userResult = await getUserAction();
71-
72-
console.log('[AsgardeoClientProvider] User fetched:', userResult);
73-
setUser(userResult?.data?.user);
74-
} else {
75-
setUser(null);
76-
}
77-
} catch (error) {
78-
setUser(null);
79-
} finally {
80-
setIsLoading(false);
81-
}
82-
})();
83-
}, [isSignedIn]);
60+
// Set loading to false when server has resolved authentication state
61+
setIsLoading(false);
62+
}, [isSignedIn, user]);
8463

8564
const handleSignIn = async (
8665
payload: EmbeddedSignInFlowHandleRequestPayload,
@@ -96,6 +75,13 @@ const AsgardeoClientProvider: FC<PropsWithChildren<AsgardeoClientProviderProps>>
9675
return;
9776
}
9877

78+
// After the Embedded flow is successful, the URL to navigate next is sent as `afterSignInUrl` in the response.
79+
if (result?.data?.afterSignInUrl) {
80+
router.push(result.data.afterSignInUrl);
81+
82+
return;
83+
}
84+
9985
if (result?.error) {
10086
throw new Error(result.error);
10187
}
@@ -134,7 +120,7 @@ const AsgardeoClientProvider: FC<PropsWithChildren<AsgardeoClientProviderProps>>
134120
signOut: handleSignOut,
135121
signInUrl,
136122
}),
137-
[user, isSignedIn, isLoading],
123+
[user, isSignedIn, isLoading, signInUrl],
138124
);
139125

140126
return (

packages/nextjs/src/server/AsgardeoProvider.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
*/
1818

1919
import {FC, PropsWithChildren, ReactElement} from 'react';
20-
import {AsgardeoRuntimeError} from '@asgardeo/node';
20+
import {AsgardeoRuntimeError, User} from '@asgardeo/node';
2121
import AsgardeoClientProvider, {AsgardeoClientProviderProps} from '../client/contexts/Asgardeo/AsgardeoProvider';
2222
import AsgardeoNextClient from '../AsgardeoNextClient';
2323
import signInAction from './actions/signInAction';
2424
import signOutAction from './actions/signOutAction';
2525
import {AsgardeoNextConfig} from '../models/config';
2626
import isSignedIn from './actions/isSignedIn';
27+
import getUserAction from './actions/getUserAction';
28+
import getSessionId from './actions/getSessionId';
2729

2830
/**
2931
* Props interface of {@link AsgardeoServerProvider}
@@ -74,6 +76,15 @@ const AsgardeoServerProvider: FC<PropsWithChildren<AsgardeoServerProviderProps>>
7476
return <></>;
7577
}
7678

79+
const _isSignedIn: boolean = await isSignedIn();
80+
let user: User = {};
81+
82+
if (_isSignedIn) {
83+
const response = await getUserAction((await getSessionId()) as string);
84+
85+
user = response.data?.user || {};
86+
}
87+
7788
return (
7889
<AsgardeoClientProvider
7990
baseUrl={config.baseUrl}
@@ -82,7 +93,8 @@ const AsgardeoServerProvider: FC<PropsWithChildren<AsgardeoServerProviderProps>>
8293
signInUrl={configuration?.signInUrl}
8394
preferences={config.preferences}
8495
clientId={config.clientId}
85-
isSignedIn={await isSignedIn()}
96+
user={user}
97+
isSignedIn={_isSignedIn}
8698
>
8799
{children}
88100
</AsgardeoClientProvider>

packages/nextjs/src/server/actions/authActions.ts renamed to packages/nextjs/src/server/actions/getUserAction.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ import deleteSessionId from './deleteSessionId';
3535
* Server action to get the current user.
3636
* Returns the user profile if signed in.
3737
*/
38-
export async function getUserAction() {
38+
const getUserAction = async (sessionId: string) => {
3939
try {
4040
const client = AsgardeoNextClient.getInstance();
41-
const user = await client.getUser();
42-
return {data: {user}, error: null};
41+
const user = await client.getUser(sessionId);
42+
return {success: true, data: {user}, error: null};
4343
} catch (error) {
44-
return {data: {user: null}, error: 'Failed to get user'};
44+
return {success: false, data: {user: null}, error: 'Failed to get user'};
4545
}
46-
}
46+
};
47+
48+
export default getUserAction;

packages/nextjs/src/server/actions/isSignedIn.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818

1919
'use server';
2020

21-
import {CookieConfig} from '@asgardeo/node';
22-
import {ReadonlyRequestCookies} from 'next/dist/server/web/spec-extension/adapters/request-cookies';
23-
import {cookies} from 'next/headers';
21+
import AsgardeoNextClient from '../../AsgardeoNextClient';
22+
import getSessionId from './getSessionId';
2423

2524
const isSignedIn = async (): Promise<boolean> => {
26-
const cookieStore: ReadonlyRequestCookies = await cookies();
25+
const sessionId: string | undefined = await getSessionId();
26+
const client = AsgardeoNextClient.getInstance();
27+
const accessToken: string | undefined = await client.getAccessToken(sessionId);
2728

28-
return !!cookieStore.get(CookieConfig.SESSION_COOKIE_NAME)?.value;
29+
return !!accessToken;
2930
};
3031

3132
export default isSignedIn;

0 commit comments

Comments
 (0)