Dispatch customOAuthState before signInWithRedirect_failure on OAuth error redirects
Is this related to a new or existing framework?
Next.js
Is this related to a new or existing API?
Authentication
Is this related to another service?
Amazon Cognito (Hosted UI / OAuth)
Describe the feature you'd like to request
When signInWithRedirect fails during the OAuth callback (e.g. Cognito redirects back with ?error=...&error_description=...&state=..., such as when a PreSignUp Lambda trigger throws to block the sign-in), the customOAuthState Hub event is never dispatched — only signInWithRedirect_failure fires.
This means any customState passed to signInWithRedirect({ customState: ... }) is lost on failure, even though the state query parameter (which encodes the custom state) is still present in the callback URL in the error case.
const error = urlParams.searchParams.get('error');
const errorMessage = urlParams.searchParams.get('error_description');
if (error) {
throw createOAuthError(errorMessage ?? error);
}The function throws immediately and never reaches completeFlow, which is where customOAuthState is dispatched (derived from the state param) right before the signInWithRedirect success event:
if (isCustomState(state)) {
Hub.dispatch(
'auth',
{
event: 'customOAuthState',
data: urlSafeDecode(getCustomState(state)),
},
'Auth',
AMPLIFY_SYMBOL,
);
}
Hub.dispatch('auth', { event: 'signInWithRedirect' }, 'Auth', AMPLIFY_SYMBOL);We'd like to know if it's possible (or intentionally avoided) to dispatch customOAuthState from the error branch too, using the state param that's already on the error redirect URL — before dispatching signInWithRedirect_failure.
Describe the solution you'd like
In the error branch of completeOAuthFlow, read the state query param and dispatch customOAuthState (reusing the existing isCustomState/getCustomState helpers) before throwing, so that signInWithRedirect_failure listeners can still recover the custom state that was passed to signInWithRedirect:
if (error) {
const state = urlParams.searchParams.get('state');
if (state && isCustomState(state)) {
Hub.dispatch(
'auth',
{ event: 'customOAuthState', data: urlSafeDecode(getCustomState(state)) },
'Auth',
AMPLIFY_SYMBOL,
);
}
throw createOAuthError(errorMessage ?? error);
}We understand the error path deliberately skips validateState (there's no token exchange to validate against), so we wanted to flag explicitly that this reads customState from an unvalidated state param. From what we can tell, customState is treated by Amplify as an opaque, app-defined string with no security-sensitive use internally, so recovering it without validation seems low-risk — but we wanted to raise it in case there's a reason it's currently skipped that we're missing.
Describe alternatives you've considered
We currently work around this by stashing the value in sessionStorage before calling signInWithRedirect, and reading it back (with sessionStorage.removeItem) in our signInWithRedirect_failure handler. This works, but means we can't rely on the Hub event system alone for this — we wanted to check if there's a more idiomatic way we're missing, or if this workaround is the recommended approach.
Additional context
Use case: we pass a returnTo path (e.g. an invitation link the user arrived from) as customState so we can send the user back to where they started after signing in with Google:
await signInWithRedirect({ provider: "Google", customState: returnTo });On success we read it back via customOAuthState and redirect accordingly. On failure (e.g. an existing native/email user mistakenly tries Google sign-in and our PreSignUp Lambda trigger blocks it with a friendly error message directing them back to email/password login), we'd like to redirect back to our login page with the same returnTo preserved so the original flow (e.g. accepting an invitation) isn't lost — but currently have no way to do this via the Hub event system.
Is this something that you'd be interested in working on?
- I may be able to implement this feature request
- ⚠️ This feature might incur a breaking change
Source: aws-amplify/amplify-js