hazo_auth 5.1.34 → 5.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -251,7 +251,7 @@ export default function Page() {
251
251
  | Page | Import | Description |
252
252
  |------|--------|-------------|
253
253
  | **LoginPage** | `hazo_auth/pages/login` | Login form with forgot password link |
254
- | **RegisterPage** | `hazo_auth/pages/register` | Registration with password validation |
254
+ | **RegisterPage** | `hazo_auth/pages/register` | Registration with password validation and OAuth support |
255
255
  | **ForgotPasswordPage** | `hazo_auth/pages/forgot_password` | Request password reset email |
256
256
  | **ResetPasswordPage** | `hazo_auth/pages/reset_password` | Set new password with token |
257
257
  | **VerifyEmailPage** | `hazo_auth/pages/verify_email` | Email verification handler |
@@ -926,7 +926,7 @@ hazo_auth supports Google Sign-In via NextAuth.js v4, allowing users to authenti
926
926
 
927
927
  - **Dual authentication**: Users can have BOTH Google OAuth and email/password login
928
928
  - **Auto-linking**: Automatically links Google login to existing unverified email/password accounts
929
- - **Graceful degradation**: Login page adapts based on enabled authentication methods
929
+ - **Graceful degradation**: Login and register pages adapt based on enabled authentication methods
930
930
  - **Set password feature**: Google-only users can add a password later via My Settings
931
931
  - **Profile data**: Full name and profile picture automatically populated from Google
932
932
 
@@ -1018,6 +1018,7 @@ auto_link_unverified_accounts = true
1018
1018
 
1019
1019
  # Customize button text (optional)
1020
1020
  google_button_text = Continue with Google
1021
+ google_button_text_register = Sign up with Google
1021
1022
  oauth_divider_text = or
1022
1023
 
1023
1024
  # Post-Login Redirect Configuration (v5.1.16+)
@@ -1266,7 +1267,7 @@ export default async function LoginPage() {
1266
1267
 
1267
1268
  **Available Layout Components:**
1268
1269
  - `LoginLayout` - Login form with email/password
1269
- - `RegisterLayout` - Registration form with password requirements
1270
+ - `RegisterLayout` - Registration form with password requirements and OAuth (Google Sign-In)
1270
1271
  - `ForgotPasswordLayout` - Request password reset
1271
1272
  - `ResetPasswordLayout` - Set new password with token
1272
1273
  - `EmailVerificationLayout` - Verify email address
@@ -7,6 +7,7 @@ import { get_config_boolean, get_config_value, read_config_section } from "./con
7
7
  import { get_password_requirements_config } from "./password_requirements_config.server.js";
8
8
  import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
9
9
  import { get_user_fields_config } from "./user_fields_config.server.js";
10
+ import { get_oauth_config } from "./oauth_config.server.js";
10
11
 
11
12
  // Default image path - consuming apps should either:
12
13
  // 1. Configure their own image_src in hazo_auth_config.ini
@@ -33,6 +34,13 @@ export type RegisterConfig = {
33
34
  imageSrc: string;
34
35
  imageAlt: string;
35
36
  imageBackgroundColor: string;
37
+ /** OAuth configuration */
38
+ oauth: {
39
+ enable_google: boolean;
40
+ enable_email_password: boolean;
41
+ google_button_text: string;
42
+ oauth_divider_text: string;
43
+ };
36
44
  };
37
45
 
38
46
  // section: helpers
@@ -89,6 +97,16 @@ export function get_register_config(): RegisterConfig {
89
97
  "#e2e8f0"
90
98
  );
91
99
 
100
+ // Get OAuth configuration (shared with login)
101
+ const oauthConfig = get_oauth_config();
102
+
103
+ // For the register page, default button text to "Sign up with Google" unless overridden
104
+ const registerGoogleButtonText = get_config_value(
105
+ "hazo_auth__oauth",
106
+ "google_button_text_register",
107
+ "Sign up with Google"
108
+ );
109
+
92
110
  return {
93
111
  showNameField,
94
112
  passwordRequirements,
@@ -102,6 +120,12 @@ export function get_register_config(): RegisterConfig {
102
120
  imageSrc,
103
121
  imageAlt,
104
122
  imageBackgroundColor,
123
+ oauth: {
124
+ enable_google: oauthConfig.enable_google,
125
+ enable_email_password: oauthConfig.enable_email_password,
126
+ google_button_text: registerGoogleButtonText,
127
+ oauth_divider_text: oauthConfig.oauth_divider_text,
128
+ },
105
129
  };
106
130
  }
107
131
 
@@ -1,6 +1,16 @@
1
1
  import { type ButtonPaletteOverrides, type LayoutFieldMapOverrides, type LayoutLabelOverrides, type PasswordRequirementOverrides } from "../shared/config/layout_customization.js";
2
2
  import { type LayoutDataClient } from "../shared/data/layout_data_client.js";
3
3
  import type { StaticImageData } from "next/image";
4
+ export type OAuthLayoutConfig = {
5
+ /** Enable Google OAuth login */
6
+ enable_google: boolean;
7
+ /** Enable traditional email/password login */
8
+ enable_email_password: boolean;
9
+ /** Text displayed on the Google sign-in button */
10
+ google_button_text: string;
11
+ /** Text displayed on the divider between OAuth and email/password form */
12
+ oauth_divider_text: string;
13
+ };
4
14
  export type RegisterLayoutProps<TClient = unknown> = {
5
15
  image_src: string | StaticImageData;
6
16
  image_alt: string;
@@ -19,6 +29,8 @@ export type RegisterLayoutProps<TClient = unknown> = {
19
29
  signInPath?: string;
20
30
  signInLabel?: string;
21
31
  urlOnLogon?: string;
32
+ /** OAuth configuration */
33
+ oauth?: OAuthLayoutConfig;
22
34
  };
23
- export default function register_layout<TClient>({ image_src, image_alt, image_background_color, field_overrides, labels, button_colors, password_requirements, show_name_field, data_client, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, signInPath, signInLabel, urlOnLogon, }: RegisterLayoutProps<TClient>): import("react/jsx-runtime").JSX.Element;
35
+ export default function register_layout<TClient>({ image_src, image_alt, image_background_color, field_overrides, labels, button_colors, password_requirements, show_name_field, data_client, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, signInPath, signInLabel, urlOnLogon, oauth, }: RegisterLayoutProps<TClient>): import("react/jsx-runtime").JSX.Element;
24
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/register/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAClC,MAAM,uCAAuC,CAAC;AAY/C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,MAAM,mBAAmB,CAAC,OAAO,GAAG,OAAO,IAAI;IACnD,SAAS,EAAE,MAAM,GAAG,eAAe,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,qBAAqB,CAAC,EAAE,4BAA4B,CAAC;IACrD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAYF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,OAAO,EAAE,EAC/C,SAAS,EACT,SAAS,EACT,sBAAkC,EAClC,eAAe,EACf,MAAM,EACN,aAAa,EACb,qBAAqB,EACrB,eAAsB,EACtB,WAAW,EACX,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,UAA+B,EAC/B,WAAuB,EACvB,UAAU,GACX,EAAE,mBAAmB,CAAC,OAAO,CAAC,2CA+I9B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/register/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAClC,MAAM,uCAAuC,CAAC;AAY/C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gCAAgC;IAChC,aAAa,EAAE,OAAO,CAAC;IACvB,8CAA8C;IAC9C,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kDAAkD;IAClD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,mBAAmB,CAAC,OAAO,GAAG,OAAO,IAAI;IACnD,SAAS,EAAE,MAAM,GAAG,eAAe,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,qBAAqB,CAAC,EAAE,4BAA4B,CAAC;IACrD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B,CAAC;AAYF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,OAAO,EAAE,EAC/C,SAAS,EACT,SAAS,EACT,sBAAkC,EAClC,eAAe,EACf,MAAM,EACN,aAAa,EACb,qBAAqB,EACrB,eAAsB,EACtB,WAAW,EACX,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,UAA+B,EAC/B,WAAuB,EACvB,UAAU,EACV,KAAK,GACN,EAAE,mBAAmB,CAAC,OAAO,CAAC,2CAgN9B"}
@@ -4,6 +4,7 @@
4
4
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
5
5
  // section: imports
6
6
  import Link from "next/link";
7
+ import { useSearchParams } from "next/navigation";
7
8
  import { Input } from "../../ui/input.js";
8
9
  import { PasswordField } from "../shared/components/password_field.js";
9
10
  import { FormFieldWrapper } from "../shared/components/form_field_wrapper.js";
@@ -11,6 +12,9 @@ import { FormHeader } from "../shared/components/form_header.js";
11
12
  import { FormActionButtons } from "../shared/components/form_action_buttons.js";
12
13
  import { TwoColumnAuthLayout } from "../shared/components/two_column_auth_layout.js";
13
14
  import { AlreadyLoggedInGuard } from "../shared/components/already_logged_in_guard.js";
15
+ import { GoogleSignInButton } from "../shared/components/google_sign_in_button.js";
16
+ import { OAuthDivider } from "../shared/components/oauth_divider.js";
17
+ import { AlertCircle } from "lucide-react";
14
18
  import { REGISTER_FIELD_IDS, createRegisterFieldDefinitions, resolveRegisterButtonPalette, resolveRegisterLabels, resolveRegisterPasswordRequirements, } from "./config/register_field_config.js";
15
19
  import { use_register_form, } from "./hooks/use_register_form.js";
16
20
  const ORDERED_FIELDS = [
@@ -20,7 +24,29 @@ const ORDERED_FIELDS = [
20
24
  REGISTER_FIELD_IDS.CONFIRM_PASSWORD,
21
25
  ];
22
26
  // section: component
23
- export default function register_layout({ image_src, image_alt, image_background_color = "#f1f5f9", field_overrides, labels, button_colors, password_requirements, show_name_field = true, data_client, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", signInPath = "/hazo_auth/login", signInLabel = "Sign in", urlOnLogon, }) {
27
+ export default function register_layout({ image_src, image_alt, image_background_color = "#f1f5f9", field_overrides, labels, button_colors, password_requirements, show_name_field = true, data_client, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", signInPath = "/hazo_auth/login", signInLabel = "Sign in", urlOnLogon, oauth, }) {
28
+ // Default OAuth config: both enabled
29
+ const oauthConfig = oauth || {
30
+ enable_google: true,
31
+ enable_email_password: true,
32
+ google_button_text: "Sign up with Google",
33
+ oauth_divider_text: "or continue with email",
34
+ };
35
+ // Read OAuth error from URL query params (e.g., ?error=AccessDenied)
36
+ const searchParams = useSearchParams();
37
+ const oauthError = searchParams.get("error");
38
+ const getOAuthErrorMessage = (error) => {
39
+ switch (error) {
40
+ case "AccessDenied":
41
+ return "Access was denied. You may have cancelled the sign-in or your account is not authorized.";
42
+ case "OAuthSignin":
43
+ case "OAuthCallback":
44
+ case "OAuthCreateAccount":
45
+ return "Something went wrong with Google sign-in. Please try again.";
46
+ default:
47
+ return "An error occurred during sign-in. Please try again.";
48
+ }
49
+ };
24
50
  const fieldDefinitions = createRegisterFieldDefinitions(field_overrides);
25
51
  const resolvedLabels = resolveRegisterLabels(labels);
26
52
  const resolvedButtonPalette = resolveRegisterButtonPalette(button_colors);
@@ -54,5 +80,5 @@ export default function register_layout({ image_src, image_alt, image_background
54
80
  return (_jsx(FormFieldWrapper, { fieldId: fieldDefinition.id, label: fieldDefinition.label, input: inputElement, errorMessage: shouldShowError }, fieldId));
55
81
  });
56
82
  };
57
- return (_jsx(AlreadyLoggedInGuard, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, message: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, children: _jsx(TwoColumnAuthLayout, { imageSrc: image_src, imageAlt: image_alt, imageBackgroundColor: image_background_color, formContent: _jsxs(_Fragment, { children: [_jsx(FormHeader, { heading: resolvedLabels.heading, subHeading: resolvedLabels.subHeading }), _jsxs("form", { className: "cls_register_layout_form_fields flex flex-col gap-5", onSubmit: form.handleSubmit, "aria-label": "Registration form", children: [renderFields(form), _jsx(FormActionButtons, { submitLabel: resolvedLabels.submitButton, cancelLabel: resolvedLabels.cancelButton, buttonPalette: resolvedButtonPalette, isSubmitDisabled: form.isSubmitDisabled, onCancel: form.handleCancel, submitAriaLabel: "Submit registration form", cancelAriaLabel: "Cancel registration form" }), _jsxs("div", { className: "cls_register_layout_sign_in_link flex items-center justify-center gap-1 text-sm text-muted-foreground", children: [_jsx("span", { children: "Already have an account?" }), _jsx(Link, { href: signInPath, className: "cls_register_layout_sign_in_link_text text-primary underline-offset-4 hover:underline", "aria-label": "Go to sign in page", children: signInLabel })] }), form.isSubmitting && (_jsx("div", { className: "cls_register_submitting_indicator text-sm text-slate-600 text-center", children: "Registering..." }))] })] }) }) }));
83
+ return (_jsx(AlreadyLoggedInGuard, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, message: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, children: _jsx(TwoColumnAuthLayout, { imageSrc: image_src, imageAlt: image_alt, imageBackgroundColor: image_background_color, formContent: _jsxs(_Fragment, { children: [_jsx(FormHeader, { heading: resolvedLabels.heading, subHeading: resolvedLabels.subHeading }), oauthError && (_jsxs("div", { className: "cls_register_layout_oauth_error flex items-center gap-2 rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-700", children: [_jsx(AlertCircle, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }), _jsx("span", { children: getOAuthErrorMessage(oauthError) })] })), oauthConfig.enable_google && (_jsx("div", { className: "cls_register_layout_oauth_section", children: _jsx(GoogleSignInButton, { label: oauthConfig.google_button_text }) })), oauthConfig.enable_google && oauthConfig.enable_email_password && (_jsx(OAuthDivider, { text: oauthConfig.oauth_divider_text })), oauthConfig.enable_email_password && (_jsxs("form", { className: "cls_register_layout_form_fields flex flex-col gap-5", onSubmit: form.handleSubmit, "aria-label": "Registration form", children: [renderFields(form), _jsx(FormActionButtons, { submitLabel: resolvedLabels.submitButton, cancelLabel: resolvedLabels.cancelButton, buttonPalette: resolvedButtonPalette, isSubmitDisabled: form.isSubmitDisabled, onCancel: form.handleCancel, submitAriaLabel: "Submit registration form", cancelAriaLabel: "Cancel registration form" }), _jsxs("div", { className: "cls_register_layout_sign_in_link flex items-center justify-center gap-1 text-sm text-muted-foreground", children: [_jsx("span", { children: "Already have an account?" }), _jsx(Link, { href: signInPath, className: "cls_register_layout_sign_in_link_text text-primary underline-offset-4 hover:underline", "aria-label": "Go to sign in page", children: signInLabel })] }), form.isSubmitting && (_jsx("div", { className: "cls_register_submitting_indicator text-sm text-slate-600 text-center", children: "Registering..." }))] })), !oauthConfig.enable_email_password && oauthConfig.enable_google && (_jsxs("div", { className: "cls_register_layout_sign_in_link mt-4 flex items-center justify-center gap-1 text-sm text-muted-foreground", children: [_jsx("span", { children: "Already have an account?" }), _jsx(Link, { href: signInPath, className: "cls_register_layout_sign_in_link_text text-primary underline-offset-4 hover:underline", "aria-label": "Go to sign in page", children: signInLabel })] }))] }) }) }));
58
84
  }
@@ -18,6 +18,13 @@ export type RegisterConfig = {
18
18
  imageSrc: string;
19
19
  imageAlt: string;
20
20
  imageBackgroundColor: string;
21
+ /** OAuth configuration */
22
+ oauth: {
23
+ enable_google: boolean;
24
+ enable_email_password: boolean;
25
+ google_button_text: string;
26
+ oauth_divider_text: string;
27
+ };
21
28
  };
22
29
  /**
23
30
  * Reads register layout configuration from hazo_auth_config.ini file
@@ -1 +1 @@
1
- {"version":3,"file":"register_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/register_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAcrB,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,oBAAoB,EAAE;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,iBAAiB,EAAE,OAAO,CAAC;QAC3B,cAAc,EAAE,OAAO,CAAC;QACxB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAGF;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CA8DpD"}
1
+ {"version":3,"file":"register_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/register_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAerB,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,oBAAoB,EAAE;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,iBAAiB,EAAE,OAAO,CAAC;QAC3B,cAAc,EAAE,OAAO,CAAC;QACxB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,0BAA0B;IAC1B,KAAK,EAAE;QACL,aAAa,EAAE,OAAO,CAAC;QACvB,qBAAqB,EAAE,OAAO,CAAC;QAC/B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;CACH,CAAC;AAGF;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CA8EpD"}
@@ -6,6 +6,7 @@ import { get_config_boolean, get_config_value, read_config_section } from "./con
6
6
  import { get_password_requirements_config } from "./password_requirements_config.server.js";
7
7
  import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
8
8
  import { get_user_fields_config } from "./user_fields_config.server.js";
9
+ import { get_oauth_config } from "./oauth_config.server.js";
9
10
  // Default image path - consuming apps should either:
10
11
  // 1. Configure their own image_src in hazo_auth_config.ini
11
12
  // 2. Copy the default images from node_modules/hazo_auth/public/hazo_auth/images/ to their public folder
@@ -37,6 +38,10 @@ export function get_register_config() {
37
38
  const imageSrc = get_config_value("hazo_auth__register_layout", "image_src", DEFAULT_REGISTER_IMAGE_PATH);
38
39
  const imageAlt = get_config_value("hazo_auth__register_layout", "image_alt", "Modern building representing user registration");
39
40
  const imageBackgroundColor = get_config_value("hazo_auth__register_layout", "image_background_color", "#e2e8f0");
41
+ // Get OAuth configuration (shared with login)
42
+ const oauthConfig = get_oauth_config();
43
+ // For the register page, default button text to "Sign up with Google" unless overridden
44
+ const registerGoogleButtonText = get_config_value("hazo_auth__oauth", "google_button_text_register", "Sign up with Google");
40
45
  return {
41
46
  showNameField,
42
47
  passwordRequirements,
@@ -50,5 +55,11 @@ export function get_register_config() {
50
55
  imageSrc,
51
56
  imageAlt,
52
57
  imageBackgroundColor,
58
+ oauth: {
59
+ enable_google: oauthConfig.enable_google,
60
+ enable_email_password: oauthConfig.enable_email_password,
61
+ google_button_text: registerGoogleButtonText,
62
+ oauth_divider_text: oauthConfig.oauth_divider_text,
63
+ },
53
64
  };
54
65
  }
@@ -1,9 +1,10 @@
1
+ import { NextRequest } from "next/server";
1
2
  type NextAuthContext = {
2
3
  params: Promise<{
3
4
  nextauth: string[];
4
5
  }>;
5
6
  };
6
- export declare function GET(request: Request, context: NextAuthContext): Promise<any>;
7
- export declare function POST(request: Request, context: NextAuthContext): Promise<any>;
7
+ export declare function GET(request: NextRequest, context: NextAuthContext): Promise<any>;
8
+ export declare function POST(request: NextRequest, context: NextAuthContext): Promise<any>;
8
9
  export {};
9
10
  //# sourceMappingURL=nextauth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nextauth.d.ts","sourceRoot":"","sources":["../../../src/server/routes/nextauth.ts"],"names":[],"mappings":"AAQA,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACzC,CAAC;AAyGF,wBAAsB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,gBAEnE;AAED,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,gBAEpE"}
1
+ {"version":3,"file":"nextauth.d.ts","sourceRoot":"","sources":["../../../src/server/routes/nextauth.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACzC,CAAC;AAyGF,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,gBAEvE;AAED,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,gBAExE"}
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/server_pages/register.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAOrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,SAAS,EACT,SAAS,EACT,sBAAsB,GACvB,GAAE,iBAAsB,2CA4BxB;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/server_pages/register.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAOrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,SAAS,EACT,SAAS,EACT,sBAAsB,GACvB,GAAE,iBAAsB,2CAkCxB;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -40,7 +40,12 @@ export default function RegisterPage({ image_src, image_alt, image_background_co
40
40
  const finalImageAlt = image_alt || config.imageAlt;
41
41
  const finalImageBackgroundColor = image_background_color || config.imageBackgroundColor;
42
42
  // Pass serializable config to client wrapper, wrapped in AuthPageShell for navbar support
43
- return (_jsx(AuthPageShell, { children: _jsx(RegisterClientWrapper, { image_src: finalImageSrc, image_alt: finalImageAlt, image_background_color: finalImageBackgroundColor, showNameField: config.showNameField, passwordRequirements: config.passwordRequirements, alreadyLoggedInMessage: config.alreadyLoggedInMessage, showLogoutButton: config.showLogoutButton, showReturnHomeButton: config.showReturnHomeButton, returnHomeButtonLabel: config.returnHomeButtonLabel, returnHomePath: config.returnHomePath, signInPath: config.signInPath, signInLabel: config.signInLabel }) }));
43
+ return (_jsx(AuthPageShell, { children: _jsx(RegisterClientWrapper, { image_src: finalImageSrc, image_alt: finalImageAlt, image_background_color: finalImageBackgroundColor, showNameField: config.showNameField, passwordRequirements: config.passwordRequirements, alreadyLoggedInMessage: config.alreadyLoggedInMessage, showLogoutButton: config.showLogoutButton, showReturnHomeButton: config.showReturnHomeButton, returnHomeButtonLabel: config.returnHomeButtonLabel, returnHomePath: config.returnHomePath, signInPath: config.signInPath, signInLabel: config.signInLabel, oauth: {
44
+ enable_google: config.oauth.enable_google,
45
+ enable_email_password: config.oauth.enable_email_password,
46
+ google_button_text: config.oauth.google_button_text,
47
+ oauth_divider_text: config.oauth.oauth_divider_text,
48
+ } }) }));
44
49
  }
45
50
  // Named export for direct imports
46
51
  export { RegisterPage };
@@ -1,13 +1,16 @@
1
1
  import type { RegisterConfig } from "../lib/register_config.server";
2
+ import type { OAuthLayoutConfig } from "../components/layouts/register/index";
2
3
  import type { StaticImageData } from "next/image";
3
- export type RegisterClientWrapperProps = Omit<RegisterConfig, 'imageSrc' | 'imageAlt' | 'imageBackgroundColor'> & {
4
+ export type RegisterClientWrapperProps = Omit<RegisterConfig, 'imageSrc' | 'imageAlt' | 'imageBackgroundColor' | 'oauth'> & {
4
5
  image_src: string | StaticImageData;
5
6
  image_alt: string;
6
7
  image_background_color: string;
8
+ /** OAuth configuration */
9
+ oauth?: OAuthLayoutConfig;
7
10
  };
8
11
  /**
9
12
  * Client wrapper for RegisterLayout
10
13
  * Initializes hazo_connect data client on client side and passes config from server
11
14
  */
12
- export declare function RegisterClientWrapper({ image_src, image_alt, image_background_color, showNameField, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, signInPath, signInLabel, }: RegisterClientWrapperProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function RegisterClientWrapper({ image_src, image_alt, image_background_color, showNameField, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, signInPath, signInLabel, oauth, }: RegisterClientWrapperProps): import("react/jsx-runtime").JSX.Element;
13
16
  //# sourceMappingURL=register_client_wrapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register_client_wrapper.d.ts","sourceRoot":"","sources":["../../src/server_pages/register_client_wrapper.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,UAAU,GAAG,sBAAsB,CAAC,GAAG;IAChH,SAAS,EAAE,MAAM,GAAG,eAAe,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAAC;AAGF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,SAAS,EACT,sBAAsB,EACtB,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,UAAU,EACV,WAAW,GACZ,EAAE,0BAA0B,2CAqC5B"}
1
+ {"version":3,"file":"register_client_wrapper.d.ts","sourceRoot":"","sources":["../../src/server_pages/register_client_wrapper.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAG9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,UAAU,GAAG,sBAAsB,GAAG,OAAO,CAAC,GAAG;IAC1H,SAAS,EAAE,MAAM,GAAG,eAAe,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,0BAA0B;IAC1B,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B,CAAC;AAGF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,SAAS,EACT,sBAAsB,EACtB,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,UAAU,EACV,WAAW,EACX,KAAK,GACN,EAAE,0BAA0B,2CAsC5B"}
@@ -11,7 +11,7 @@ import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
11
11
  * Client wrapper for RegisterLayout
12
12
  * Initializes hazo_connect data client on client side and passes config from server
13
13
  */
14
- export function RegisterClientWrapper({ image_src, image_alt, image_background_color, showNameField, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, signInPath, signInLabel, }) {
14
+ export function RegisterClientWrapper({ image_src, image_alt, image_background_color, showNameField, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, signInPath, signInLabel, oauth, }) {
15
15
  const [dataClient, setDataClient] = useState(null);
16
16
  useEffect(() => {
17
17
  // Initialize hazo_connect on client side
@@ -23,5 +23,5 @@ export function RegisterClientWrapper({ image_src, image_alt, image_background_c
23
23
  if (!dataClient) {
24
24
  return (_jsx("div", { className: "cls_register_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
25
25
  }
26
- return (_jsx(RegisterLayout, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, data_client: dataClient, show_name_field: showNameField, password_requirements: passwordRequirements, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, signInPath: signInPath, signInLabel: signInLabel }));
26
+ return (_jsx(RegisterLayout, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, data_client: dataClient, show_name_field: showNameField, password_requirements: passwordRequirements, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, signInPath: signInPath, signInLabel: signInLabel, oauth: oauth }));
27
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_auth",
3
- "version": "5.1.34",
3
+ "version": "5.1.36",
4
4
  "description": "Zero-config authentication UI components for Next.js with RBAC, OAuth, scope-based multi-tenancy, and invitations",
5
5
  "keywords": [
6
6
  "authentication",