login with facebook added
This commit is contained in:
@@ -1,28 +1,23 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OAuthButtons — "Continue with Google / Facebook" row used above both
|
* OAuthButtons — "Continue with …" row used above both LoginForm and
|
||||||
* LoginForm and SignUpForm. Clicking a button performs a top-level
|
* SignUpForm. Clicking a button performs a top-level navigation to the
|
||||||
* navigation to the BFF's /oauth/<provider>/start endpoint, which kicks off
|
* BFF's /oauth/<provider>/start endpoint, which kicks off the
|
||||||
* the Authorization Code flow. The BFF handles the round-trip and 302s back
|
* Authorization Code flow. The BFF handles the round-trip and 302s back
|
||||||
* to ${frontend}${next} with the session cookie already set.
|
* to ${frontend}${next} with the session cookie already set.
|
||||||
*
|
*
|
||||||
* Top-level navigation (not fetch) is intentional: cross-origin redirects
|
* Top-level navigation (not fetch) is intentional: cross-origin redirects
|
||||||
* to Google / Facebook can't happen from XHR, and we need the BFF to set
|
* to Google / Facebook can't happen from XHR, and we need the BFF to set
|
||||||
* the cookie before the browser lands back on the frontend.
|
* the cookie before the browser lands back on the frontend.
|
||||||
|
*
|
||||||
|
* To re-enable a provider that's currently commented out, uncomment its
|
||||||
|
* <a> block in the grid below.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useMemo } from "react";
|
|
||||||
|
|
||||||
const BFF_BASE =
|
const BFF_BASE =
|
||||||
process.env.NEXT_PUBLIC_BFF_URL || "http://localhost:8080";
|
process.env.NEXT_PUBLIC_BFF_URL || "http://localhost:8080";
|
||||||
|
|
||||||
// Build-time switch — keep the buttons hidden until the Google + Facebook
|
|
||||||
// OAuth apps clear review. Flip `NEXT_PUBLIC_OAUTH_ENABLED=true` on the
|
|
||||||
// Next.js build (Vercel/Dokploy env vars) once approval lands; no code
|
|
||||||
// change required. Defaults to disabled so prod stays safe by default.
|
|
||||||
const OAUTH_ENABLED = process.env.NEXT_PUBLIC_OAUTH_ENABLED === "true";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/** Frontend path to land on after the round-trip. Defaults to /u/me. */
|
/** Frontend path to land on after the round-trip. Defaults to /u/me. */
|
||||||
next?: string;
|
next?: string;
|
||||||
@@ -31,34 +26,30 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function OAuthButtons({ next, showDivider = true }: Props) {
|
export function OAuthButtons({ next, showDivider = true }: Props) {
|
||||||
// Suppress the whole row (no buttons → no "or" divider either) while
|
function startUrl(provider: "google" | "facebook"): string {
|
||||||
// the OAuth apps are under review.
|
const u = new URL(`${BFF_BASE}/api/v1/auth/oauth/${provider}/start`);
|
||||||
if (!OAUTH_ENABLED) return null;
|
if (next) u.searchParams.set("next", next);
|
||||||
const startUrl = useMemo(
|
return u.toString();
|
||||||
() => (provider: "google" | "facebook") => {
|
}
|
||||||
const u = new URL(`${BFF_BASE}/api/v1/auth/oauth/${provider}/start`);
|
|
||||||
if (next) u.searchParams.set("next", next);
|
|
||||||
return u.toString();
|
|
||||||
},
|
|
||||||
[next],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="grid grid-cols-1 gap-2 sm:grid-cols-2">
|
<div className="grid grid-cols-1 gap-2">
|
||||||
|
{/* Google sign-in — uncomment once the Google OAuth app clears review.
|
||||||
<a
|
<a
|
||||||
href={startUrl("google")}
|
href={startUrl("google")}
|
||||||
className="h-11 inline-flex items-center justify-center gap-2 rounded-md border border-border bg-card text-sm font-medium text-foreground hover:bg-muted transition-colors"
|
className="h-11 inline-flex items-center justify-center gap-2 rounded-md border border-border bg-card text-sm font-medium text-foreground hover:bg-muted transition-colors"
|
||||||
>
|
>
|
||||||
<GoogleIcon className="size-4" />
|
<GoogleIcon className="size-4" />
|
||||||
Google
|
Login with Google
|
||||||
</a>
|
</a>
|
||||||
|
*/}
|
||||||
<a
|
<a
|
||||||
href={startUrl("facebook")}
|
href={startUrl("facebook")}
|
||||||
className="h-11 inline-flex items-center justify-center gap-2 rounded-md border border-border bg-card text-sm font-medium text-foreground hover:bg-muted transition-colors"
|
className="h-11 inline-flex items-center justify-center gap-2 rounded-md border border-border bg-card text-sm font-medium text-foreground hover:bg-muted transition-colors"
|
||||||
>
|
>
|
||||||
<FacebookIcon className="size-4" />
|
<FacebookIcon className="size-4" />
|
||||||
Facebook
|
Login with Facebook
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{showDivider ? (
|
{showDivider ? (
|
||||||
@@ -74,6 +65,9 @@ export function OAuthButtons({ next, showDivider = true }: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kept exported-internally so the Google block above can be uncommented
|
||||||
|
// without re-importing or re-pasting the SVG.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
function GoogleIcon({ className }: { className?: string }) {
|
function GoogleIcon({ className }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg className={className} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden>
|
<svg className={className} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden>
|
||||||
|
|||||||
Reference in New Issue
Block a user