Skip to content
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
14 changes: 14 additions & 0 deletions .changeset/signin-signup-followups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'@asgardeo/react': patch
'@asgardeo/nextjs': patch
'@asgardeo/i18n': patch
---

Fixes for the embedded `<SignIn />` and `<SignUp />` components:

- Social login buttons in the sign-in, sign-up and recovery flows no longer receive internal form-state props (`formValues`, `formErrors`, `touchedFields`, `isFormValid`, `onInputChange`, `inputClassName`), which React reported as unknown attributes on the `<button>` element.
- When the identity server rejects the embedded sign-in because the redirect URI (`afterSignInUrl`) is not registered for the application, the form shows a translated, actionable message naming the URL to register (`errors.signin.redirect.uri.mismatch`) instead of the raw `invalid_callback - callback.not.match` text. The Next.js README documents the redirect URL requirements.
- When the automatic sign-in after an embedded registration cannot be performed, the reason is reported in the browser console as well as the server log.
- `<SignUp />` renders `RICH_TEXT` flow components (for example the terms of service text), which were previously dropped, leaving the submit button jammed against the last field.
- The Next.js `<SignUp />` forwards all remaining props to the underlying form (`showTitle`, `showSubtitle`, `showLogo`, `onComplete`, `onFlowChange`, class names, ...), so for instance `showTitle={false}` now works when a registration flow renders its own heading.
- After a server-side validation error (for example a rejected password), `<SignUp />` now keeps the values the user entered and the submit button stays enabled, so the user can correct the field and resubmit. Previously the form's validation errors were recorded under keys no input could clear, which left the button disabled permanently. Form validation also runs against the value being typed instead of the previous one.
1 change: 1 addition & 0 deletions packages/i18n/src/models/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export interface I18nTranslations {

'errors.heading': string;
'errors.signin.initialization': string;
'errors.signin.redirect.uri.mismatch': string;
'errors.signin.flow.failure': string;
'errors.signin.flow.completion.failure': string;
'errors.signin.flow.passkeys.failure': string;
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/translations/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ const translations: I18nTranslations = {
'errors.heading': 'Error',
'errors.signin.components.not.available': 'Sign-in form is not available at the moment. Please try again later.',
'errors.signin.initialization': 'An error occurred while initializing. Please try again later.',
'errors.signin.redirect.uri.mismatch':
'The redirect URI "{url}" is not registered for this application. Add it to the application\'s authorized redirect URLs in the console, and to your social login provider if you use app-native social sign-in.',
'errors.signin.flow.failure': 'An error occurred during the sign-in flow. Please try again later.',
'errors.signin.flow.completion.failure':
'An error occurred while completing the sign-in flow. Please try again later.',
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/translations/fr-FR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ const translations: I18nTranslations = {

'errors.heading': 'Erreur',
'errors.signin.initialization': "Une erreur est survenue lors de l'initialisation. Veuillez réessayer plus tard.",
'errors.signin.redirect.uri.mismatch':
"L'URI de redirection \"{url}\" n'est pas enregistrée pour cette application. Ajoutez-la aux URL de redirection autorisées de l'application dans la console, ainsi qu'à votre fournisseur de connexion sociale si vous utilisez la connexion sociale native.",
'errors.signin.flow.failure': 'Une erreur est survenue lors du flux de connexion. Veuillez réessayer plus tard.',
'errors.signin.flow.completion.failure':
'Une erreur est survenue lors de la finalisation du flux de connexion. Veuillez réessayer plus tard.',
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/translations/hi-IN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ const translations: I18nTranslations = {

'errors.heading': 'त्रुटि',
'errors.signin.initialization': 'इनिशियलाइज़ेशन में त्रुटि हुई। कृपया बाद में पुनः प्रयास करें।',
'errors.signin.redirect.uri.mismatch':
'रीडायरेक्ट URI "{url}" इस एप्लिकेशन के लिए पंजीकृत नहीं है। इसे कंसोल में एप्लिकेशन के अधिकृत रीडायरेक्ट URL में जोड़ें, और यदि आप ऐप-नेटिव सोशल साइन-इन का उपयोग करते हैं तो अपने सोशल लॉगिन प्रदाता में भी जोड़ें।',
'errors.signin.flow.failure': 'साइन-इन प्रक्रिया में त्रुटि। कृपया बाद में पुनः प्रयास करें।',
'errors.signin.flow.completion.failure': 'साइन-इन प्रक्रिया पूरी करते समय त्रुटि। कृपया बाद में पुनः प्रयास करें।',
'errors.signin.flow.passkeys.failure': 'पासकीज़ के साथ साइन-इन करते समय त्रुटि।',
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/translations/ja-JP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ const translations: I18nTranslations = {

'errors.heading': 'エラー',
'errors.signin.initialization': '初期化中にエラーが発生しました。後でもう一度お試しください。',
'errors.signin.redirect.uri.mismatch':
'リダイレクト URI「{url}」はこのアプリケーションに登録されていません。コンソールでアプリケーションの承認済みリダイレクト URL に追加してください。アプリネイティブのソーシャルサインインを使用する場合は、ソーシャルログインプロバイダーにも追加してください。',
'errors.signin.flow.failure': 'サインイン処理中にエラーが発生しました。後でもう一度お試しください。',
'errors.signin.flow.completion.failure': 'サインイン処理の完了中にエラーが発生しました。後でもう一度お試しください。',
'errors.signin.flow.passkeys.failure': 'パスキーでのサインイン中にエラーが発生しました。後でもう一度お試しください。',
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/translations/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ const translations: I18nTranslations = {

'errors.heading': 'Erro',
'errors.signin.initialization': 'Ocorreu um erro ao inicializar. Tente novamente mais tarde.',
'errors.signin.redirect.uri.mismatch':
'O URI de redirecionamento "{url}" não está registrado para este aplicativo. Adicione-o às URLs de redirecionamento autorizadas do aplicativo no console e, se usar login social nativo, também ao seu provedor de login social.',
'errors.signin.flow.failure': 'Ocorreu um erro durante o login. Tente novamente mais tarde.',
'errors.signin.flow.completion.failure': 'Ocorreu um erro ao completar o login. Tente novamente mais tarde.',
'errors.signin.flow.passkeys.failure':
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/translations/pt-PT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ const translations: I18nTranslations = {

'errors.heading': 'Erro',
'errors.signin.initialization': 'Ocorreu um erro ao inicializar. Tente novamente mais tarde.',
'errors.signin.redirect.uri.mismatch':
'O URI de redirecionamento "{url}" não está registado para esta aplicação. Adicione-o aos URLs de redirecionamento autorizados da aplicação na consola e, se utilizar início de sessão social nativo, também ao seu fornecedor de início de sessão social.',
'errors.signin.flow.failure': 'Ocorreu um erro durante o início de sessão. Tente novamente mais tarde.',
'errors.signin.flow.completion.failure':
'Ocorreu um erro ao completar o início de sessão. Tente novamente mais tarde.',
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/translations/si-LK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ const translations: I18nTranslations = {

'errors.heading': 'දෝෂය',
'errors.signin.initialization': 'ආරම්භ කිරීමේදී දෝෂයක් සිදු විය. කරුණාකර පසුව නැවත උත්සාහ කරන්න.',
'errors.signin.redirect.uri.mismatch':
'යළි-යොමු URI "{url}" මෙම යෙදුම සඳහා ලියාපදිංචි කර නොමැත. එය කොන්සෝලයේ යෙදුමේ අනුමත යළි-යොමු URL වලට එක් කරන්න, සහ ඔබ යෙදුම්-ස්වදේශීය සමාජ පිවිසුම භාවිතා කරන්නේ නම් ඔබගේ සමාජ පිවිසුම් සපයන්නාටද එක් කරන්න.',
'errors.signin.flow.failure': 'ලොග් වීමේදී දෝෂයක් සිදු විය. කරුණාකර පසුව නැවත උත්සාහ කරන්න.',
'errors.signin.flow.completion.failure':
'ලොග් වීමේ ක්‍රියාවලිය සම්පූර්ණ කිරීමේදී දෝෂයක් සිදු විය. කරුණාකර පසුව නැවත උත්සාහ කරන්න.',
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/translations/ta-IN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ const translations: I18nTranslations = {

'errors.heading': 'பிழை',
'errors.signin.initialization': 'தொடக்கத்தில் பிழை ஏற்பட்டது. பின்னர் மீண்டும் முயற்சிக்கவும்.',
'errors.signin.redirect.uri.mismatch':
'திருப்பிவிடும் URI "{url}" இந்த பயன்பாட்டிற்கு பதிவு செய்யப்படவில்லை. இதை கன்சோலில் பயன்பாட்டின் அங்கீகரிக்கப்பட்ட திருப்பிவிடும் URL களில் சேர்க்கவும்; பயன்பாட்டு-சொந்த சமூக உள்நுழைவைப் பயன்படுத்தினால் உங்கள் சமூக உள்நுழைவு வழங்குநரிலும் சேர்க்கவும்.',
'errors.signin.flow.failure': 'உள்நுழைவு செயல்பாட்டின் போது பிழை ஏற்பட்டது. பின்னர் மீண்டும் முயற்சிக்கவும்.',
'errors.signin.flow.completion.failure':
'உள்நுழைவு செயல்பாட்டை முடிக்கும் போது பிழை ஏற்பட்டது. பின்னர் மீண்டும் முயற்சிக்கவும்.',
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/translations/te-IN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ const translations: I18nTranslations = {

'errors.heading': 'లోపం',
'errors.signin.initialization': 'ప్రారంభించేటప్పుడు లోపం వచ్చింది. దయచేసి తరువాత మళ్లీ ప్రయత్నించండి.',
'errors.signin.redirect.uri.mismatch':
'రీడైరెక్ట్ URI "{url}" ఈ అప్లికేషన్ కోసం నమోదు కాలేదు. దీన్ని కన్సోల్‌లో అప్లికేషన్ యొక్క అధీకృత రీడైరెక్ట్ URLలకు జోడించండి; మీరు యాప్-నేటివ్ సోషల్ సైన్-ఇన్ ఉపయోగిస్తే మీ సోషల్ లాగిన్ ప్రొవైడర్‌కు కూడా జోడించండి.',
'errors.signin.flow.failure': 'సైన్ ఇన్ ప్రక్రియలో లోపం వచ్చింది. దయచేసి తరువాత మళ్లీ ప్రయత్నించండి.',
'errors.signin.flow.completion.failure': 'సైన్ ఇన్ పూర్తి చేయడంలో లోపం వచ్చింది. దయచేసి తరువాత మళ్లీ ప్రయత్నించండి.',
'errors.signin.flow.passkeys.failure': 'పాస్‌కీలతో సైన్ ఇన్ చేస్తూ లోపం వచ్చింది. దయచేసి తరువాత మళ్లీ ప్రయత్నించండి.',
Expand Down
20 changes: 20 additions & 0 deletions packages/nextjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@

Get started with Asgardeo in your Next.js application in minutes. Follow our [Next.js Quick Start Guide](https://wso2.com/asgardeo/docs/quick-starts/nextjs/) for step-by-step instructions on integrating authentication into your app.

## Redirect URLs

The SDK sends `afterSignInUrl` (`NEXT_PUBLIC_ASGARDEO_AFTER_SIGN_IN_URL`, or the `afterSignInUrl` prop of
`<AsgardeoProvider>`) to the identity server as the OAuth `redirect_uri`. A relative value such as `/dashboard` is
resolved against your app's origin. Register the resolved URL, for example `http://localhost:3000/dashboard` and its
production equivalent, under the application's **Authorized redirect URLs** in the console; the bare origin is not
enough. If it is missing, the embedded `<SignIn />` fails to initialise and shows the exact URL to register.

Social login with app-native authentication needs two more redirect URIs on the social provider's OAuth client (for
Google: the OAuth client's **Authorized redirect URIs**), because the identity server sends different callbacks for
the two flows:

- sign-in: the same resolved `afterSignInUrl`, e.g. `http://localhost:3000/dashboard`
- sign-up (self registration): the identity server's registration callback,
Comment thread
DonOmalVindula marked this conversation as resolved.
`https://accounts.asgardeo.io/t/<organization>/accounts/register`

A missing entry surfaces as Google's `Error 400: redirect_uri_mismatch`.

`afterSignOutUrl` (default: the app origin) is sent as the post-logout redirect URI and must be registered as well.

## API Documentation

For complete API documentation including all components, hooks, and customization options, see the [Next.js SDK Documentation](https://wso2.com/asgardeo/docs/sdks/nextjs/overview).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const SignUp: FC<SignUpProps> = ({
variant = 'outlined',
afterSignUpUrl,
onError,
...rest
}: SignUpProps) => {
const {signUp} = useAsgardeo();

Expand Down Expand Up @@ -110,6 +111,7 @@ const SignUp: FC<SignUpProps> = ({

return (
<BaseSignUp
{...rest}
afterSignUpUrl={afterSignUpUrl}
onInitialize={handleInitialize}
onSubmit={handleOnSubmit}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,14 +258,20 @@ const AsgardeoClientProvider: FC<PropsWithChildren<AsgardeoClientProviderProps>>

// After the Embedded flow is successful, the URL to navigate next is sent as `afterSignUpUrl` in the response.
if (result?.data?.afterSignUpUrl) {
const {afterSignUpUrl, signedIn, ...flowResponse}: any = result.data;
const {afterSignUpUrl, autoSignInSkippedReason, signedIn, ...flowResponse}: any = result.data;

// A URL passed by the caller (e.g. the `afterSignUpUrl` prop of `<SignUp />`) wins over the configured one.
router.push(options?.afterSignUpUrl || afterSignUpUrl);

if (signedIn) {
// A session cookie was set during sign-up; re-render server components so the signed-in state is picked up.
router.refresh();
} else if (autoSignInSkippedReason) {
// Make the fallback visible where developers look first, not only in the server log.
logger.warn(
`[AsgardeoClientProvider] The user was registered but not signed in automatically: ${autoSignInSkippedReason} ` +
'They will have to sign in manually.',
);
}

// Hand the completed flow back to the caller (e.g. `<SignUp />`) so it can finish its lifecycle
Expand Down
26 changes: 22 additions & 4 deletions packages/nextjs/src/server/actions/signUpAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@

import {EmbeddedFlowExecuteRequestPayload, EmbeddedFlowExecuteResponse, EmbeddedFlowStatus} from '@asgardeo/node';
import AsgardeoNextClient from '../../AsgardeoNextClient';
import autoSignInAfterSignUp, {extractSignUpCredentials, SignUpCredentials} from '../../utils/autoSignInAfterSignUp';
import autoSignInAfterSignUp, {
AutoSignInResult,
extractSignUpCredentials,
SignUpCredentials,
} from '../../utils/autoSignInAfterSignUp';

/**
* Server action for signing in a user.
Expand All @@ -38,7 +42,7 @@ const signUpAction = async (
afterSignUpUrl?: string;
signUpUrl?: string;
}
| (EmbeddedFlowExecuteResponse & {afterSignUpUrl?: string; signedIn?: boolean});
| (EmbeddedFlowExecuteResponse & {afterSignUpUrl?: string; autoSignInSkippedReason?: string; signedIn?: boolean});
error?: string;
success: boolean;
}> => {
Expand All @@ -65,11 +69,25 @@ const signUpAction = async (
// When that is not possible (MFA, app-native auth disabled, multi-step registration), they are
// sent to `afterSignUpUrl` without a session and can sign in manually.
const credentials: SignUpCredentials | undefined = extractSignUpCredentials(payload.inputs);
const signedIn: boolean = credentials ? await autoSignInAfterSignUp(credentials) : false;
const autoSignIn: AutoSignInResult = credentials
? await autoSignInAfterSignUp(credentials)
: {
reason:
'The final registration step did not include a username and password (e.g. a multi-step registration flow).',
signedIn: false,
};

// Return the completed flow response along with the URL so that client components
// (e.g. `<SignUp />`) can finish their own lifecycle instead of receiving nothing.
return {data: {...response, afterSignUpUrl: String(afterSignUpUrl), signedIn}, success: true};
return {
data: {
...response,
afterSignUpUrl: String(afterSignUpUrl),
autoSignInSkippedReason: autoSignIn.reason,
signedIn: autoSignIn.signedIn,
},
success: true,
};
}

return {data: response as EmbeddedFlowExecuteResponse, success: true};
Expand Down
Loading
Loading