From f5a5793309d9d479e77bee105b74ae67f22333da Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Fri, 8 May 2026 11:49:24 +0200
Subject: [PATCH] dns switch poweron-center to poweron.swiss
---
.github/workflows/poweron_nyla_int.yml | 2 +-
.github/workflows/poweron_nyla_main.yml | 2 +-
.gitignore | 6 +-
README.md | 31 ++--
config/.env.dev | 34 -----
config/.env.int | 33 ----
config/.env.prod | 33 ----
config/env-poweron-nyla-dev.env | 6 +
config/env-poweron-nyla-int.env | 6 +
config/env-poweron-nyla-prod.env | 6 +
env.d.ts | 15 +-
package-lock.json | 36 -----
package.json | 2 -
src/App.tsx | 3 -
src/hooks/useAuthentication.ts | 193 +++---------------------
src/hooks/useUsers.ts | 32 +---
src/pages/Register.tsx | 4 +-
src/providers/auth/AuthProvider.tsx | 99 ------------
src/providers/auth/ProtectedRoute.tsx | 89 +----------
src/providers/auth/authConfig.ts | 45 ------
20 files changed, 68 insertions(+), 609 deletions(-)
delete mode 100644 config/.env.dev
delete mode 100644 config/.env.int
delete mode 100644 config/.env.prod
create mode 100644 config/env-poweron-nyla-dev.env
create mode 100644 config/env-poweron-nyla-int.env
create mode 100644 config/env-poweron-nyla-prod.env
delete mode 100644 src/providers/auth/AuthProvider.tsx
delete mode 100644 src/providers/auth/authConfig.ts
diff --git a/.github/workflows/poweron_nyla_int.yml b/.github/workflows/poweron_nyla_int.yml
index c315780..7998da8 100644
--- a/.github/workflows/poweron_nyla_int.yml
+++ b/.github/workflows/poweron_nyla_int.yml
@@ -27,7 +27,7 @@ jobs:
- name: Copy integration environment file
run: |
- cp config/.env.int .env
+ cp config/env-poweron-nyla-int.env .env
- name: Install dependencies
run: |
diff --git a/.github/workflows/poweron_nyla_main.yml b/.github/workflows/poweron_nyla_main.yml
index 50877ea..1e0c31e 100644
--- a/.github/workflows/poweron_nyla_main.yml
+++ b/.github/workflows/poweron_nyla_main.yml
@@ -27,7 +27,7 @@ jobs:
- name: Copy production environment file
run: |
- cp config/.env.prod .env
+ cp config/env-poweron-nyla-prod.env .env
- name: Install dependencies
run: |
diff --git a/.gitignore b/.gitignore
index f0524e8..b7aac00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,7 +30,5 @@ dist-ssr
.cursorignore
-# Keep environment template files in config/
-!config/.env.dev
-!config/.env.int
-!config/.env.prod
\ No newline at end of file
+# Keep environment files in config/ (naming: env-.env)
+!config/env-*.env
\ No newline at end of file
diff --git a/README.md b/README.md
index 97574fe..f792e3a 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,9 @@
```mermaid
graph TB
%% Environment Files
- ENV_DEV[".env.dev
Development"]
- ENV_PROD[".env.prod
Production"]
- ENV_INT[".env.int
Integration"]
+ ENV_DEV["env-poweron-nyla-dev.env
Development"]
+ ENV_PROD["env-poweron-nyla-prod.env
Production"]
+ ENV_INT["env-poweron-nyla-int.env
Integration"]
%% Configuration System
CONFIG_TS["config.ts
TypeScript Config
(React Frontend)"]
@@ -114,30 +114,25 @@ The app uses a **dual configuration system** to handle environment variables acr
- **Used by:** Express servers and build scripts
### Environment Files
-- **`config/.env.dev`** - Development environment variables
- - **Why:** Separate config for local development with debug settings
- - **How:** Copied to root `.env` by `npm run dev` command
- - **Contains:** Local API URLs, debug flags, dev-specific settings
-- **`config/.env.prod`** - Production environment variables
- - **Why:** Production-specific settings (live API URLs, optimized settings)
- - **How:** Copied to root `.env` by GitHub Actions workflow
- - **Contains:** Production API URLs, security settings, performance configs
+Naming convention: `env-.env` — matches the GitHub Actions workflow that uses it.
-- **`config/.env.int`** - Integration environment variables
- - **Why:** Testing environment that mirrors production but with test data
- - **How:** Copied to root `.env` by integration deployment workflow
- - **Contains:** Staging API URLs, test user credentials, integration settings
+- **`config/env-poweron-nyla-dev.env`** — Local development (localhost gateway)
+- **`config/env-poweron-nyla-int.env`** — Integration (used by `poweron_nyla_int` workflow)
+- **`config/env-poweron-nyla-prod.env`** — Production (used by `poweron_nyla_main` workflow)
+
+Each env is copied to root `.env` at build time (by CI or manually for local dev).
### Usage
```bash
-# Development (loads .env.dev)
+# Local development — copy env then start Vite
+cp config/env-poweron-nyla-dev.env .env
npm run dev
-# Production build (loads .env.prod)
+# Production build (CI copies env-poweron-nyla-prod.env → .env)
npm run build:prod
-# Integration build (loads .env.int)
+# Integration build (CI copies env-poweron-nyla-int.env → .env)
npm run build:int
```
diff --git a/config/.env.dev b/config/.env.dev
deleted file mode 100644
index 89a972a..0000000
--- a/config/.env.dev
+++ /dev/null
@@ -1,34 +0,0 @@
-# Development Environment Configuration
-# Frontend Nyla - Development
-
-# API Configuration
-VITE_API_BASE_URL="http://localhost:8000/"
-VITE_API_TIMEOUT=10000
-
-# Microsoft Entra ID Configuration
-VITE_MICROSOFT_CLIENT_ID=24cd6c8a-b592-4905-a5ba-d5fa9f911154
-VITE_MICROSOFT_TENANT_ID=6a51aaeb-2467-4186-9504-2a05aedc591f
-VITE_ENTRA_CLIENT_SECRET=2iw8Q~jwqG1iacxHopBt5pstu6R45UC1gIQabcbD
-VITE_ENTRA_AUTHORITY=https://login.microsoftonline.com/6a51aaeb-2467-4186-9504-2a05aedc591f
-VITE_ENTRA_REDIRECT_PATH=/auth/callback/
-VITE_ENTRA_REDIRECT_URI=http://localhost:8000/api/msft/auth/callback/
-
-# Application Configuration
-VITE_APP_NAME=PowerOn Nyla dev
-VITE_APP_VERSION=0.0.0
-VITE_APP_ENVIRONMENT=development
-
-# Debug Configuration
-VITE_DEBUG=true
-VITE_LOG_LEVEL=debug
-VITE_ENABLE_CONSOLE_LOGS=true
-
-# Feature Flags
-VITE_ENABLE_ANALYTICS=false
-VITE_ENABLE_ERROR_REPORTING=false
-VITE_ENABLE_PERFORMANCE_MONITORING=false
-
-# Development Server
-VITE_DEV_SERVER_PORT=5176
-VITE_DEV_SERVER_HOST=localhost
-VITE_DEV_SERVER_HTTPS=false
\ No newline at end of file
diff --git a/config/.env.int b/config/.env.int
deleted file mode 100644
index 32874bc..0000000
--- a/config/.env.int
+++ /dev/null
@@ -1,33 +0,0 @@
-# Integration/Test Environment Configuration
-# Frontend Nyla - Integration
-
-# API Configuration
-VITE_API_BASE_URL=https://gateway-int.poweron-center.net
-VITE_API_TIMEOUT=12000
-
-# Microsoft Entra ID Configuration
-VITE_MICROSOFT_CLIENT_ID=24cd6c8a-b592-4905-a5ba-d5fa9f911154
-VITE_MICROSOFT_TENANT_ID=6a51aaeb-2467-4186-9504-2a05aedc591f
-VITE_ENTRA_CLIENT_SECRET=2iw8Q~jwqG1iacxHopBt5pstu6R45UC1gIQabcbD
-VITE_ENTRA_AUTHORITY=https://login.microsoftonline.com/6a51aaeb-2467-4186-9504-2a05aedc591f
-VITE_ENTRA_REDIRECT_PATH=/auth/callback/
-VITE_ENTRA_REDIRECT_URI=https://gateway-int.poweron-center.net/api/msft/auth/callback/
-
-# Application Configuration
-VITE_APP_NAME=Poweron Nyla int
-VITE_APP_VERSION=0.0.0
-VITE_APP_ENVIRONMENT=integration
-
-# Debug Configuration
-VITE_DEBUG=true
-VITE_LOG_LEVEL=info
-VITE_ENABLE_CONSOLE_LOGS=true
-
-# Feature Flags
-VITE_ENABLE_ANALYTICS=true
-VITE_ENABLE_ERROR_REPORTING=true
-VITE_ENABLE_PERFORMANCE_MONITORING=true
-
-# Test Configuration
-VITE_ENABLE_MOCK_DATA=false
-VITE_ENABLE_TEST_MODE=true
diff --git a/config/.env.prod b/config/.env.prod
deleted file mode 100644
index 0db5112..0000000
--- a/config/.env.prod
+++ /dev/null
@@ -1,33 +0,0 @@
-# Production Environment Configuration
-# Frontend Nyla - Production
-
-# API Configuration
-VITE_API_BASE_URL=https://gateway-prod.poweron-center.net
-VITE_API_TIMEOUT=15000
-
-# Microsoft Entra ID Configuration
-VITE_MICROSOFT_CLIENT_ID=24cd6c8a-b592-4905-a5ba-d5fa9f911154
-VITE_MICROSOFT_TENANT_ID=6a51aaeb-2467-4186-9504-2a05aedc591f
-VITE_ENTRA_CLIENT_SECRET=2iw8Q~jwqG1iacxHopBt5pstu6R45UC1gIQabcbD
-VITE_ENTRA_AUTHORITY=https://login.microsoftonline.com/6a51aaeb-2467-4186-9504-2a05aedc591f
-VITE_ENTRA_REDIRECT_PATH=/auth/callback/
-VITE_ENTRA_REDIRECT_URI=https://gateway-prod.poweron-center.net/api/msft/auth/callback/
-
-# Application Configuration
-VITE_APP_NAME=PowerOn Nyla
-VITE_APP_VERSION=0.0.0
-VITE_APP_ENVIRONMENT=production
-
-# Debug Configuration
-VITE_DEBUG=false
-VITE_LOG_LEVEL=error
-VITE_ENABLE_CONSOLE_LOGS=false
-
-# Feature Flags
-VITE_ENABLE_ANALYTICS=true
-VITE_ENABLE_ERROR_REPORTING=true
-VITE_ENABLE_PERFORMANCE_MONITORING=true
-
-# Security Configuration
-VITE_ENABLE_HTTPS=true
-VITE_ENABLE_CSP=true
diff --git a/config/env-poweron-nyla-dev.env b/config/env-poweron-nyla-dev.env
new file mode 100644
index 0000000..a66d513
--- /dev/null
+++ b/config/env-poweron-nyla-dev.env
@@ -0,0 +1,6 @@
+# Environment: poweron-nyla-dev (local development)
+# Consumed by: Vite build (title) + SPA runtime (getApiBaseUrl / getAppName)
+# Auth and secrets live on the gateway — never in frontend env.
+
+VITE_API_BASE_URL="http://localhost:8000/"
+VITE_APP_NAME=PowerOn Nyla dev
diff --git a/config/env-poweron-nyla-int.env b/config/env-poweron-nyla-int.env
new file mode 100644
index 0000000..6655d68
--- /dev/null
+++ b/config/env-poweron-nyla-int.env
@@ -0,0 +1,6 @@
+# Environment: poweron-nyla-int (integration)
+# Consumed by: Vite build (title) + SPA runtime (getApiBaseUrl / getAppName)
+# Auth and secrets live on the gateway — never in frontend env.
+
+VITE_API_BASE_URL=https://gateway-int.poweron.swiss
+VITE_APP_NAME=Poweron Nyla int
diff --git a/config/env-poweron-nyla-prod.env b/config/env-poweron-nyla-prod.env
new file mode 100644
index 0000000..7c3adff
--- /dev/null
+++ b/config/env-poweron-nyla-prod.env
@@ -0,0 +1,6 @@
+# Environment: poweron-nyla-prod (production)
+# Consumed by: Vite build (title) + SPA runtime (getApiBaseUrl / getAppName)
+# Auth and secrets live on the gateway — never in frontend env.
+
+VITE_API_BASE_URL=https://gateway-prod.poweron.swiss
+VITE_APP_NAME=PowerOn Nyla
diff --git a/env.d.ts b/env.d.ts
index 633661e..0533123 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -1,15 +1,6 @@
///
interface ImportMetaEnv {
- readonly VITE_API_URL: string
- readonly VITE_MICROSOFT_CLIENT_ID: string
- readonly VITE_MICROSOFT_TENANT_ID: string
- readonly VITE_ENTRA_CLIENT_SECRET: string
- readonly VITE_ENTRA_AUTHORITY: string
- readonly VITE_ENTRA_REDIRECT_PATH: string
- readonly VITE_ENTRA_REDIRECT_URI: string
- }
-
-interface ImportMeta {
- readonly env: ImportMetaEnv
- }
\ No newline at end of file
+ readonly VITE_API_BASE_URL?: string
+ readonly VITE_APP_NAME?: string
+}
diff --git a/package-lock.json b/package-lock.json
index 60224ca..d1fd27b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,8 +8,6 @@
"name": "frontend_nyla_new",
"version": "0.0.0",
"dependencies": {
- "@azure/msal-browser": "^4.12.0",
- "@azure/msal-react": "^3.0.12",
"@monaco-editor/react": "^4.7.0",
"@types/leaflet": "^1.9.21",
"@xstate/react": "^5.0.0",
@@ -101,40 +99,6 @@
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true
},
- "node_modules/@azure/msal-browser": {
- "version": "4.16.0",
- "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.16.0.tgz",
- "integrity": "sha512-yF8gqyq7tVnYftnrWaNaxWpqhGQXoXpDfwBtL7UCGlIbDMQ1PUJF/T2xCL6NyDNHoO70qp1xU8GjjYTyNIefkw==",
- "license": "MIT",
- "dependencies": {
- "@azure/msal-common": "15.9.0"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/@azure/msal-common": {
- "version": "15.9.0",
- "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.9.0.tgz",
- "integrity": "sha512-lbz/D+C9ixUG3hiZzBLjU79a0+5ZXCorjel3mwXluisKNH0/rOS/ajm8yi4yI9RP5Uc70CAcs9Ipd0051Oh/kA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/@azure/msal-react": {
- "version": "3.0.16",
- "resolved": "https://registry.npmjs.org/@azure/msal-react/-/msal-react-3.0.16.tgz",
- "integrity": "sha512-fIFc3z9UrHoOCG4rApNWMRr83DnQlo+CHfLSPNBQa4rndIkr+XYBpdYDqlzqtmikRf3A+CYNVOQ+lQX6jM0zdw==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@azure/msal-browser": "^4.16.0",
- "react": "^16.8.0 || ^17 || ^18 || ^19"
- }
- },
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
diff --git a/package.json b/package.json
index 2145710..cd3e78e 100644
--- a/package.json
+++ b/package.json
@@ -18,8 +18,6 @@
"test:coverage": "vitest run --coverage"
},
"dependencies": {
- "@azure/msal-browser": "^4.12.0",
- "@azure/msal-react": "^3.0.12",
"@monaco-editor/react": "^4.7.0",
"@types/leaflet": "^1.9.21",
"@xstate/react": "^5.0.0",
diff --git a/src/App.tsx b/src/App.tsx
index c81e8fb..499bb37 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -25,7 +25,6 @@ import Reset from './pages/Reset';
import { InvitePage } from './pages/InvitePage';
// Providers
-import { AuthProvider } from './providers/auth/AuthProvider';
import { ProtectedRoute } from './providers/auth/ProtectedRoute';
import { LanguageProvider } from './providers/language/LanguageContext';
import { ToastProvider } from './contexts/ToastContext';
@@ -71,7 +70,6 @@ function App() {
return (
-
@@ -240,7 +238,6 @@ function App() {
-
);
}
diff --git a/src/hooks/useAuthentication.ts b/src/hooks/useAuthentication.ts
index a67bcac..fb901ba 100644
--- a/src/hooks/useAuthentication.ts
+++ b/src/hooks/useAuthentication.ts
@@ -1,15 +1,12 @@
import { useState } from 'react';
-import { useMsal } from '@azure/msal-react';
import api from '../api';
-import { useApiRequest } from './useApi';
import { getApiBaseUrl } from '../../config/config';
import { setUserDataCache, clearUserDataCache, type CachedUserData } from '../utils/userCache';
import {
loginApi,
fetchCurrentUserApi,
registerApi,
- registerWithMsalApi,
checkUsernameAvailabilityApi,
logoutApi,
requestPasswordResetApi,
@@ -18,7 +15,6 @@ import {
type RegisterResponse,
type UsernameAvailabilityResponse,
type RegisterData,
- type MsalRegisterData,
type PasswordResetRequestResponse,
type PasswordResetResponse
} from '../api/authApi';
@@ -408,48 +404,6 @@ export function useGoogleAuth() {
};
}
-// Microsoft Registration
-export function useMsalRegister() {
- const { instance, accounts } = useMsal();
- const { request, isLoading, error } = useApiRequest();
-
- const registerWithMsal = async (): Promise => {
- try {
- if (!accounts || accounts.length === 0) {
- // If not signed in with Microsoft, sign in first
- await instance.loginPopup({
- scopes: ['user.read']
- });
- }
-
- // Get the current account
- const currentAccount = instance.getAllAccounts()[0];
- if (!currentAccount) {
- throw new Error('No Microsoft account found');
- }
-
- // Prepare user data from Microsoft account
- const userData: MsalRegisterData = {
- username: currentAccount.username,
- email: currentAccount.username,
- fullName: currentAccount.name || currentAccount.username,
- language: 'de'
- };
-
- // Register the user through our backend
- return await registerWithMsalApi(request, userData);
- } catch (error: any) {
- throw error;
- }
- };
-
- return {
- registerWithMsal,
- error,
- isLoading
- };
-}
-
// Username availability check
export function useUsernameAvailability() {
const [isChecking, setIsChecking] = useState(false);
@@ -568,145 +522,32 @@ export function useLogout() {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
+ const _clearLocalState = () => {
+ clearUserDataCache();
+ localStorage.removeItem('authToken');
+ sessionStorage.clear();
+ document.cookie.split(";").forEach((c) => {
+ const name = c.split("=")[0].trim();
+ if (name) {
+ document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
+ }
+ });
+ };
+
const logout = async (): Promise => {
setIsLoading(true);
setError(null);
try {
- // Call logout endpoint to clear JWT tokens on server
await logoutApi();
-
-
-
- // CRITICAL: Wait for browser to process Set-Cookie headers from logout response
- // This gives the browser time to clear httpOnly cookies before redirect
+ // Give browser time to process Set-Cookie headers from logout response
await new Promise(resolve => setTimeout(resolve, 1000));
-
- // Clear user data cache from sessionStorage
- clearUserDataCache();
-
- // Clear auth authority from sessionStorage
- sessionStorage.removeItem('auth_authority');
-
- // Clear MSAL cache tokens from localStorage
- // MSAL stores tokens with keys starting with 'msal.'
- const keysToRemove = [];
- for (let i = 0; i < localStorage.length; i++) {
- const key = localStorage.key(i);
- if (key && (
- key.startsWith('msal.') ||
- key === 'auth_token' ||
- key === 'refresh_token' ||
- key.includes('token') ||
- key.includes('auth') ||
- key.includes('msal')
- )) {
- keysToRemove.push(key);
- }
- }
- keysToRemove.forEach(key => {
-
- localStorage.removeItem(key);
- });
-
- // Clear ALL MSAL cache data (including account keys, token keys, version)
- const msalKeysToRemove = [];
- for (let i = 0; i < localStorage.length; i++) {
- const key = localStorage.key(i);
- if (key && key.startsWith('msal.')) {
- msalKeysToRemove.push(key);
- }
- }
- msalKeysToRemove.forEach(key => {
-
- localStorage.removeItem(key);
- });
-
- // Clear sessionStorage as well (CSRF tokens, etc.)
- sessionStorage.clear();
-
- // Clear cookies as backup (in case backend doesn't clear them properly)
- // Note: This only works for cookies that are accessible to JavaScript
-
-
- const cookies = document.cookie.split(";");
-
-
- cookies.forEach(function(c) {
- const cookieName = c.split("=")[0].trim();
-
-
- if (cookieName === 'auth_token' || cookieName === 'refresh_token' || cookieName.includes('token') || cookieName.includes('msal')) {
-
- document.cookie = cookieName + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
- }
- });
-
-
-
- // Redirect to login page
- window.location.href = '/login?logout=true';
- } catch (error: any) {
- let errorMessage = 'Logout failed';
-
- if (error.response) {
- errorMessage = error.response.data?.detail || errorMessage;
- }
-
- setError(errorMessage);
-
- // Even if logout fails on server, clear local data and redirect
- clearUserDataCache();
- sessionStorage.removeItem('auth_authority');
-
- // Clear MSAL cache tokens from localStorage
- const keysToRemove = [];
- for (let i = 0; i < localStorage.length; i++) {
- const key = localStorage.key(i);
- if (key && (
- key.startsWith('msal.') ||
- key === 'auth_token' ||
- key === 'refresh_token' ||
- key.includes('token') ||
- key.includes('auth') ||
- key.includes('msal')
- )) {
- keysToRemove.push(key);
- }
- }
- keysToRemove.forEach(key => {
-
- localStorage.removeItem(key);
- });
-
- // Clear ALL MSAL cache data (including account keys, token keys, version)
- const msalKeysToRemove = [];
- for (let i = 0; i < localStorage.length; i++) {
- const key = localStorage.key(i);
- if (key && key.startsWith('msal.')) {
- msalKeysToRemove.push(key);
- }
- }
- msalKeysToRemove.forEach(key => {
-
- localStorage.removeItem(key);
- });
-
- // Clear sessionStorage as well
- sessionStorage.clear();
-
- // Clear cookies as backup (in case backend doesn't clear them properly)
- document.cookie.split(";").forEach(function(c) {
- const cookieName = c.split("=")[0].trim();
- if (cookieName === 'auth_token' || cookieName === 'refresh_token' || cookieName.includes('token') || cookieName.includes('msal')) {
-
- document.cookie = cookieName + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
- }
- });
-
- window.location.href = '/login?logout=true';
+ } catch (err: any) {
+ setError(err.response?.data?.detail || 'Logout failed');
} finally {
+ _clearLocalState();
setIsLoading(false);
+ window.location.href = '/login?logout=true';
}
};
diff --git a/src/hooks/useUsers.ts b/src/hooks/useUsers.ts
index acd7242..7c1c1e4 100644
--- a/src/hooks/useUsers.ts
+++ b/src/hooks/useUsers.ts
@@ -172,36 +172,14 @@ export function useCurrentUser() {
// Clear auth authority from sessionStorage
sessionStorage.removeItem('auth_authority');
- // Optional: clear MSAL browser cache only (PowerOn JWT lives in httpOnly cookies + backend).
- // Do not call msal.logoutRedirect — that signs the user out of Microsoft globally.
- for (let i = localStorage.length - 1; i >= 0; i--) {
- const key = localStorage.key(i);
- if (key && key.startsWith('msal.')) {
- localStorage.removeItem(key);
- }
- }
+ localStorage.removeItem('authToken');
- // Clear cookies as backup (in case backend doesn't clear them properly)
- // Note: This only works for cookies that are accessible to JavaScript
- console.log('🍪 Checking cookies for cleanup...');
- console.log('🍪 All cookies:', document.cookie);
-
- const cookies = document.cookie.split(";");
- console.log('🍪 Cookie count:', cookies.length);
-
- cookies.forEach(function(c) {
- const cookieName = c.split("=")[0].trim();
- console.log('🍪 Checking cookie:', cookieName);
-
- if (cookieName === 'auth_token' || cookieName === 'refresh_token' || cookieName.includes('token') || cookieName.includes('msal')) {
- console.log('🗑️ Clearing cookie:', cookieName);
- document.cookie = cookieName + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
+ document.cookie.split(";").forEach((c) => {
+ const name = c.split("=")[0].trim();
+ if (name) {
+ document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
}
});
-
- console.log('🍪 Cookies after cleanup attempt:', document.cookie);
-
- console.log('✅ Cleanup completed');
// Redirect to login or home page
console.log('🔄 Redirecting to login page...');
diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx
index 05b4a3b..575665f 100644
--- a/src/pages/Register.tsx
+++ b/src/pages/Register.tsx
@@ -3,7 +3,7 @@ import { useNavigate, useLocation } from 'react-router-dom';
import { FaEnvelopeOpenText } from 'react-icons/fa';
import styles from './Register.module.css';
-import { useRegister, useMsalRegister, useUsernameAvailability } from '../hooks/useAuthentication';
+import { useRegister, useUsernameAvailability } from '../hooks/useAuthentication';
import { generateAndStoreCSRFToken } from '../utils/csrfUtils';
import { PENDING_INVITATION_KEY } from './InvitePage';
import { LanguageSelector } from '../components/UiComponents/LanguageSelector';
@@ -21,7 +21,6 @@ function Register() {
const navigate = useNavigate();
const location = useLocation();
const { register, error: registerError, isLoading } = useRegister();
- const { error: msalError } = useMsalRegister();
const { checkAvailability, isChecking, error: availabilityError } = useUsernameAvailability();
const invitationUsername = (location.state as any)?.invitationUsername || '';
const invitationEmail = (location.state as any)?.invitationEmail || '';
@@ -118,7 +117,6 @@ function Register() {
const _getErrorMessage = () => {
if (validationError) return validationError;
if (registerError) return typeof registerError === 'string' ? registerError : t('Registrierung fehlgeschlagen');
- if (msalError) return typeof msalError === 'string' ? msalError : t('Microsoft-Registrierung fehlgeschlagen');
if (availabilityError) return typeof availabilityError === 'string' ? availabilityError : t('Benutzernamen-Prüfung fehlgeschlagen');
return null;
};
diff --git a/src/providers/auth/AuthProvider.tsx b/src/providers/auth/AuthProvider.tsx
deleted file mode 100644
index c433e4b..0000000
--- a/src/providers/auth/AuthProvider.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import {
- AuthenticationResult,
- EventType,
- PublicClientApplication
- } from "@azure/msal-browser";
- import { msalConfig } from "./authConfig";
- import { MsalProvider } from "@azure/msal-react";
- import { ReactNode, useEffect, useState } from "react";
- import { useLanguage } from "../language/LanguageContext";
-
- interface AuthProviderProps {
- children: ReactNode;
- }
-
- export const AuthProvider = ({ children }: AuthProviderProps) => {
- const { t } = useLanguage();
- const [msalInstance, setMsalInstance] = useState(null);
- const [isInitialized, setIsInitialized] = useState(false);
-
-
- useEffect(() => {
- const msalApp = new PublicClientApplication(msalConfig);
-
- const initializeMsal = async () => {
- try {
- // Set event handlers first, so we catch all events
- msalApp.addEventCallback((event) => {
- if (event.eventType === EventType.LOGIN_SUCCESS) {
- const payload = event?.payload as AuthenticationResult;
- if (payload?.account) {
- msalApp.setActiveAccount(payload.account);
- console.log("MSAL login successful");
-
- // Store authentication authority for backend communication
- if (payload.account?.environment) {
- sessionStorage.setItem('auth_authority', payload.account.environment);
- }
-
- console.log('✅ MSAL login successful - tokens will be set in httpOnly cookies by backend');
- }
- } else if (event.eventType === EventType.LOGIN_FAILURE) {
- console.error("MSAL login failed:", event.error);
- }
- });
-
- // Initialize MSAL
- await msalApp.initialize();
- msalApp.enableAccountStorageEvents();
-
- // Handle any redirect response
- const response = await msalApp.handleRedirectPromise();
- if (response) {
- // If we have a response, we've completed a redirect flow
- console.log("MSAL redirect completed successfully");
- if (response.account) {
- msalApp.setActiveAccount(response.account);
-
- // Store authentication authority
- if (response.account.environment) {
- sessionStorage.setItem('auth_authority', response.account.environment);
- }
-
- console.log('✅ MSAL redirect completed - tokens will be set in httpOnly cookies by backend');
- }
- }
-
- // Check for accounts
- const accounts = msalApp.getAllAccounts();
- if (accounts.length > 0) {
- msalApp.setActiveAccount(accounts[0]);
-
- // Store authentication authority for existing accounts
- if (accounts[0].environment) {
- sessionStorage.setItem('auth_authority', accounts[0].environment);
- }
-
- console.log('✅ MSAL account found - tokens will be set in httpOnly cookies by backend');
- }
-
- setMsalInstance(msalApp);
- setIsInitialized(true);
- } catch (err) {
- console.error("MSAL initialization failed", err);
- }
- };
-
- initializeMsal();
- }, []);
-
- if (!isInitialized || !msalInstance) {
- return {t('Authentifizierung wird geladen…')}
;
- }
-
- return {children};
- };
-
- export function useAuthProvider() {
- return { AuthProvider };
- }
\ No newline at end of file
diff --git a/src/providers/auth/ProtectedRoute.tsx b/src/providers/auth/ProtectedRoute.tsx
index 12a57a7..1b9b42a 100644
--- a/src/providers/auth/ProtectedRoute.tsx
+++ b/src/providers/auth/ProtectedRoute.tsx
@@ -1,4 +1,3 @@
-import { useMsal } from "@azure/msal-react";
import { Navigate, useLocation } from "react-router-dom";
import { ReactNode, useEffect, useState } from "react";
import { useLanguage } from "../language/LanguageContext";
@@ -13,110 +12,36 @@ export const ProtectedRoute = ({
redirectPath = "/login"
}: ProtectedRouteProps) => {
const { t } = useLanguage();
- const { accounts } = useMsal();
const location = useLocation();
const [isChecking, setIsChecking] = useState(true);
const [isAuthenticated, setIsAuthenticated] = useState(false);
useEffect(() => {
- const checkAuthentication = async () => {
- try {
- // Check for MSAL authentication
- const hasMsalAccount = accounts.length > 0;
-
- // Check for backend authentication via API call
- let hasBackendAuth = false;
-
- try {
- // Check for authentication authority (httpOnly cookies are handled automatically)
- const authAuthority = sessionStorage.getItem('auth_authority');
- console.log('🔍 Checking auth authority:', authAuthority);
-
- if (authAuthority) {
- hasBackendAuth = true;
- console.log('✅ Authenticated with backend (httpOnly cookies), authority:', authAuthority);
- } else {
- hasBackendAuth = false;
- console.log('❌ No authentication authority found');
- }
- } catch (error) {
- console.log('❌ Backend authentication failed:', error);
- hasBackendAuth = false;
- }
+ const authAuthority = sessionStorage.getItem('auth_authority');
+ setIsAuthenticated(!!authAuthority);
+ setIsChecking(false);
+ }, []);
- // User is authenticated if either method is valid
- const isAuth = hasMsalAccount || hasBackendAuth;
- setIsAuthenticated(isAuth);
-
- console.log('🔐 Authentication status:', {
- hasMsalAccount,
- hasBackendAuth,
- isAuthenticated: isAuth,
- authAuthority: sessionStorage.getItem('auth_authority')
- });
-
- if (hasBackendAuth) {
- console.log('✅ Authenticated with backend cookies');
- } else if (hasMsalAccount) {
- console.log('✅ Authenticated with MSAL');
- } else {
- console.log('❌ No valid authentication found');
- }
- } catch (error) {
- console.error('❌ Error checking authentication:', error);
- setIsAuthenticated(false);
- } finally {
- setIsChecking(false);
- }
- };
-
- // Small delay to ensure MSAL is initialized and localStorage is updated
- const timer = setTimeout(() => {
- checkAuthentication();
- }, 200);
-
- return () => clearTimeout(timer);
- }, [accounts]);
-
- // Re-check authentication when component mounts or accounts change
- // This handles cases where auth_authority is set after initial mount
useEffect(() => {
if (!isChecking) {
- // Double-check authentication state periodically when not initially loading
const recheckTimer = setTimeout(() => {
const authAuthority = sessionStorage.getItem('auth_authority');
- const hasMsalAccount = accounts.length > 0;
- const hasBackendAuth = !!authAuthority;
- const isAuth = hasMsalAccount || hasBackendAuth;
-
- // Only update if authentication state actually changed
+ const isAuth = !!authAuthority;
if (isAuth !== isAuthenticated) {
- console.log('🔄 Authentication state changed, updating...', {
- previous: isAuthenticated,
- current: isAuth,
- authAuthority,
- hasMsalAccount,
- hasBackendAuth
- });
setIsAuthenticated(isAuth);
}
}, 300);
-
return () => clearTimeout(recheckTimer);
}
- }, [isChecking, isAuthenticated, accounts]);
+ }, [isChecking, isAuthenticated]);
- // If still checking, show loading
if (isChecking) {
return {t('Authentifizierung wird geprüft…')}
;
}
- // Check if user is authenticated through either method
if (!isAuthenticated) {
- console.log("No valid authentication found, redirecting to login");
return ;
}
- console.log("User is authenticated, rendering protected content");
return <>{children}>;
-};
\ No newline at end of file
+};
diff --git a/src/providers/auth/authConfig.ts b/src/providers/auth/authConfig.ts
deleted file mode 100644
index a06c7e8..0000000
--- a/src/providers/auth/authConfig.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { LogLevel } from '@azure/msal-browser';
-
-export const msalConfig = {
- auth: {
- clientId: '24cd6c8a-b592-4905-a5ba-d5fa9f911154',
- authority: 'https://login.microsoftonline.com/6a51aaeb-2467-4186-9504-2a05aedc591f/',
- redirectUri: '/',
- postLogoutRedirectUri: '/',
- navigateToLoginRequestUrl: false,
- },
- cache: {
- cacheLocation: 'localStorage',
- storeAuthStateInCookie: false,
- },
- system: {
- loggerOptions: {
- loggerCallback: (level: any, message: any, containsPii: any) => {
- if (containsPii) {
- return;
- }
- switch (level) {
- case LogLevel.Error:
- console.error(message);
- return;
- case LogLevel.Info:
- console.info(message);
- return;
- case LogLevel.Verbose:
- console.debug(message);
- return;
- case LogLevel.Warning:
- console.warn(message);
- return;
- default:
- return;
- }
- },
- },
- },
-};
-
-
-export const loginRequest = {
- scopes: ["openid", "profile", "email", "api://24cd6c8a-b592-4905-a5ba-d5fa9f911154/user_impersonation"],
-};
\ No newline at end of file