hazo_auth 6.1.1 → 7.0.1
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 +163 -8
- package/SETUP_CHECKLIST.md +148 -0
- package/cli-src/lib/auth/nextauth_config.ts +101 -1
- package/cli-src/lib/email_verification_config.server.ts +0 -34
- package/cli-src/lib/forgot_password_config.server.ts +0 -34
- package/cli-src/lib/login_config.server.ts +0 -31
- package/cli-src/lib/my_settings_config.server.ts +0 -3
- package/cli-src/lib/oauth_config.server.ts +58 -0
- package/cli-src/lib/register_config.server.ts +11 -31
- package/cli-src/lib/reset_password_config.server.ts +0 -31
- package/cli-src/lib/services/oauth_service.ts +197 -0
- package/config/hazo_auth_config.example.ini +38 -41
- package/dist/components/layouts/create_firm/index.d.ts +4 -8
- package/dist/components/layouts/create_firm/index.d.ts.map +1 -1
- package/dist/components/layouts/create_firm/index.js +3 -3
- package/dist/components/layouts/email_verification/index.d.ts +4 -5
- package/dist/components/layouts/email_verification/index.d.ts.map +1 -1
- package/dist/components/layouts/email_verification/index.js +4 -4
- package/dist/components/layouts/forgot_password/index.d.ts +4 -5
- package/dist/components/layouts/forgot_password/index.d.ts.map +1 -1
- package/dist/components/layouts/forgot_password/index.js +2 -2
- package/dist/components/layouts/login/index.d.ts +13 -9
- package/dist/components/layouts/login/index.d.ts.map +1 -1
- package/dist/components/layouts/login/index.js +12 -6
- package/dist/components/layouts/otp/index.d.ts +8 -1
- package/dist/components/layouts/otp/index.d.ts.map +1 -1
- package/dist/components/layouts/otp/index.js +4 -2
- package/dist/components/layouts/register/index.d.ts +11 -7
- package/dist/components/layouts/register/index.d.ts.map +1 -1
- package/dist/components/layouts/register/index.js +8 -4
- package/dist/components/layouts/reset_password/index.d.ts +4 -5
- package/dist/components/layouts/reset_password/index.d.ts.map +1 -1
- package/dist/components/layouts/reset_password/index.js +5 -5
- package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts +3 -5
- package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/already_logged_in_guard.js +2 -2
- package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts +25 -0
- package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/facebook_sign_in_button.js +49 -0
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +1 -1
- package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts +3 -6
- package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/two_column_auth_layout.js +8 -5
- package/dist/consent/consent_state.d.ts +18 -0
- package/dist/consent/consent_state.d.ts.map +1 -0
- package/dist/consent/consent_state.js +29 -0
- package/dist/consent/cookie_consent_banner.d.ts +11 -0
- package/dist/consent/cookie_consent_banner.d.ts.map +1 -0
- package/dist/consent/cookie_consent_banner.js +40 -0
- package/dist/consent/gtm_mapping.d.ts +13 -0
- package/dist/consent/gtm_mapping.d.ts.map +1 -0
- package/dist/consent/gtm_mapping.js +30 -0
- package/dist/consent/index.d.ts +7 -0
- package/dist/consent/index.d.ts.map +1 -0
- package/dist/consent/index.js +7 -0
- package/dist/consent/manage_modal.d.ts +2 -0
- package/dist/consent/manage_modal.d.ts.map +1 -0
- package/dist/consent/manage_modal.js +33 -0
- package/dist/consent/read_consent.d.ts +15 -0
- package/dist/consent/read_consent.d.ts.map +1 -0
- package/dist/consent/read_consent.js +23 -0
- package/dist/consent/use_consent.d.ts +7 -0
- package/dist/consent/use_consent.d.ts.map +1 -0
- package/dist/consent/use_consent.js +55 -0
- package/dist/lib/auth/nextauth_config.d.ts +10 -0
- package/dist/lib/auth/nextauth_config.d.ts.map +1 -1
- package/dist/lib/auth/nextauth_config.js +80 -2
- package/dist/lib/email_verification_config.server.d.ts +0 -3
- package/dist/lib/email_verification_config.server.d.ts.map +1 -1
- package/dist/lib/email_verification_config.server.js +0 -15
- package/dist/lib/forgot_password_config.server.d.ts +0 -3
- package/dist/lib/forgot_password_config.server.d.ts.map +1 -1
- package/dist/lib/forgot_password_config.server.js +0 -15
- package/dist/lib/login_config.server.d.ts +0 -3
- package/dist/lib/login_config.server.d.ts.map +1 -1
- package/dist/lib/login_config.server.js +0 -13
- package/dist/lib/my_settings_config.server.d.ts +0 -1
- package/dist/lib/my_settings_config.server.d.ts.map +1 -1
- package/dist/lib/my_settings_config.server.js +0 -2
- package/dist/lib/oauth_config.server.d.ts +17 -0
- package/dist/lib/oauth_config.server.d.ts.map +1 -1
- package/dist/lib/oauth_config.server.js +25 -0
- package/dist/lib/register_config.server.d.ts +2 -3
- package/dist/lib/register_config.server.d.ts.map +1 -1
- package/dist/lib/register_config.server.js +4 -13
- package/dist/lib/reset_password_config.server.d.ts +0 -3
- package/dist/lib/reset_password_config.server.d.ts.map +1 -1
- package/dist/lib/reset_password_config.server.js +0 -13
- package/dist/lib/services/oauth_service.d.ts +24 -0
- package/dist/lib/services/oauth_service.d.ts.map +1 -1
- package/dist/lib/services/oauth_service.js +155 -0
- package/dist/page_components/create_firm.d.ts +13 -1
- package/dist/page_components/create_firm.d.ts.map +1 -1
- package/dist/page_components/create_firm.js +10 -6
- package/dist/page_components/forgot_password.d.ts +1 -4
- package/dist/page_components/forgot_password.d.ts.map +1 -1
- package/dist/page_components/forgot_password.js +2 -6
- package/dist/page_components/login.d.ts +1 -4
- package/dist/page_components/login.d.ts.map +1 -1
- package/dist/page_components/login.js +2 -6
- package/dist/page_components/register.d.ts +1 -4
- package/dist/page_components/register.d.ts.map +1 -1
- package/dist/page_components/register.js +2 -6
- package/dist/page_components/reset_password.d.ts +1 -4
- package/dist/page_components/reset_password.d.ts.map +1 -1
- package/dist/page_components/reset_password.js +2 -6
- package/dist/page_components/verify_email.d.ts +1 -4
- package/dist/page_components/verify_email.d.ts.map +1 -1
- package/dist/page_components/verify_email.js +2 -6
- package/dist/server/routes/index.d.ts +1 -0
- package/dist/server/routes/index.d.ts.map +1 -1
- package/dist/server/routes/index.js +1 -0
- package/dist/server/routes/oauth_facebook_callback.d.ts +8 -0
- package/dist/server/routes/oauth_facebook_callback.d.ts.map +1 -0
- package/dist/server/routes/oauth_facebook_callback.js +157 -0
- package/dist/server/routes/oauth_google_callback.js +1 -1
- package/dist/server_pages/forgot_password.d.ts +13 -17
- package/dist/server_pages/forgot_password.d.ts.map +1 -1
- package/dist/server_pages/forgot_password.js +12 -8
- package/dist/server_pages/forgot_password_client_wrapper.d.ts +7 -6
- package/dist/server_pages/forgot_password_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/forgot_password_client_wrapper.js +2 -2
- package/dist/server_pages/login.d.ts +22 -21
- package/dist/server_pages/login.d.ts.map +1 -1
- package/dist/server_pages/login.js +15 -19
- package/dist/server_pages/login_client_wrapper.d.ts +10 -6
- package/dist/server_pages/login_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/login_client_wrapper.js +2 -2
- package/dist/server_pages/my_settings.d.ts +2 -0
- package/dist/server_pages/my_settings.d.ts.map +1 -1
- package/dist/server_pages/my_settings.js +8 -2
- package/dist/server_pages/otp.d.ts +16 -2
- package/dist/server_pages/otp.d.ts.map +1 -1
- package/dist/server_pages/otp.js +10 -3
- package/dist/server_pages/register.d.ts +19 -16
- package/dist/server_pages/register.d.ts.map +1 -1
- package/dist/server_pages/register.js +15 -12
- package/dist/server_pages/register_client_wrapper.d.ts +10 -6
- package/dist/server_pages/register_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/register_client_wrapper.js +2 -2
- package/dist/server_pages/reset_password.d.ts +11 -16
- package/dist/server_pages/reset_password.d.ts.map +1 -1
- package/dist/server_pages/reset_password.js +11 -9
- package/dist/server_pages/reset_password_client_wrapper.d.ts +7 -6
- package/dist/server_pages/reset_password_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/reset_password_client_wrapper.js +2 -2
- package/dist/server_pages/verify_email.d.ts +11 -17
- package/dist/server_pages/verify_email.d.ts.map +1 -1
- package/dist/server_pages/verify_email.js +11 -8
- package/dist/server_pages/verify_email_client_wrapper.d.ts +7 -6
- package/dist/server_pages/verify_email_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/verify_email_client_wrapper.js +2 -2
- package/dist/strings/default_strings.d.ts +47 -0
- package/dist/strings/default_strings.d.ts.map +1 -0
- package/dist/strings/default_strings.js +18 -0
- package/dist/strings/index.d.ts +4 -0
- package/dist/strings/index.d.ts.map +1 -0
- package/dist/strings/index.js +3 -0
- package/dist/strings/strings_context.d.ts +12 -0
- package/dist/strings/strings_context.d.ts.map +1 -0
- package/dist/strings/strings_context.js +23 -0
- package/dist/strings/strings_provider.d.ts +26 -0
- package/dist/strings/strings_provider.d.ts.map +1 -0
- package/dist/strings/strings_provider.js +45 -0
- package/dist/theme/create_theme.d.ts +7 -0
- package/dist/theme/create_theme.d.ts.map +1 -0
- package/dist/theme/create_theme.js +97 -0
- package/dist/theme/hex_to_hsl.d.ts +16 -0
- package/dist/theme/hex_to_hsl.d.ts.map +1 -0
- package/dist/theme/hex_to_hsl.js +110 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +3 -0
- package/dist/theme/luminance.d.ts +11 -0
- package/dist/theme/luminance.d.ts.map +1 -0
- package/dist/theme/luminance.js +45 -0
- package/dist/theme/theme_provider.d.ts +14 -0
- package/dist/theme/theme_provider.d.ts.map +1 -0
- package/dist/theme/theme_provider.js +23 -0
- package/dist/theme/theme_types.d.ts +36 -0
- package/dist/theme/theme_types.d.ts.map +1 -0
- package/dist/theme/theme_types.js +1 -0
- package/dist/themes/index.d.ts +3 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +2 -0
- package/dist/themes/preset_indigo_sunset.d.ts +3 -0
- package/dist/themes/preset_indigo_sunset.d.ts.map +1 -0
- package/dist/themes/preset_indigo_sunset.js +20 -0
- package/dist/themes/preset_neutral.d.ts +3 -0
- package/dist/themes/preset_neutral.d.ts.map +1 -0
- package/dist/themes/preset_neutral.js +14 -0
- package/package.json +19 -2
package/README.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
A reusable authentication UI component package powered by Next.js, TailwindCSS, and shadcn. It integrates `hazo_config` for configuration management and `hazo_connect` for data access, enabling future components to stay aligned with platform conventions.
|
|
4
4
|
|
|
5
|
+
## What's New in v7.0.0
|
|
6
|
+
|
|
7
|
+
**Themes, cookie consent, text overrides, and Facebook OAuth.**
|
|
8
|
+
|
|
9
|
+
### Highlights
|
|
10
|
+
|
|
11
|
+
- **Pluggable theme system** — `createTheme` + `<HazoAuthThemeProvider>` (zero FOUC, compiles to shadcn CSS variables). Use a preset or build from scratch.
|
|
12
|
+
- **Facebook OAuth** — `<FacebookSignInButton>` and `handle_facebook_oauth_login` service. Strict linking by default (verified accounts only).
|
|
13
|
+
- **Cookie consent banner** — `<CookieConsentBanner>` from `hazo_auth/consent`. GTM optional, 4 categories, theme-driven.
|
|
14
|
+
- **Text override system** — `<HazoAuthStringsProvider>` and per-page `title`/`subtitle`/`ctaText`/`legalText` props. INI text keys removed.
|
|
15
|
+
- **Preset themes** — `preset_neutral` (default look, no config needed) and `preset_indigo_sunset` from `hazo_auth/themes`.
|
|
16
|
+
|
|
17
|
+
### Breaking Changes Summary
|
|
18
|
+
|
|
19
|
+
- Per-page `imageSrc`/`imageAlt`/`imageBackgroundColor` props removed — use `theme.brandPanel`.
|
|
20
|
+
- INI text keys (`title`, `subtitle`, `cta_text`, `legal_text`) removed from layout sections — use `HazoAuthStringsProvider` or per-page props.
|
|
21
|
+
- Facebook OAuth requires new env vars (`HAZO_AUTH_FACEBOOK_APP_ID`, `HAZO_AUTH_FACEBOOK_APP_SECRET`).
|
|
22
|
+
|
|
23
|
+
> Full upgrade guide: [MIGRATION.md](./MIGRATION.md)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
5
27
|
## What's New in v6.1.0
|
|
6
28
|
|
|
7
29
|
**Email-OTP sign-in** — a passwordless, OAuth-free way to sign in via a 6-digit code emailed to the user. Targeted at single-operator deployments that don't want to wire Google OAuth or manage passwords.
|
|
@@ -450,23 +472,30 @@ export default function Page() {
|
|
|
450
472
|
}
|
|
451
473
|
```
|
|
452
474
|
|
|
453
|
-
**Customizing Visual Appearance (
|
|
475
|
+
**Customizing Visual Appearance (v7.0+):**
|
|
454
476
|
|
|
455
|
-
|
|
456
|
-
|
|
477
|
+
Use `HazoAuthThemeProvider` instead of per-page image props (which were removed in v7.0):
|
|
478
|
+
|
|
479
|
+
```tsx
|
|
480
|
+
import { createTheme, HazoAuthThemeProvider } from "hazo_auth/theme";
|
|
457
481
|
import { LoginPage } from "hazo_auth/pages/login";
|
|
458
482
|
|
|
483
|
+
const theme = createTheme({
|
|
484
|
+
layout: "split",
|
|
485
|
+
brandPanel: { logoSrc: "/logo.svg", tagline: "Welcome.", backgroundGradient: "linear-gradient(135deg, #3730A3, #F59E0B)" },
|
|
486
|
+
});
|
|
487
|
+
|
|
459
488
|
export default function Page() {
|
|
460
489
|
return (
|
|
461
|
-
<
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
image_background_color="#f0f0f0"
|
|
465
|
-
/>
|
|
490
|
+
<HazoAuthThemeProvider theme={theme}>
|
|
491
|
+
<LoginPage theme={theme} />
|
|
492
|
+
</HazoAuthThemeProvider>
|
|
466
493
|
);
|
|
467
494
|
}
|
|
468
495
|
```
|
|
469
496
|
|
|
497
|
+
See the [Theming](#theming-v700) section for all options.
|
|
498
|
+
|
|
470
499
|
**Embedding MySettings in Your Dashboard:**
|
|
471
500
|
|
|
472
501
|
```typescript
|
|
@@ -656,6 +685,132 @@ The dark class is typically added by next-themes or similar theme providers.
|
|
|
656
685
|
|
|
657
686
|
---
|
|
658
687
|
|
|
688
|
+
## Theming (v7.0.0+)
|
|
689
|
+
|
|
690
|
+
hazo_auth v7 ships a pluggable theme system. `<HazoAuthThemeProvider>` is a Server Component that injects CSS variables at `:root` with zero FOUC.
|
|
691
|
+
|
|
692
|
+
### Option 1: Use a preset directly
|
|
693
|
+
|
|
694
|
+
```tsx
|
|
695
|
+
import { HazoAuthThemeProvider } from "hazo_auth/theme";
|
|
696
|
+
import { preset_indigo_sunset } from "hazo_auth/themes";
|
|
697
|
+
|
|
698
|
+
// app/layout.tsx
|
|
699
|
+
export default function RootLayout({ children }) {
|
|
700
|
+
return (
|
|
701
|
+
<html>
|
|
702
|
+
<body>
|
|
703
|
+
<HazoAuthThemeProvider theme={preset_indigo_sunset}>
|
|
704
|
+
{children}
|
|
705
|
+
</HazoAuthThemeProvider>
|
|
706
|
+
</body>
|
|
707
|
+
</html>
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
`preset_neutral` is the default look (slate-700 palette, centered layout). Auth pages render acceptably with no theme configuration at all.
|
|
713
|
+
|
|
714
|
+
### Option 2: Customize a preset
|
|
715
|
+
|
|
716
|
+
```tsx
|
|
717
|
+
import { createTheme, HazoAuthThemeProvider } from "hazo_auth/theme";
|
|
718
|
+
import { preset_indigo_sunset } from "hazo_auth/themes";
|
|
719
|
+
|
|
720
|
+
const theme = createTheme({
|
|
721
|
+
...preset_indigo_sunset,
|
|
722
|
+
brandPanel: { logoSrc: "/logo.svg", tagline: "Welcome." },
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
<HazoAuthThemeProvider theme={theme}>{children}</HazoAuthThemeProvider>
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
### Option 3: Build from scratch
|
|
729
|
+
|
|
730
|
+
```tsx
|
|
731
|
+
import { createTheme, HazoAuthThemeProvider } from "hazo_auth/theme";
|
|
732
|
+
|
|
733
|
+
const theme = createTheme({
|
|
734
|
+
colors: { primary: "#2563EB", primaryForeground: "#ffffff" },
|
|
735
|
+
layout: "split",
|
|
736
|
+
brandPanel: {
|
|
737
|
+
logoSrc: "/logo.svg",
|
|
738
|
+
tagline: "Welcome to MyApp.",
|
|
739
|
+
backgroundGradient: "linear-gradient(135deg, #2563EB, #7C3AED)",
|
|
740
|
+
},
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
<HazoAuthThemeProvider theme={theme}>{children}</HazoAuthThemeProvider>
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
**Note:** `preset_indigo_sunset` uses `var(--font-display)` and `var(--font-body)`. Wire these in `app/layout.tsx` using `next/font`. See [MIGRATION.md §3](./MIGRATION.md).
|
|
747
|
+
|
|
748
|
+
---
|
|
749
|
+
|
|
750
|
+
## Cookie Consent (v7.0.0+)
|
|
751
|
+
|
|
752
|
+
```tsx
|
|
753
|
+
import { CookieConsentBanner } from "hazo_auth/consent";
|
|
754
|
+
|
|
755
|
+
// In your root layout or a page:
|
|
756
|
+
<CookieConsentBanner />
|
|
757
|
+
|
|
758
|
+
// With GTM:
|
|
759
|
+
<CookieConsentBanner enableGTM gtmContainerId="GTM-XXXX" />
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
Read consent server-side:
|
|
763
|
+
|
|
764
|
+
```tsx
|
|
765
|
+
import { read_consent } from "hazo_auth/consent";
|
|
766
|
+
|
|
767
|
+
export async function GET(request: NextRequest) {
|
|
768
|
+
const consent = read_consent(request.headers);
|
|
769
|
+
if (consent.analytics) {
|
|
770
|
+
// Track event
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
Use the `useConsent` hook client-side:
|
|
776
|
+
|
|
777
|
+
```tsx
|
|
778
|
+
"use client";
|
|
779
|
+
import { useConsent } from "hazo_auth/consent";
|
|
780
|
+
|
|
781
|
+
export function MyComponent() {
|
|
782
|
+
const { analytics, marketing } = useConsent();
|
|
783
|
+
// Syncs across tabs via custom event
|
|
784
|
+
}
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
---
|
|
788
|
+
|
|
789
|
+
## Strings & Text Overrides (v7.0.0+)
|
|
790
|
+
|
|
791
|
+
INI text keys (`title`, `subtitle`, `cta_text`, `legal_text`) are removed in v7. Use `<HazoAuthStringsProvider>` or per-page props instead.
|
|
792
|
+
|
|
793
|
+
### Global overrides (app/layout.tsx)
|
|
794
|
+
|
|
795
|
+
```tsx
|
|
796
|
+
import { HazoAuthStringsProvider } from "hazo_auth/strings";
|
|
797
|
+
|
|
798
|
+
<HazoAuthStringsProvider strings={{ login: { title: "Sign in to MyApp" } }}>
|
|
799
|
+
{children}
|
|
800
|
+
</HazoAuthStringsProvider>
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
### Per-page overrides
|
|
804
|
+
|
|
805
|
+
```tsx
|
|
806
|
+
<LoginPage title="Sign in to MyApp" subtitle="Access your workspace" />
|
|
807
|
+
<RegisterPage title="Create your account" ctaText="Get started" />
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
`DEFAULT_STRINGS` is exported from `hazo_auth/strings` for reference.
|
|
811
|
+
|
|
812
|
+
---
|
|
813
|
+
|
|
659
814
|
## Configuration Setup
|
|
660
815
|
|
|
661
816
|
After installing the package, you need to set up configuration files in your project root:
|
package/SETUP_CHECKLIST.md
CHANGED
|
@@ -1535,6 +1535,154 @@ npm install input-otp
|
|
|
1535
1535
|
|
|
1536
1536
|
---
|
|
1537
1537
|
|
|
1538
|
+
## Phase 5.4: Theme Setup (v7.0.0+)
|
|
1539
|
+
|
|
1540
|
+
### Step 5.4.1: Mount HazoAuthThemeProvider (Required for themed auth pages)
|
|
1541
|
+
|
|
1542
|
+
Mount `<HazoAuthThemeProvider>` in `app/layout.tsx`. Use `preset_neutral` for the default look, or configure a custom theme.
|
|
1543
|
+
|
|
1544
|
+
**Option A: Default look (no config needed)**
|
|
1545
|
+
```tsx
|
|
1546
|
+
import { HazoAuthThemeProvider } from "hazo_auth/theme";
|
|
1547
|
+
import { preset_neutral } from "hazo_auth/themes";
|
|
1548
|
+
|
|
1549
|
+
export default function RootLayout({ children }) {
|
|
1550
|
+
return (
|
|
1551
|
+
<html>
|
|
1552
|
+
<body>
|
|
1553
|
+
<HazoAuthThemeProvider theme={preset_neutral}>
|
|
1554
|
+
{children}
|
|
1555
|
+
</HazoAuthThemeProvider>
|
|
1556
|
+
</body>
|
|
1557
|
+
</html>
|
|
1558
|
+
);
|
|
1559
|
+
}
|
|
1560
|
+
```
|
|
1561
|
+
|
|
1562
|
+
**Option B: Custom theme**
|
|
1563
|
+
```tsx
|
|
1564
|
+
import { createTheme, HazoAuthThemeProvider } from "hazo_auth/theme";
|
|
1565
|
+
|
|
1566
|
+
const theme = createTheme({
|
|
1567
|
+
colors: { primary: "#2563EB" },
|
|
1568
|
+
layout: "split",
|
|
1569
|
+
brandPanel: { logoSrc: "/logo.svg", tagline: "Welcome." },
|
|
1570
|
+
});
|
|
1571
|
+
|
|
1572
|
+
<HazoAuthThemeProvider theme={theme}>{children}</HazoAuthThemeProvider>
|
|
1573
|
+
```
|
|
1574
|
+
|
|
1575
|
+
**If using `preset_indigo_sunset` (custom fonts required):**
|
|
1576
|
+
|
|
1577
|
+
Wire `next/font` in `app/layout.tsx` to expose `--font-display` and `--font-body` CSS variables. See [MIGRATION.md §3](./MIGRATION.md).
|
|
1578
|
+
|
|
1579
|
+
```tsx
|
|
1580
|
+
import { Crimson_Pro, DM_Sans } from "next/font/google";
|
|
1581
|
+
const display = Crimson_Pro({ subsets: ["latin"], variable: "--font-display" });
|
|
1582
|
+
const body = DM_Sans({ subsets: ["latin"], variable: "--font-body" });
|
|
1583
|
+
|
|
1584
|
+
export default function Layout({ children }) {
|
|
1585
|
+
return <html className={`${display.variable} ${body.variable}`}>{children}</html>;
|
|
1586
|
+
}
|
|
1587
|
+
```
|
|
1588
|
+
|
|
1589
|
+
**Checklist:**
|
|
1590
|
+
- [ ] `<HazoAuthThemeProvider>` mounted in `app/layout.tsx`
|
|
1591
|
+
- [ ] Preset or custom theme configured
|
|
1592
|
+
- [ ] If using `preset_indigo_sunset`: `next/font` wired for `--font-display` and `--font-body`
|
|
1593
|
+
|
|
1594
|
+
---
|
|
1595
|
+
|
|
1596
|
+
## Phase 5.5: Facebook OAuth Setup (Optional, v7.0.0+)
|
|
1597
|
+
|
|
1598
|
+
### Step 5.5.1: Get Facebook App credentials
|
|
1599
|
+
|
|
1600
|
+
1. Go to [Meta Developers](https://developers.facebook.com/)
|
|
1601
|
+
2. Create or select an app
|
|
1602
|
+
3. Add the **Facebook Login** product
|
|
1603
|
+
4. Set authorized redirect URIs: `http://localhost:3000/api/auth/callback/facebook` (dev) and your production URL
|
|
1604
|
+
5. Copy **App ID** and **App Secret**
|
|
1605
|
+
|
|
1606
|
+
### Step 5.5.2: Add Facebook OAuth environment variables
|
|
1607
|
+
|
|
1608
|
+
Add to your `.env.local`:
|
|
1609
|
+
```env
|
|
1610
|
+
HAZO_AUTH_FACEBOOK_APP_ID=your_app_id
|
|
1611
|
+
HAZO_AUTH_FACEBOOK_APP_SECRET=your_app_secret
|
|
1612
|
+
```
|
|
1613
|
+
|
|
1614
|
+
The Facebook sign-in button is hidden when these vars are not set.
|
|
1615
|
+
|
|
1616
|
+
### Step 5.5.3: Enable Facebook in config
|
|
1617
|
+
|
|
1618
|
+
Add to `config/hazo_auth_config.ini`:
|
|
1619
|
+
```ini
|
|
1620
|
+
[hazo_auth__oauth]
|
|
1621
|
+
enable_facebook = true
|
|
1622
|
+
|
|
1623
|
+
; Facebook: default false — stricter security posture
|
|
1624
|
+
; Set true only if you want to auto-link to unverified email accounts
|
|
1625
|
+
auto_link_unverified_accounts_facebook = false
|
|
1626
|
+
```
|
|
1627
|
+
|
|
1628
|
+
### Step 5.5.4: Apply Facebook migration
|
|
1629
|
+
|
|
1630
|
+
```bash
|
|
1631
|
+
npm run migrate migrations/016_facebook_oauth.sql
|
|
1632
|
+
```
|
|
1633
|
+
|
|
1634
|
+
### Step 5.5.5: Create Facebook OAuth callback route
|
|
1635
|
+
|
|
1636
|
+
```typescript
|
|
1637
|
+
// app/api/hazo_auth/oauth/facebook/callback/route.ts
|
|
1638
|
+
export { GET } from "hazo_auth/server/routes/oauth_facebook_callback";
|
|
1639
|
+
```
|
|
1640
|
+
|
|
1641
|
+
**Facebook OAuth Checklist:**
|
|
1642
|
+
- [ ] Facebook App credentials obtained
|
|
1643
|
+
- [ ] `HAZO_AUTH_FACEBOOK_APP_ID` and `HAZO_AUTH_FACEBOOK_APP_SECRET` set in `.env.local`
|
|
1644
|
+
- [ ] `enable_facebook = true` in `[hazo_auth__oauth]`
|
|
1645
|
+
- [ ] Migration `016_facebook_oauth.sql` applied
|
|
1646
|
+
- [ ] Facebook callback route created
|
|
1647
|
+
|
|
1648
|
+
---
|
|
1649
|
+
|
|
1650
|
+
## Phase 5.6: Cookie Consent Setup (Optional, v7.0.0+)
|
|
1651
|
+
|
|
1652
|
+
### Step 5.6.1: Mount CookieConsentBanner
|
|
1653
|
+
|
|
1654
|
+
Mount `<CookieConsentBanner>` in your root layout:
|
|
1655
|
+
|
|
1656
|
+
```tsx
|
|
1657
|
+
import { CookieConsentBanner } from "hazo_auth/consent";
|
|
1658
|
+
|
|
1659
|
+
export default function RootLayout({ children }) {
|
|
1660
|
+
return (
|
|
1661
|
+
<html>
|
|
1662
|
+
<body>
|
|
1663
|
+
<HazoAuthThemeProvider theme={preset_neutral}>
|
|
1664
|
+
{children}
|
|
1665
|
+
<CookieConsentBanner />
|
|
1666
|
+
</HazoAuthThemeProvider>
|
|
1667
|
+
</body>
|
|
1668
|
+
</html>
|
|
1669
|
+
);
|
|
1670
|
+
}
|
|
1671
|
+
```
|
|
1672
|
+
|
|
1673
|
+
**With GTM (optional):**
|
|
1674
|
+
```tsx
|
|
1675
|
+
<CookieConsentBanner enableGTM gtmContainerId="GTM-XXXX" />
|
|
1676
|
+
```
|
|
1677
|
+
|
|
1678
|
+
See the README [Cookie Consent](#cookie-consent-v700) section for server-side `read_consent` usage.
|
|
1679
|
+
|
|
1680
|
+
**Checklist:**
|
|
1681
|
+
- [ ] `<CookieConsentBanner>` mounted in root layout
|
|
1682
|
+
- [ ] GTM container ID configured (if using GTM)
|
|
1683
|
+
|
|
1684
|
+
---
|
|
1685
|
+
|
|
1538
1686
|
## Phase 6: Verification Tests
|
|
1539
1687
|
|
|
1540
1688
|
Run these tests to verify your setup is working correctly.
|
|
@@ -5,8 +5,10 @@ import type { JWT } from "next-auth/jwt";
|
|
|
5
5
|
// ESM/CJS interop: next-auth providers are CommonJS, handle both export scenarios
|
|
6
6
|
import GoogleProviderImport from "next-auth/providers/google";
|
|
7
7
|
const GoogleProvider = (GoogleProviderImport as any).default || GoogleProviderImport;
|
|
8
|
+
import FacebookProviderImport from "next-auth/providers/facebook";
|
|
9
|
+
const FacebookProvider = (FacebookProviderImport as any).default || FacebookProviderImport;
|
|
8
10
|
import { get_oauth_config } from "../oauth_config.server.js";
|
|
9
|
-
import { handle_google_oauth_login } from "../services/oauth_service.js";
|
|
11
|
+
import { handle_google_oauth_login, handle_facebook_oauth_login } from "../services/oauth_service.js";
|
|
10
12
|
import { get_hazo_connect_instance } from "../hazo_connect_instance.server.js";
|
|
11
13
|
import { create_app_logger } from "../app_logger.js";
|
|
12
14
|
|
|
@@ -35,6 +37,13 @@ export type NextAuthCallbackProfile = {
|
|
|
35
37
|
email_verified?: boolean;
|
|
36
38
|
};
|
|
37
39
|
|
|
40
|
+
export type FacebookCallbackProfile = {
|
|
41
|
+
id?: string;
|
|
42
|
+
name?: string;
|
|
43
|
+
email?: string;
|
|
44
|
+
picture?: { data?: { url: string } } | string;
|
|
45
|
+
};
|
|
46
|
+
|
|
38
47
|
// section: config
|
|
39
48
|
/**
|
|
40
49
|
* Gets NextAuth.js configuration with enabled OAuth providers
|
|
@@ -67,6 +76,21 @@ export function get_nextauth_config(): AuthOptions {
|
|
|
67
76
|
}
|
|
68
77
|
}
|
|
69
78
|
|
|
79
|
+
// Add Facebook provider if enabled and credentials are present
|
|
80
|
+
if (oauth_config.enable_facebook && oauth_config.facebook_client_id && oauth_config.facebook_client_secret) {
|
|
81
|
+
providers.push(
|
|
82
|
+
FacebookProvider({
|
|
83
|
+
clientId: oauth_config.facebook_client_id,
|
|
84
|
+
clientSecret: oauth_config.facebook_client_secret,
|
|
85
|
+
authorization: {
|
|
86
|
+
params: {
|
|
87
|
+
scope: "email,public_profile",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
70
94
|
return {
|
|
71
95
|
providers,
|
|
72
96
|
pages: {
|
|
@@ -88,6 +112,9 @@ export function get_nextauth_config(): AuthOptions {
|
|
|
88
112
|
if (url.includes("/api/hazo_auth/oauth/google/callback")) {
|
|
89
113
|
return url;
|
|
90
114
|
}
|
|
115
|
+
if (url.includes("/api/hazo_auth/oauth/facebook/callback")) {
|
|
116
|
+
return url;
|
|
117
|
+
}
|
|
91
118
|
|
|
92
119
|
// If URL is relative or same origin, allow it
|
|
93
120
|
if (url.startsWith("/")) {
|
|
@@ -162,6 +189,75 @@ export function get_nextauth_config(): AuthOptions {
|
|
|
162
189
|
return false;
|
|
163
190
|
}
|
|
164
191
|
}
|
|
192
|
+
|
|
193
|
+
if (account?.provider === "facebook" && profile) {
|
|
194
|
+
try {
|
|
195
|
+
const fbProfile = profile as FacebookCallbackProfile;
|
|
196
|
+
const hazoConnect = get_hazo_connect_instance();
|
|
197
|
+
const current_oauth_config = get_oauth_config();
|
|
198
|
+
|
|
199
|
+
// Resolve profile picture URL from Facebook's nested structure
|
|
200
|
+
let fb_picture_url: string | undefined;
|
|
201
|
+
if (fbProfile.picture) {
|
|
202
|
+
if (typeof fbProfile.picture === "string") {
|
|
203
|
+
fb_picture_url = fbProfile.picture;
|
|
204
|
+
} else if (fbProfile.picture?.data?.url) {
|
|
205
|
+
fb_picture_url = fbProfile.picture.data.url;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (!fb_picture_url && user.image) {
|
|
209
|
+
fb_picture_url = user.image ?? undefined;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
logger.info("nextauth_facebook_signin_attempt", {
|
|
213
|
+
email: user.email,
|
|
214
|
+
facebook_id: fbProfile.id,
|
|
215
|
+
name: user.name,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const result = await handle_facebook_oauth_login(
|
|
219
|
+
hazoConnect,
|
|
220
|
+
{
|
|
221
|
+
facebook_id: fbProfile.id || account.providerAccountId,
|
|
222
|
+
email: user.email ?? fbProfile.email ?? null,
|
|
223
|
+
name: user.name || fbProfile.name || undefined,
|
|
224
|
+
profile_picture_url: fb_picture_url,
|
|
225
|
+
},
|
|
226
|
+
{ auto_link_unverified: current_oauth_config.auto_link_unverified_accounts_facebook }
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
if (!result.success) {
|
|
230
|
+
logger.error("nextauth_facebook_signin_failed", {
|
|
231
|
+
email: user.email,
|
|
232
|
+
error: result.error,
|
|
233
|
+
});
|
|
234
|
+
if (result.error === "link_blocked_unverified") {
|
|
235
|
+
return `/hazo_auth/login?error=link_blocked_unverified`;
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
logger.info("nextauth_facebook_signin_success", {
|
|
241
|
+
user_id: result.user_id,
|
|
242
|
+
email: result.email,
|
|
243
|
+
is_new_user: result.is_new_user,
|
|
244
|
+
was_linked: result.was_linked,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Store user_id in account for the JWT callback to pick up
|
|
248
|
+
(account as Record<string, unknown>).hazo_user_id = result.user_id;
|
|
249
|
+
|
|
250
|
+
return true;
|
|
251
|
+
} catch (error) {
|
|
252
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
253
|
+
logger.error("nextauth_facebook_signin_exception", {
|
|
254
|
+
email: user.email,
|
|
255
|
+
error: errorMessage,
|
|
256
|
+
});
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
165
261
|
return true;
|
|
166
262
|
},
|
|
167
263
|
/**
|
|
@@ -225,5 +321,9 @@ export function has_oauth_providers(): boolean {
|
|
|
225
321
|
if (has_google_credentials) return true;
|
|
226
322
|
}
|
|
227
323
|
|
|
324
|
+
if (oauth_config.enable_facebook && oauth_config.facebook_client_id && oauth_config.facebook_client_secret) {
|
|
325
|
+
return true;
|
|
326
|
+
}
|
|
327
|
+
|
|
228
328
|
return false;
|
|
229
329
|
}
|
|
@@ -4,12 +4,6 @@ import "server-only";
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
|
|
7
|
-
import { get_config_value } from "./config/config_loader.server.js";
|
|
8
|
-
|
|
9
|
-
// Default image path - consuming apps should either:
|
|
10
|
-
// 1. Configure their own image_src in hazo_auth_config.ini
|
|
11
|
-
// 2. Copy the default images from node_modules/hazo_auth/public/hazo_auth/images/ to their public folder
|
|
12
|
-
const DEFAULT_VERIFY_EMAIL_IMAGE_PATH = "/hazo_auth/images/verify_email_default.jpg";
|
|
13
7
|
|
|
14
8
|
// section: types
|
|
15
9
|
export type EmailVerificationConfig = {
|
|
@@ -18,9 +12,6 @@ export type EmailVerificationConfig = {
|
|
|
18
12
|
showReturnHomeButton: boolean;
|
|
19
13
|
returnHomeButtonLabel: string;
|
|
20
14
|
returnHomePath: string;
|
|
21
|
-
imageSrc: string;
|
|
22
|
-
imageAlt: string;
|
|
23
|
-
imageBackgroundColor: string;
|
|
24
15
|
};
|
|
25
16
|
|
|
26
17
|
// section: helpers
|
|
@@ -30,40 +21,15 @@ export type EmailVerificationConfig = {
|
|
|
30
21
|
* @returns Email verification configuration options
|
|
31
22
|
*/
|
|
32
23
|
export function get_email_verification_config(): EmailVerificationConfig {
|
|
33
|
-
const section = "hazo_auth__email_verification_layout";
|
|
34
|
-
|
|
35
24
|
// Get shared already logged in config
|
|
36
25
|
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
37
26
|
|
|
38
|
-
// Read image configuration
|
|
39
|
-
// If not set in config, falls back to default path-based image
|
|
40
|
-
// Consuming apps should copy images to public/hazo_auth/images/ or configure their own image_src
|
|
41
|
-
const imageSrc = get_config_value(
|
|
42
|
-
section,
|
|
43
|
-
"image_src",
|
|
44
|
-
DEFAULT_VERIFY_EMAIL_IMAGE_PATH
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
const imageAlt = get_config_value(
|
|
48
|
-
section,
|
|
49
|
-
"image_alt",
|
|
50
|
-
"Email verification illustration"
|
|
51
|
-
);
|
|
52
|
-
const imageBackgroundColor = get_config_value(
|
|
53
|
-
section,
|
|
54
|
-
"image_background_color",
|
|
55
|
-
"#f1f5f9"
|
|
56
|
-
);
|
|
57
|
-
|
|
58
27
|
return {
|
|
59
28
|
alreadyLoggedInMessage: alreadyLoggedInConfig.message,
|
|
60
29
|
showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
|
|
61
30
|
showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
|
|
62
31
|
returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
|
|
63
32
|
returnHomePath: alreadyLoggedInConfig.returnHomePath,
|
|
64
|
-
imageSrc,
|
|
65
|
-
imageAlt,
|
|
66
|
-
imageBackgroundColor,
|
|
67
33
|
};
|
|
68
34
|
}
|
|
69
35
|
|
|
@@ -4,12 +4,6 @@ import "server-only";
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
|
|
7
|
-
import { get_config_value } from "./config/config_loader.server.js";
|
|
8
|
-
|
|
9
|
-
// Default image path - consuming apps should either:
|
|
10
|
-
// 1. Configure their own image_src in hazo_auth_config.ini
|
|
11
|
-
// 2. Copy the default images from node_modules/hazo_auth/public/hazo_auth/images/ to their public folder
|
|
12
|
-
const DEFAULT_FORGOT_PASSWORD_IMAGE_PATH = "/hazo_auth/images/forgot_password_default.jpg";
|
|
13
7
|
|
|
14
8
|
// section: types
|
|
15
9
|
export type ForgotPasswordConfig = {
|
|
@@ -18,9 +12,6 @@ export type ForgotPasswordConfig = {
|
|
|
18
12
|
showReturnHomeButton: boolean;
|
|
19
13
|
returnHomeButtonLabel: string;
|
|
20
14
|
returnHomePath: string;
|
|
21
|
-
imageSrc: string;
|
|
22
|
-
imageAlt: string;
|
|
23
|
-
imageBackgroundColor: string;
|
|
24
15
|
};
|
|
25
16
|
|
|
26
17
|
// section: helpers
|
|
@@ -30,40 +21,15 @@ export type ForgotPasswordConfig = {
|
|
|
30
21
|
* @returns Forgot password configuration options
|
|
31
22
|
*/
|
|
32
23
|
export function get_forgot_password_config(): ForgotPasswordConfig {
|
|
33
|
-
const section = "hazo_auth__forgot_password_layout";
|
|
34
|
-
|
|
35
24
|
// Get shared already logged in config
|
|
36
25
|
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
37
26
|
|
|
38
|
-
// Read image configuration
|
|
39
|
-
// If not set in config, falls back to default path-based image
|
|
40
|
-
// Consuming apps should copy images to public/hazo_auth/images/ or configure their own image_src
|
|
41
|
-
const imageSrc = get_config_value(
|
|
42
|
-
section,
|
|
43
|
-
"image_src",
|
|
44
|
-
DEFAULT_FORGOT_PASSWORD_IMAGE_PATH
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
const imageAlt = get_config_value(
|
|
48
|
-
section,
|
|
49
|
-
"image_alt",
|
|
50
|
-
"Password recovery illustration"
|
|
51
|
-
);
|
|
52
|
-
const imageBackgroundColor = get_config_value(
|
|
53
|
-
section,
|
|
54
|
-
"image_background_color",
|
|
55
|
-
"#f1f5f9"
|
|
56
|
-
);
|
|
57
|
-
|
|
58
27
|
return {
|
|
59
28
|
alreadyLoggedInMessage: alreadyLoggedInConfig.message,
|
|
60
29
|
showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
|
|
61
30
|
showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
|
|
62
31
|
returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
|
|
63
32
|
returnHomePath: alreadyLoggedInConfig.returnHomePath,
|
|
64
|
-
imageSrc,
|
|
65
|
-
imageAlt,
|
|
66
|
-
imageBackgroundColor,
|
|
67
33
|
};
|
|
68
34
|
}
|
|
69
35
|
|
|
@@ -7,11 +7,6 @@ import { get_config_value, get_config_value_allow_empty } from "./config/config_
|
|
|
7
7
|
import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
|
|
8
8
|
import { get_oauth_config, type OAuthConfig } from "./oauth_config.server.js";
|
|
9
9
|
|
|
10
|
-
// Default image path - consuming apps should either:
|
|
11
|
-
// 1. Configure their own image_src in hazo_auth_config.ini
|
|
12
|
-
// 2. Copy the default images from node_modules/hazo_auth/public/hazo_auth/images/ to their public folder
|
|
13
|
-
const DEFAULT_LOGIN_IMAGE_PATH = "/hazo_auth/images/login_default.jpg";
|
|
14
|
-
|
|
15
10
|
// section: types
|
|
16
11
|
export type LoginConfig = {
|
|
17
12
|
redirectRoute?: string;
|
|
@@ -26,9 +21,6 @@ export type LoginConfig = {
|
|
|
26
21
|
createAccountPath: string;
|
|
27
22
|
createAccountLabel: string;
|
|
28
23
|
showCreateAccountLink: boolean;
|
|
29
|
-
imageSrc: string;
|
|
30
|
-
imageAlt: string;
|
|
31
|
-
imageBackgroundColor: string;
|
|
32
24
|
/** OAuth configuration */
|
|
33
25
|
oauth: OAuthConfig;
|
|
34
26
|
/** Whether the OTP sign-in link is shown below the login form */
|
|
@@ -77,26 +69,6 @@ export function get_login_config(): LoginConfig {
|
|
|
77
69
|
// Get shared already logged in config
|
|
78
70
|
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
79
71
|
|
|
80
|
-
// Read image configuration
|
|
81
|
-
// If not set in config, falls back to default path-based image
|
|
82
|
-
// Consuming apps should copy images to public/hazo_auth/images/ or configure their own image_src
|
|
83
|
-
const imageSrc = get_config_value(
|
|
84
|
-
section,
|
|
85
|
-
"image_src",
|
|
86
|
-
DEFAULT_LOGIN_IMAGE_PATH
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
const imageAlt = get_config_value(
|
|
90
|
-
section,
|
|
91
|
-
"image_alt",
|
|
92
|
-
"Secure login illustration"
|
|
93
|
-
);
|
|
94
|
-
const imageBackgroundColor = get_config_value(
|
|
95
|
-
section,
|
|
96
|
-
"image_background_color",
|
|
97
|
-
"#f1f5f9"
|
|
98
|
-
);
|
|
99
|
-
|
|
100
72
|
// Get OAuth configuration
|
|
101
73
|
const oauth = get_oauth_config();
|
|
102
74
|
|
|
@@ -118,9 +90,6 @@ export function get_login_config(): LoginConfig {
|
|
|
118
90
|
createAccountPath,
|
|
119
91
|
createAccountLabel,
|
|
120
92
|
showCreateAccountLink,
|
|
121
|
-
imageSrc,
|
|
122
|
-
imageAlt,
|
|
123
|
-
imageBackgroundColor,
|
|
124
93
|
oauth,
|
|
125
94
|
otpSigninEnabled,
|
|
126
95
|
otpSigninLabel,
|