auth flow
This commit is contained in:
parent
ef4f73ad9e
commit
279a5a34ab
104
app/api/auth/rocket-login/route.ts
Normal file
104
app/api/auth/rocket-login/route.ts
Normal file
@ -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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
50
app/components/rocket-auth.tsx
Normal file
50
app/components/rocket-auth.tsx
Normal file
@ -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;
|
||||||
@ -2,6 +2,7 @@ import { getServerSession } from "next-auth/next";
|
|||||||
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
|
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { ResponsiveIframe } from "@/app/components/responsive-iframe";
|
import { ResponsiveIframe } from "@/app/components/responsive-iframe";
|
||||||
|
import RocketChatAuth from "@/app/components/rocket-auth";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const session = await getServerSession(authOptions);
|
const session = await getServerSession(authOptions);
|
||||||
@ -15,6 +16,8 @@ export default async function Page() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="w-full h-screen bg-black">
|
<main className="w-full h-screen bg-black">
|
||||||
|
<RocketChatAuth />
|
||||||
|
|
||||||
<div className="w-full h-full px-4 pt-12 pb-4">
|
<div className="w-full h-full px-4 pt-12 pb-4">
|
||||||
<ResponsiveIframe
|
<ResponsiveIframe
|
||||||
src={proxyUrl}
|
src={proxyUrl}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user