fix: resolve OAuth redirects dynamically using client-facing headers
This commit is contained in:
parent
568fb16a89
commit
f47c9e58ce
5 changed files with 42 additions and 10 deletions
|
|
@ -6,17 +6,19 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||||
import { cookies } from 'next/headers';
|
import { cookies } from 'next/headers';
|
||||||
import { setSessionCookies } from '@/lib/auth/session';
|
import { setSessionCookies } from '@/lib/auth/session';
|
||||||
import { getSettings } from '@/lib/settings';
|
import { getSettings } from '@/lib/settings';
|
||||||
|
import { getRequestBaseUrl } from '@/lib/url';
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
const code = request.nextUrl.searchParams.get('code');
|
const code = request.nextUrl.searchParams.get('code');
|
||||||
const error = request.nextUrl.searchParams.get('error');
|
const error = request.nextUrl.searchParams.get('error');
|
||||||
|
const baseUrl = getRequestBaseUrl(request);
|
||||||
|
|
||||||
if (error || !code) {
|
if (error || !code) {
|
||||||
const errorDesc =
|
const errorDesc =
|
||||||
request.nextUrl.searchParams.get('error_description') || 'Login cancelled';
|
request.nextUrl.searchParams.get('error_description') || 'Login cancelled';
|
||||||
|
|
||||||
return NextResponse.redirect(
|
return NextResponse.redirect(
|
||||||
new URL(`/login?error=${encodeURIComponent(errorDesc)}`, request.url)
|
new URL(`/login?error=${encodeURIComponent(errorDesc)}`, baseUrl)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,7 +34,7 @@ export async function GET(request: NextRequest) {
|
||||||
|
|
||||||
const redirectUri =
|
const redirectUri =
|
||||||
process.env.META_REDIRECT_URI ||
|
process.env.META_REDIRECT_URI ||
|
||||||
'https://admanager.seureview.com.br/api/auth/callback';
|
new URL('/api/auth/callback', baseUrl).toString();
|
||||||
|
|
||||||
if (!appId || !appSecret) {
|
if (!appId || !appSecret) {
|
||||||
return NextResponse.redirect(
|
return NextResponse.redirect(
|
||||||
|
|
@ -40,7 +42,7 @@ export async function GET(request: NextRequest) {
|
||||||
`/login?error=${encodeURIComponent(
|
`/login?error=${encodeURIComponent(
|
||||||
'Credenciais Meta não configuradas no sistema.'
|
'Credenciais Meta não configuradas no sistema.'
|
||||||
)}`,
|
)}`,
|
||||||
request.url
|
baseUrl
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -96,14 +98,14 @@ export async function GET(request: NextRequest) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 5. Redirect to dashboard
|
// 5. Redirect to dashboard
|
||||||
return NextResponse.redirect(new URL('/dashboard', request.url));
|
return NextResponse.redirect(new URL('/dashboard', baseUrl));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[Auth] OAuth error:', err);
|
console.error('[Auth] OAuth error:', err);
|
||||||
|
|
||||||
return NextResponse.redirect(
|
return NextResponse.redirect(
|
||||||
new URL(
|
new URL(
|
||||||
`/login?error=${encodeURIComponent('Erro na autenticação')}`,
|
`/login?error=${encodeURIComponent('Erro na autenticação')}`,
|
||||||
request.url
|
baseUrl
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,11 @@
|
||||||
import { NextRequest, NextResponse } from 'next/server';
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
import { cookies } from 'next/headers';
|
import { cookies } from 'next/headers';
|
||||||
import { clearSessionCookies } from '@/lib/auth/session';
|
import { clearSessionCookies } from '@/lib/auth/session';
|
||||||
|
import { getRequestBaseUrl } from '@/lib/url';
|
||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
const cookieStore = await cookies();
|
const cookieStore = await cookies();
|
||||||
clearSessionCookies(cookieStore);
|
clearSessionCookies(cookieStore);
|
||||||
return NextResponse.redirect(new URL('/login', request.url));
|
const baseUrl = getRequestBaseUrl(request);
|
||||||
|
return NextResponse.redirect(new URL('/login', baseUrl));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
// OAuth — Redirect to Meta Login
|
// OAuth — Redirect to Meta Login
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
import { NextResponse } from 'next/server';
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
import { getSettings } from '@/lib/settings';
|
import { getSettings } from '@/lib/settings';
|
||||||
|
import { getRequestBaseUrl } from '@/lib/url';
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET(request: NextRequest) {
|
||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
|
|
||||||
const appId =
|
const appId =
|
||||||
|
|
@ -14,7 +15,7 @@ export async function GET() {
|
||||||
|
|
||||||
const redirectUri =
|
const redirectUri =
|
||||||
process.env.META_REDIRECT_URI ||
|
process.env.META_REDIRECT_URI ||
|
||||||
'https://admanager.seureview.com.br/api/auth/callback';
|
new URL('/api/auth/callback', getRequestBaseUrl(request)).toString();
|
||||||
|
|
||||||
if (!appId || appId === 'your_meta_app_id') {
|
if (!appId || appId === 'your_meta_app_id') {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
|
|
|
||||||
25
src/lib/url.ts
Normal file
25
src/lib/url.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the correct client-facing base URL (protocol + host) of the request.
|
||||||
|
* Handles reverse proxies by checking standard headers like X-Forwarded-Host and X-Forwarded-Proto.
|
||||||
|
*/
|
||||||
|
export function getRequestBaseUrl(request: NextRequest): URL {
|
||||||
|
const forwardedHost = request.headers.get('x-forwarded-host');
|
||||||
|
const forwardedProto = request.headers.get('x-forwarded-proto') || 'https';
|
||||||
|
|
||||||
|
if (forwardedHost) {
|
||||||
|
const host = forwardedHost.split(',')[0].trim();
|
||||||
|
const proto = forwardedProto.split(',')[0].trim();
|
||||||
|
return new URL(`${proto}://${host}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostHeader = request.headers.get('host');
|
||||||
|
if (hostHeader) {
|
||||||
|
// Standard local dev or direct connection
|
||||||
|
const proto = request.headers.get('x-forwarded-proto') || 'http';
|
||||||
|
return new URL(`${proto}://${hostHeader}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new URL(request.url);
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
import { NextRequest, NextResponse } from 'next/server';
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { getRequestBaseUrl } from '@/lib/url';
|
||||||
|
|
||||||
export function middleware(request: NextRequest) {
|
export function middleware(request: NextRequest) {
|
||||||
const { pathname } = request.nextUrl;
|
const { pathname } = request.nextUrl;
|
||||||
|
|
@ -20,7 +21,8 @@ export function middleware(request: NextRequest) {
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
}
|
}
|
||||||
return NextResponse.redirect(new URL('/login', request.url));
|
const baseUrl = getRequestBaseUrl(request);
|
||||||
|
return NextResponse.redirect(new URL('/login', baseUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue