Skip to content

Commit 0c79235

Browse files
Merge pull request #6 from emdgroup/feat/login-url
feat: generate loginUrl for manual redirects
2 parents 2c4919a + 056ac9f commit 0c79235

1 file changed

Lines changed: 23 additions & 14 deletions

File tree

packages/auth/src/index.tsx

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function isString(arg: unknown): arg is string {
103103
export interface LoginOptions {
104104
/** Entrypoint to redirect the user to after successful authentication. Defaults to the URL that the user initially visited. */
105105
entrypoint?: string;
106-
/** Perform redirect after successful authentication, default to `true`. */
106+
/** Automatically redirect the user to the login URL and to the entrypoint after successful authentication. Disabling this will disable all redirects. Defaults to `false`. */
107107
redirect?: boolean;
108108
}
109109

@@ -140,6 +140,8 @@ export interface UserContext {
140140
logout?: () => void;
141141
/** Convenience header object containing the `Authorization` header value set to the access token. */
142142
authHeader?: { [key: string]: string };
143+
/** Set to the URL that the user is redirected to initiate the authorization flow. Useful when you need to start the login flow in a separate window or tab. Use in combination with `login({ refresh: false })`. */
144+
loginUrl?: string;
143145
}
144146

145147
export const UserContext = createContext<UserContext>({});
@@ -207,6 +209,7 @@ export function UserContextProvider({
207209

208210
const [userInfo, setUserInfo] = useState<UserInfo>();
209211

212+
const [loginUrl, setLoginUrl] = useState<string>();
210213
const login = useCallback(async (
211214
{ entrypoint, redirect = true }: LoginOptions = {}
212215
): Promise<void> => {
@@ -219,18 +222,21 @@ export function UserContextProvider({
219222
}
220223
const challenge = base64encode(await sha256(encodedKey));
221224

222-
document.location.href =
223-
`https://${idpHost}/oauth2/authorize?` +
224-
querystring.stringify({
225-
client_id: clientId,
226-
domain_hint: domainHint,
227-
response_type: 'code',
228-
scope: 'openid email',
229-
redirect_uri: redirectUri || `${document.location.origin}/auth`,
230-
code_challenge_method: 'S256',
231-
code_challenge: challenge,
232-
prompt,
233-
});
225+
const url = `https://${idpHost}/oauth2/authorize?` +
226+
querystring.stringify({
227+
client_id: clientId,
228+
domain_hint: domainHint,
229+
response_type: 'code',
230+
scope: 'openid email',
231+
redirect_uri: redirectUri || `${document.location.origin}/auth`,
232+
code_challenge_method: 'S256',
233+
code_challenge: challenge,
234+
prompt,
235+
});
236+
237+
setLoginUrl(url);
238+
239+
if (redirect) document.location.href = url;
234240
}, [setKey, idpHost, clientId, domainHint, redirectUri, setEntrypoint, prompt]);
235241

236242
const logout = useCallback((): void => {
@@ -294,6 +300,7 @@ export function UserContextProvider({
294300
useEffect(() => {
295301
if (!session && tokenStatus === 'success' && isTokenResponse(tokenResponse)) {
296302
clearKey();
303+
setLoginUrl(undefined);
297304
updateSession({
298305
accessToken: tokenResponse.access_token,
299306
refreshToken: refreshSessionOpt ? tokenResponse.refresh_token : undefined,
@@ -309,6 +316,7 @@ export function UserContextProvider({
309316
session,
310317
clearEntrypoint,
311318
clearKey,
319+
setLoginUrl,
312320
tokenStatus,
313321
tokenResponse,
314322
entrypoint,
@@ -364,8 +372,9 @@ export function UserContextProvider({
364372
login,
365373
logout,
366374
authHeader,
375+
loginUrl,
367376
};
368-
}, [session, userInfo, login, logout, authHeader])}
377+
}, [session, userInfo, login, logout, authHeader, loginUrl])}
369378
>{!autoLogin || userInfo ? children : null}</UserContext.Provider>
370379
);
371380
}

0 commit comments

Comments
 (0)