diff --git a/app/api/auth/rocket-login/route.ts b/app/api/auth/rocket-login/route.ts new file mode 100644 index 00000000..216ad7c5 --- /dev/null +++ b/app/api/auth/rocket-login/route.ts @@ -0,0 +1,104 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { getServerSession } from 'next-auth/next'; +import { authOptions } from '@/app/api/auth/[...nextauth]/route'; +import { getToken } from 'next-auth/jwt'; + +// Helper function to get user token using admin credentials +async function getUserTokenForRocketChat(email: string) { + try { + const baseUrl = process.env.NEXT_PUBLIC_IFRAME_PAROLE_URL?.split('/channel')[0]; + + if (!baseUrl) { + console.error('Failed to get Rocket.Chat base URL'); + return null; + } + + // Admin headers for Rocket.Chat API + const adminHeaders = { + 'X-Auth-Token': process.env.ROCKET_CHAT_TOKEN!, + 'X-User-Id': process.env.ROCKET_CHAT_USER_ID!, + 'Content-Type': 'application/json' + }; + + // Get the username from email + const username = email.split('@')[0]; + + // Get all users to find the current user + const usersResponse = await fetch(`${baseUrl}/api/v1/users.list`, { + method: 'GET', + headers: adminHeaders + }); + + if (!usersResponse.ok) { + console.error('Failed to get users list:', usersResponse.status); + return null; + } + + const usersData = await usersResponse.json(); + + // Find the current user in the list + const currentUser = usersData.users.find((user: any) => + user.username === username || user.emails?.some((email: any) => email.address === email) + ); + + if (!currentUser) { + console.error('User not found in Rocket.Chat users list'); + return null; + } + + // Create a token for the current user + const createTokenResponse = await fetch(`${baseUrl}/api/v1/users.createToken`, { + method: 'POST', + headers: adminHeaders, + body: JSON.stringify({ + userId: currentUser._id + }) + }); + + if (!createTokenResponse.ok) { + console.error('Failed to create user token:', createTokenResponse.status); + return null; + } + + const tokenData = await createTokenResponse.json(); + + return { + authToken: tokenData.data.authToken, + userId: currentUser._id + }; + } catch (error) { + console.error('Error getting user token for Rocket.Chat:', error); + return null; + } +} + +export async function GET(request: NextRequest) { + try { + // Get the current user session + const session = await getServerSession(authOptions); + + if (!session?.user?.email) { + return NextResponse.json({ error: 'User not authenticated' }, { status: 401 }); + } + + // Get a token for Rocket.Chat + const rocketChatTokens = await getUserTokenForRocketChat(session.user.email); + + if (!rocketChatTokens) { + return NextResponse.json({ error: 'Failed to obtain Rocket.Chat tokens' }, { status: 500 }); + } + + // Now we have the tokens, but we can't update the session directly + // The client needs to make a new auth call to refresh its JWT tokens + + // Return the tokens to the client + return NextResponse.json({ + success: true, + rocketChatToken: rocketChatTokens.authToken, + rocketChatUserId: rocketChatTokens.userId + }); + } catch (error) { + console.error('Error in Rocket.Chat login API:', error); + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); + } +} \ No newline at end of file diff --git a/app/components/rocket-auth.tsx b/app/components/rocket-auth.tsx new file mode 100644 index 00000000..d1f3fb32 --- /dev/null +++ b/app/components/rocket-auth.tsx @@ -0,0 +1,50 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { useSession } from 'next-auth/react'; + +export function RocketChatAuth() { + const { data: session } = useSession(); + const [isAuthenticated, setIsAuthenticated] = useState(false); + + useEffect(() => { + async function authenticateWithRocketChat() { + if (!session?.user?.email) return; + + try { + // Call our API to get Rocket.Chat tokens + const response = await fetch('/api/auth/rocket-login'); + + if (!response.ok) { + console.error('Failed to authenticate with Rocket.Chat'); + return; + } + + const data = await response.json(); + + if (data.rocketChatToken && data.rocketChatUserId) { + // Store tokens in cookies that can be accessed by the Rocket.Chat iframe + // Note: These cookies need to have proper domain settings to be accessible + document.cookie = `rc_token=${data.rocketChatToken}; path=/; SameSite=None; Secure`; + document.cookie = `rc_uid=${data.rocketChatUserId}; path=/; SameSite=None; Secure`; + + // Also store in localStorage which Rocket.Chat might check + localStorage.setItem('Meteor.loginToken', data.rocketChatToken); + localStorage.setItem('Meteor.userId', data.rocketChatUserId); + + console.log('Successfully authenticated with Rocket.Chat'); + setIsAuthenticated(true); + } + } catch (error) { + console.error('Error authenticating with Rocket.Chat:', error); + } + } + + authenticateWithRocketChat(); + }, [session]); + + // This component doesn't render anything visible + return null; +} + +export default RocketChatAuth; \ No newline at end of file diff --git a/app/parole/page.tsx b/app/parole/page.tsx index 07a73091..127ebc5f 100644 --- a/app/parole/page.tsx +++ b/app/parole/page.tsx @@ -2,6 +2,7 @@ import { getServerSession } from "next-auth/next"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { redirect } from "next/navigation"; import { ResponsiveIframe } from "@/app/components/responsive-iframe"; +import RocketChatAuth from "@/app/components/rocket-auth"; export default async function Page() { const session = await getServerSession(authOptions); @@ -15,6 +16,8 @@ export default async function Page() { return (
+ +