Skip to content

fix(clerk-js,types): Use intent parameter to reload resource #5553

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/tidy-dolls-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@clerk/clerk-js': patch
'@clerk/types': patch
---

Optionally handle the `intent` parameter on SSO redirects to reload specific resources.
15 changes: 7 additions & 8 deletions packages/clerk-js/src/core/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1528,16 +1528,15 @@ export class Clerk implements ClerkInterface {
// directs the opening page to navigate to the /sso-callback route), we need to reload the signIn and signUp resources
// to ensure that we have the latest state. This operation can fail when we try reloading a resource that doesn't
// exist (such as when reloading a signIn resource during a signUp attempt), but this can be safely ignored.
if (!window.opener) {
if (!window.opener && params.reloadResource) {
try {
await signIn.reload();
} catch {
// This can be safely ignored
}
try {
await signUp.reload();
if (params.reloadResource === 'signIn') {
await signIn.reload();
} else if (params.reloadResource === 'signUp') {
await signUp.reload();
}
} catch {
// This can be safely ignored
// This catch intentionally left blank.
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/clerk-js/src/core/resources/SignIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ export class SignIn extends BaseResource implements SignInResource {
if (!popup) {
clerkMissingOptionError('popup');
}
return _authenticateWithPopup(SignIn.clerk, this.authenticateWithRedirectOrPopup, params, url => {
return _authenticateWithPopup(SignIn.clerk, 'signIn', this.authenticateWithRedirectOrPopup, params, url => {
popup.location.href = url.toString();
});
};
Expand Down
2 changes: 1 addition & 1 deletion packages/clerk-js/src/core/resources/SignUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ export class SignUp extends BaseResource implements SignUpResource {
clerkMissingOptionError('popup');
}

return _authenticateWithPopup(SignUp.clerk, this.authenticateWithRedirectOrPopup, params, url => {
return _authenticateWithPopup(SignUp.clerk, 'signUp', this.authenticateWithRedirectOrPopup, params, url => {
popup.location.href = url instanceof URL ? url.toString() : url;
});
};
Expand Down
4 changes: 3 additions & 1 deletion packages/clerk-js/src/ui/common/SSOCallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export const SSOCallbackCard = (props: HandleOAuthCallbackParams | HandleSamlCal
React.useEffect(() => {
let timeoutId: ReturnType<typeof setTimeout>;
if (__internal_setActiveInProgress !== true) {
handleRedirectCallback({ ...props }, navigate).catch(e => {
const intent = new URLSearchParams(window.location.search).get('intent');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we maybe use the params from the router instead ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the hash and virtual routers, the queryString isn't derived from window.location.search, which is where the intent param is going to be. For example, this is the SSO callback route when using the hash router:

http://localhost:4000/sign-in?intent=sign-in#/sso-callback

In this example, window.location.search is ?intent=sign-in, but the value of queryString from useRotuer is "".

Alternatively, we could append the intent parameter to different locations based on the router used, but I felt that was a little too much additional complexity in exchange for basically no additional functionality.

const reloadResource = intent === 'signIn' || intent === 'signUp' ? intent : undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do this ? Or is reloadResource:false not proper ?

Suggested change
const reloadResource = intent === 'signIn' || intent === 'signUp' ? intent : undefined;
const reloadResource = ['signIn', 'signUp'].includes(intent)

Copy link
Member Author

@dstaley dstaley Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript won't narrow from string to 'signIn' | 'signUp' if we use Array.includes, and we still need to make sure we know which resource needs to be reloaded, so a boolean value won't work.

handleRedirectCallback({ ...props, reloadResource }, navigate).catch(e => {
handleError(e, [], card.setError);
timeoutId = setTimeout(() => void navigate('../'), 4000);
});
Expand Down
2 changes: 2 additions & 0 deletions packages/clerk-js/src/utils/authenticateWithPopup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Clerk } from '../core/clerk';

export async function _authenticateWithPopup(
client: Clerk,
reloadResource: 'signIn' | 'signUp',
authenticateMethod: (
params: AuthenticateWithRedirectParams,
navigateCallback: (url: URL | string) => void,
Expand All @@ -27,6 +28,7 @@ export async function _authenticateWithPopup(
const r = new URL(redirectUrl);
r.searchParams.set('sign_in_force_redirect_url', params.redirectUrlComplete);
r.searchParams.set('sign_up_force_redirect_url', params.redirectUrlComplete);
r.searchParams.set('intent', reloadResource);
// All URLs are decorated with the dev browser token in development mode since we're moving between AP and the app.
const redirectUrlWithForceRedirectUrl = client.buildUrlWithAuth(r.toString());

Expand Down
4 changes: 4 additions & 0 deletions packages/types/src/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,10 @@ export type HandleOAuthCallbackParams = TransferableOption &
* Full URL or path to navigate to after requesting phone verification.
*/
verifyPhoneNumberUrl?: string | null;
/**
* The underlying resource to optionally reload before processing an OAuth callback.
*/
reloadResource?: 'signIn' | 'signUp';
};

export type HandleSamlCallbackParams = HandleOAuthCallbackParams;
Expand Down