"use client"; import Image from 'next/image'; import React, { useState, useEffect } from "react"; import { useGoogleLogin } from "@react-oauth/google"; import { useTheme } from 'next-themes'; import { Sun, Moon } from 'lucide-react'; // Optional: install lucide-react for clean icons interface GoogleAuthResponse { access_token: string; token_type: string; expires_in: number; scope: string; authuser?: string; prompt?: string; } interface KeycloakTokenResponse { access_token: string; expires_in: number; refresh_expires_in: number; refresh_token: string; token_type: string; id_token?: string; "not-before-policy": number; session_state: string; scope: string; } export default function AppleStyleAuth() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const { theme, setTheme } = useTheme(); const [mounted, setMounted] = useState(false); // Avoid hydration mismatch by waiting for mount useEffect(() => { setMounted(true); }, []); const handleExchange = async (googleResponse: GoogleAuthResponse): Promise => { try { const details: Record = { grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange', client_id: 'tvone-web', // Replace with your actual Keycloak Client ID subject_token: googleResponse.access_token, subject_token_type: 'urn:ietf:params:oauth:token-type:access_token', subject_issuer: 'google', // Ensure this matches your Keycloak IdP Alias }; const formBody = new URLSearchParams(details).toString(); const response = await fetch( 'https://keycloak.petermaquiran.xyz/realms/tvone/protocol/openid-connect/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: formBody, } ); if (!response.ok) { throw new Error(`Keycloak exchange failed: ${response.statusText}`); } const data: KeycloakTokenResponse = await response.json(); // Store the Keycloak token to send to your NestJS API localStorage.setItem("token", data.access_token); console.log("Authenticated with Keycloak:", data.access_token); // Redirect user or update Global Auth State here } catch (error) { console.error("Authentication Flow Error:", error); } }; const googleLogin = useGoogleLogin({ onSuccess: (res) => { handleExchange(res) console.log("Google Success", res) }, onError: () => console.log("Google Failed"), }); const handleManualLogin = async (): Promise => { const details: Record = { grant_type: 'password', client_id: 'tvone-web-client', username: email, password: password, scope: 'openid', }; try { const response = await fetch( 'https://keycloak.petermaquiran.xyz/realms//protocol/openid-connect/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams(details).toString(), } ); const data: KeycloakTokenResponse = await response.json(); if (data.access_token) { localStorage.setItem("token", data.access_token); } } catch (err) { console.error("Login failed", err); } }; if (!mounted) return null; return (
{/* THEME TOGGLE BUTTON */}
{/* 1. LOGOTIPO */}
logo

Iniciar sessão

Usa a tua conta TVone.

{/* 2. FORMULÁRIO */}
setEmail(e.target.value)} className="w-full rounded-2xl border border-neutral-200 bg-white/50 px-5 py-4 text-sm outline-none transition-all focus:border-blue-500 focus:bg-white focus:text-black focus:ring-4 focus:ring-blue-500/10 dark:border-neutral-800 dark:bg-neutral-900 dark:text-white" /> setPassword(e.target.value)} className="w-full rounded-2xl border border-neutral-200 bg-white/50 px-5 py-4 text-sm outline-none transition-all focus:border-blue-500 focus:bg-white focus:text-black focus:ring-4 focus:ring-blue-500/10 dark:border-neutral-800 dark:bg-neutral-900 dark:text-white" />
{/* 3. DIVISOR */}
ou
{/* 4. BOTÃO GOOGLE */} {/* 5. LINKS */}
); }