Compare commits
3 Commits
a9a1bf52db
...
3d576f0642
Author | SHA1 | Date | |
---|---|---|---|
3d576f0642 | |||
290d5b0ff2 | |||
a7760a12ce |
@ -2,7 +2,36 @@
|
|||||||
debug
|
debug
|
||||||
}
|
}
|
||||||
|
|
||||||
m040tbaraspi001.de040.corpintra.net, m040tbaraspi001.de040.corpinter.net {
|
# Hauptdomain für die Anwendung
|
||||||
|
m040tbaraspi001.de040.corpintra.net, m040tbaraspi001, localhost {
|
||||||
reverse_proxy myp-rp:3000
|
reverse_proxy myp-rp:3000
|
||||||
tls internal
|
tls internal
|
||||||
|
|
||||||
|
# Erlaube HTTP -> HTTPS Redirects für OAuth
|
||||||
|
@oauth path /auth/login/callback*
|
||||||
|
handle @oauth {
|
||||||
|
header Cache-Control "no-cache"
|
||||||
|
reverse_proxy myp-rp:3000
|
||||||
|
}
|
||||||
|
|
||||||
|
# Allgemeine Header für Sicherheit und Caching
|
||||||
|
header {
|
||||||
|
# Sicherheitsheader
|
||||||
|
Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||||
|
X-Content-Type-Options "nosniff"
|
||||||
|
X-Frame-Options "SAMEORIGIN"
|
||||||
|
Referrer-Policy "strict-origin-when-cross-origin"
|
||||||
|
|
||||||
|
# Cache-Control für statische Assets
|
||||||
|
@static {
|
||||||
|
path *.js *.css *.png *.jpg *.svg *.ico *.woff *.woff2
|
||||||
|
}
|
||||||
|
header @static Cache-Control "public, max-age=86400"
|
||||||
|
|
||||||
|
# Keine Caches für dynamische Inhalte
|
||||||
|
@dynamic {
|
||||||
|
not path *.js *.css *.png *.jpg *.svg *.ico *.woff *.woff2
|
||||||
|
}
|
||||||
|
header @dynamic Cache-Control "no-store, no-cache, must-revalidate"
|
||||||
|
}
|
||||||
}
|
}
|
@ -33,12 +33,30 @@ else
|
|||||||
log "Verwende Standard-Backend-URL: ${BACKEND_URL}"
|
log "Verwende Standard-Backend-URL: ${BACKEND_URL}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Bestimme den Hostnamen für OAuth
|
||||||
|
HOSTNAME=$(hostname)
|
||||||
|
if [[ "$HOSTNAME" == *"m040tbaraspi001"* ]] || [[ "$HOSTNAME" == *"corpintra"* ]]; then
|
||||||
|
FRONTEND_HOSTNAME="m040tbaraspi001.de040.corpintra.net"
|
||||||
|
OAUTH_URL="http://m040tbaraspi001.de040.corpintra.net/auth/login/callback"
|
||||||
|
log "Erkannt: Unternehmens-Hostname: $FRONTEND_HOSTNAME"
|
||||||
|
else
|
||||||
|
FRONTEND_HOSTNAME="$HOSTNAME"
|
||||||
|
OAUTH_URL="http://$HOSTNAME:3000/auth/login/callback"
|
||||||
|
log "Lokaler Hostname: $FRONTEND_HOSTNAME"
|
||||||
|
fi
|
||||||
|
|
||||||
# Erstelle .env.local Datei mit Backend-URL
|
# Erstelle .env.local Datei mit Backend-URL
|
||||||
log "${YELLOW}Erstelle .env.local Datei...${NC}"
|
log "${YELLOW}Erstelle .env.local Datei...${NC}"
|
||||||
cat > "$ENV_FILE" << EOL
|
cat > "$ENV_FILE" << EOL
|
||||||
# Backend API Konfiguration
|
# Backend API Konfiguration
|
||||||
NEXT_PUBLIC_API_URL=${BACKEND_URL}
|
NEXT_PUBLIC_API_URL=${BACKEND_URL}
|
||||||
|
|
||||||
|
# Frontend-URL für OAuth Callback
|
||||||
|
NEXT_PUBLIC_FRONTEND_URL=http://${FRONTEND_HOSTNAME}
|
||||||
|
|
||||||
|
# Explizite OAuth Callback URL für GitHub
|
||||||
|
NEXT_PUBLIC_OAUTH_CALLBACK_URL=${OAUTH_URL}
|
||||||
|
|
||||||
# OAuth Konfiguration (falls nötig)
|
# OAuth Konfiguration (falls nötig)
|
||||||
OAUTH_CLIENT_ID=client_id
|
OAUTH_CLIENT_ID=client_id
|
||||||
OAUTH_CLIENT_SECRET=client_secret
|
OAUTH_CLIENT_SECRET=client_secret
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { lucia } from "@/server/auth";
|
import { lucia } from "@/server/auth";
|
||||||
import { type GitHubUserResult, github } from "@/server/auth/oauth";
|
import { type GitHubUserResult, github, isValidCallbackHost } from "@/server/auth/oauth";
|
||||||
|
import { ALLOWED_CALLBACK_HOSTS, OAUTH_CALLBACK_URL } from "@/utils/api-config";
|
||||||
import { db } from "@/server/db";
|
import { db } from "@/server/db";
|
||||||
import { users } from "@/server/db/schema";
|
import { users } from "@/server/db/schema";
|
||||||
import { OAuth2RequestError } from "arctic";
|
import { OAuth2RequestError } from "arctic";
|
||||||
@ -21,11 +22,17 @@ export async function GET(request: Request): Promise<Response> {
|
|||||||
const code = url.searchParams.get("code");
|
const code = url.searchParams.get("code");
|
||||||
const state = url.searchParams.get("state");
|
const state = url.searchParams.get("state");
|
||||||
const storedState = cookies().get("github_oauth_state")?.value ?? null;
|
const storedState = cookies().get("github_oauth_state")?.value ?? null;
|
||||||
|
|
||||||
|
// Log für Debugging
|
||||||
|
console.log("OAuth Callback erhalten:", url.toString());
|
||||||
|
console.log("Callback URL Validierung:", isValidCallbackHost(url.toString()));
|
||||||
|
console.log("Erlaubte Hosts:", ALLOWED_CALLBACK_HOSTS);
|
||||||
|
|
||||||
if (!code || !state || !storedState || state !== storedState) {
|
if (!code || !state || !storedState || state !== storedState) {
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
status_text: "Something is wrong",
|
status_text: "Ungültiger OAuth-Callback",
|
||||||
data: { code, state, storedState },
|
data: { code, state, storedState, url: url.toString() },
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
status: 400,
|
status: 400,
|
||||||
@ -34,7 +41,12 @@ export async function GET(request: Request): Promise<Response> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const tokens = await github.validateAuthorizationCode(code);
|
// Verwende die zentral definierte Callback-URL für konsistente Validierung
|
||||||
|
const tokens = await github.validateAuthorizationCode(code, OAUTH_CALLBACK_URL);
|
||||||
|
|
||||||
|
// Log zur Fehlersuche
|
||||||
|
console.log(`GitHub OAuth Token-Validierung mit Callback-URL: ${OAUTH_CALLBACK_URL}`);
|
||||||
|
|
||||||
const githubUserResponse = await fetch("https://git.i.mercedes-benz.com/api/v3/user", {
|
const githubUserResponse = await fetch("https://git.i.mercedes-benz.com/api/v3/user", {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${tokens.accessToken}`,
|
Authorization: `Bearer ${tokens.accessToken}`,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { github } from "@/server/auth/oauth";
|
import { github } from "@/server/auth/oauth";
|
||||||
|
import { OAUTH_CALLBACK_URL } from "@/utils/api-config";
|
||||||
import { generateState } from "arctic";
|
import { generateState } from "arctic";
|
||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
|
|
||||||
@ -6,8 +7,11 @@ export const dynamic = "force-dynamic";
|
|||||||
|
|
||||||
export async function GET(): Promise<Response> {
|
export async function GET(): Promise<Response> {
|
||||||
const state = generateState();
|
const state = generateState();
|
||||||
|
|
||||||
|
// Verwende die zentral definierte Callback-URL
|
||||||
const url = await github.createAuthorizationURL(state, {
|
const url = await github.createAuthorizationURL(state, {
|
||||||
scopes: ["user"],
|
scopes: ["user"],
|
||||||
|
redirectURI: OAUTH_CALLBACK_URL,
|
||||||
});
|
});
|
||||||
const ONE_HOUR = 60 * 60;
|
const ONE_HOUR = 60 * 60;
|
||||||
|
|
||||||
@ -19,5 +23,9 @@ export async function GET(): Promise<Response> {
|
|||||||
sameSite: "lax",
|
sameSite: "lax",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Log zur Fehlersuche
|
||||||
|
console.log(`GitHub OAuth redirect zu: ${url.toString()}`);
|
||||||
|
console.log(`Verwendete Callback-URL: ${OAUTH_CALLBACK_URL}`);
|
||||||
|
|
||||||
return Response.redirect(url);
|
return Response.redirect(url);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,47 @@
|
|||||||
import { GitHub } from "arctic";
|
import { GitHub } from "arctic";
|
||||||
|
import { ALLOWED_CALLBACK_HOSTS, FRONTEND_URL, OAUTH_CALLBACK_URL } from "@/utils/api-config";
|
||||||
|
|
||||||
export const github = new GitHub(process.env.OAUTH_CLIENT_ID as string, process.env.OAUTH_CLIENT_SECRET as string, {
|
// Helper-Funktion, um die passende Callback-URL zu bestimmen
|
||||||
enterpriseDomain: "https://git.i.mercedes-benz.com",
|
const getCallbackUrl = () => {
|
||||||
});
|
// Wenn eine spezifische OAuth-Callback-URL definiert ist, verwende diese
|
||||||
|
if (process.env.NEXT_PUBLIC_OAUTH_CALLBACK_URL) {
|
||||||
|
console.log("Verwende konfigurierte OAuth Callback URL:", process.env.NEXT_PUBLIC_OAUTH_CALLBACK_URL);
|
||||||
|
return process.env.NEXT_PUBLIC_OAUTH_CALLBACK_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Für spezifischen Unternehmens-Hostname
|
||||||
|
if (FRONTEND_URL.includes('corpintra.net') || FRONTEND_URL.includes('m040tbaraspi001')) {
|
||||||
|
const url = `http://m040tbaraspi001.de040.corpintra.net/auth/login/callback`;
|
||||||
|
console.log("Verwende Unternehmens-Hostname für OAuth Callback:", url);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback für lokale Entwicklung
|
||||||
|
console.log("Verwende Standard OAuth Callback URL:", OAUTH_CALLBACK_URL);
|
||||||
|
return OAUTH_CALLBACK_URL;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Erstelle GitHub OAuth-Client mit expliziter Redirect-URI
|
||||||
|
export const github = new GitHub(
|
||||||
|
process.env.OAUTH_CLIENT_ID as string,
|
||||||
|
process.env.OAUTH_CLIENT_SECRET as string,
|
||||||
|
{
|
||||||
|
enterpriseDomain: "https://git.i.mercedes-benz.com",
|
||||||
|
redirectURI: getCallbackUrl(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Hilfsfunktion zur Validierung von OAuth-Callbacks
|
||||||
|
export function isValidCallbackHost(url: string): boolean {
|
||||||
|
try {
|
||||||
|
const parsedUrl = new URL(url);
|
||||||
|
return ALLOWED_CALLBACK_HOSTS.some(host => parsedUrl.hostname === host ||
|
||||||
|
parsedUrl.hostname.includes(host));
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Ungültige URL beim Validieren des Callback-Hosts:", url, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface GitHubUserResult {
|
export interface GitHubUserResult {
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -1,9 +1,51 @@
|
|||||||
// Basis-URL für Backend-API
|
// Basis-URL für Backend-API
|
||||||
export const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://192.168.0.105:5000";
|
export const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://192.168.0.105:5000";
|
||||||
|
|
||||||
|
// Frontend-URL für Callbacks - unterstützt mehrere Domains
|
||||||
|
const getFrontendUrl = () => {
|
||||||
|
// Priorität 1: Explizit gesetzte Umgebungsvariable
|
||||||
|
if (process.env.NEXT_PUBLIC_FRONTEND_URL) {
|
||||||
|
return process.env.NEXT_PUBLIC_FRONTEND_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Priorität 2: Spezifischer Hostname für das Netzwerk
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
// Im Browser: Prüfen auf m040tbaraspi001.de040.corpintra.net
|
||||||
|
const hostname = window.location.hostname;
|
||||||
|
if (hostname === 'm040tbaraspi001' ||
|
||||||
|
hostname === 'm040tbaraspi001.de040.corpintra.net' ||
|
||||||
|
hostname.includes('corpintra.net')) {
|
||||||
|
return `http://${hostname}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Priorität 3: Default für Localhost
|
||||||
|
return "http://localhost:3000";
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FRONTEND_URL = getFrontendUrl();
|
||||||
|
|
||||||
|
// OAuth Callback URL - muss exakt mit der registrierten URL in GitHub übereinstimmen
|
||||||
|
export const OAUTH_CALLBACK_URL = process.env.NEXT_PUBLIC_OAUTH_CALLBACK_URL ||
|
||||||
|
`${FRONTEND_URL}/auth/login/callback`;
|
||||||
|
|
||||||
|
// Liste der erlaubten Hostnamen für OAuth-Callbacks
|
||||||
|
export const ALLOWED_CALLBACK_HOSTS = [
|
||||||
|
'localhost',
|
||||||
|
'm040tbaraspi001',
|
||||||
|
'm040tbaraspi001.de040.corpintra.net',
|
||||||
|
'192.168.0.105'
|
||||||
|
];
|
||||||
|
|
||||||
// Endpunkte für die verschiedenen Ressourcen
|
// Endpunkte für die verschiedenen Ressourcen
|
||||||
export const API_ENDPOINTS = {
|
export const API_ENDPOINTS = {
|
||||||
PRINTERS: `${API_BASE_URL}/api/printers`,
|
PRINTERS: `${API_BASE_URL}/api/printers`,
|
||||||
JOBS: `${API_BASE_URL}/api/jobs`,
|
JOBS: `${API_BASE_URL}/api/jobs`,
|
||||||
USERS: `${API_BASE_URL}/api/users`,
|
USERS: `${API_BASE_URL}/api/users`,
|
||||||
|
|
||||||
|
// OAuth-spezifische Endpunkte
|
||||||
|
AUTH: {
|
||||||
|
LOGIN: `${API_BASE_URL}/api/auth/login`,
|
||||||
|
CALLBACK: `${API_BASE_URL}/api/auth/callback`,
|
||||||
|
}
|
||||||
};
|
};
|
@ -96,12 +96,30 @@ configure_backend_url() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
# Bestimme den Hostnamen für OAuth
|
||||||
|
HOSTNAME=$(hostname)
|
||||||
|
if [[ "$HOSTNAME" == *"m040tbaraspi001"* ]] || [[ "$HOSTNAME" == *"corpintra"* ]]; then
|
||||||
|
FRONTEND_HOSTNAME="m040tbaraspi001.de040.corpintra.net"
|
||||||
|
OAUTH_URL="http://m040tbaraspi001.de040.corpintra.net/auth/login/callback"
|
||||||
|
log "Erkannt: Unternehmens-Hostname: $FRONTEND_HOSTNAME"
|
||||||
|
else
|
||||||
|
FRONTEND_HOSTNAME="$HOSTNAME"
|
||||||
|
OAUTH_URL="http://$HOSTNAME:3000/auth/login/callback"
|
||||||
|
log "Lokaler Hostname: $FRONTEND_HOSTNAME"
|
||||||
|
fi
|
||||||
|
|
||||||
# Erstelle .env.local-Datei manuell
|
# Erstelle .env.local-Datei manuell
|
||||||
log "Erstelle .env.local-Datei manuell..."
|
log "Erstelle .env.local-Datei manuell..."
|
||||||
cat > "$FRONTEND_DIR/.env.local" << EOL
|
cat > "$FRONTEND_DIR/.env.local" << EOL
|
||||||
# Backend API Konfiguration
|
# Backend API Konfiguration
|
||||||
NEXT_PUBLIC_API_URL=${backend_url}
|
NEXT_PUBLIC_API_URL=${backend_url}
|
||||||
|
|
||||||
|
# Frontend-URL für OAuth Callback
|
||||||
|
NEXT_PUBLIC_FRONTEND_URL=http://${FRONTEND_HOSTNAME}
|
||||||
|
|
||||||
|
# Explizite OAuth Callback URL für GitHub
|
||||||
|
NEXT_PUBLIC_OAUTH_CALLBACK_URL=${OAUTH_URL}
|
||||||
|
|
||||||
# OAuth Konfiguration (falls nötig)
|
# OAuth Konfiguration (falls nötig)
|
||||||
OAUTH_CLIENT_ID=client_id
|
OAUTH_CLIENT_ID=client_id
|
||||||
OAUTH_CLIENT_SECRET=client_secret
|
OAUTH_CLIENT_SECRET=client_secret
|
||||||
@ -241,6 +259,8 @@ services:
|
|||||||
container_name: ${CONTAINER_NAME}
|
container_name: ${CONTAINER_NAME}
|
||||||
environment:
|
environment:
|
||||||
- NEXT_PUBLIC_API_URL=${BACKEND_URL}
|
- NEXT_PUBLIC_API_URL=${BACKEND_URL}
|
||||||
|
- NEXT_PUBLIC_FRONTEND_URL=http://${FRONTEND_HOSTNAME}
|
||||||
|
- NEXT_PUBLIC_OAUTH_CALLBACK_URL=${OAUTH_URL}
|
||||||
- OAUTH_CLIENT_ID=client_id
|
- OAUTH_CLIENT_ID=client_id
|
||||||
- OAUTH_CLIENT_SECRET=client_secret
|
- OAUTH_CLIENT_SECRET=client_secret
|
||||||
ports:
|
ports:
|
||||||
@ -302,6 +322,8 @@ start_container_run() {
|
|||||||
if ! docker run -d --name "$CONTAINER_NAME" \
|
if ! docker run -d --name "$CONTAINER_NAME" \
|
||||||
-p 3000:3000 \
|
-p 3000:3000 \
|
||||||
-e "NEXT_PUBLIC_API_URL=$BACKEND_URL" \
|
-e "NEXT_PUBLIC_API_URL=$BACKEND_URL" \
|
||||||
|
-e "NEXT_PUBLIC_FRONTEND_URL=http://${FRONTEND_HOSTNAME}" \
|
||||||
|
-e "NEXT_PUBLIC_OAUTH_CALLBACK_URL=${OAUTH_URL}" \
|
||||||
-e "OAUTH_CLIENT_ID=client_id" \
|
-e "OAUTH_CLIENT_ID=client_id" \
|
||||||
-e "OAUTH_CLIENT_SECRET=client_secret" \
|
-e "OAUTH_CLIENT_SECRET=client_secret" \
|
||||||
-v "$DB_VOLUME_DIR:/app/db" \
|
-v "$DB_VOLUME_DIR:/app/db" \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user