bearer
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Deploy Admin Panel / Deploy Admin Panel (push) Waiting to run
Deploy Admin Panel / Admin Panel Verification (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Deploy Admin Panel / Deploy Admin Panel (push) Waiting to run
Deploy Admin Panel / Admin Panel Verification (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
This commit is contained in:
parent
0485a35269
commit
9ca6d9ea4f
3 changed files with 65 additions and 7 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import { useAuthStore } from '@/stores/authStore'
|
||||||
|
|
||||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'https://api.mnemo-cards.online'
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'https://api.mnemo-cards.online'
|
||||||
|
|
||||||
|
|
@ -24,29 +25,72 @@ export const adminApiClient = axios.create({
|
||||||
// Request interceptor to add auth token
|
// Request interceptor to add auth token
|
||||||
const addAuthToken = (config: any) => {
|
const addAuthToken = (config: any) => {
|
||||||
const token = localStorage.getItem('admin_token')
|
const token = localStorage.getItem('admin_token')
|
||||||
|
const isPublicAuthEndpoint =
|
||||||
|
config.url?.includes('/admin/auth/request-code') ||
|
||||||
|
config.url?.includes('/admin/auth/verify-code') ||
|
||||||
|
config.url?.includes('/admin/auth/code-status')
|
||||||
|
|
||||||
if (token && token.trim()) {
|
if (token && token.trim()) {
|
||||||
// Ensure headers object exists
|
// Ensure headers object exists
|
||||||
if (!config.headers) {
|
if (!config.headers) {
|
||||||
config.headers = {}
|
config.headers = {}
|
||||||
}
|
}
|
||||||
config.headers.Authorization = `Bearer ${token.trim()}`
|
const trimmedToken = token.trim()
|
||||||
|
// Set Authorization header - axios will normalize it to lowercase for HTTP
|
||||||
|
// but we use the standard capitalization
|
||||||
|
config.headers['Authorization'] = `Bearer ${trimmedToken}`
|
||||||
|
|
||||||
|
// Debug logging for admin endpoints
|
||||||
|
if (!isPublicAuthEndpoint && config.url?.includes('/admin/')) {
|
||||||
|
console.log('[API Client] Adding auth token to request:', config.url)
|
||||||
|
console.log('[API Client] Token exists, length:', trimmedToken.length)
|
||||||
|
console.log('[API Client] Authorization header set:', config.headers['Authorization']?.substring(0, 30) + '...')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Log warning if token is missing (except for public auth endpoints)
|
// Log error if token is missing (except for public auth endpoints)
|
||||||
const isPublicAuthEndpoint =
|
|
||||||
config.url?.includes('/admin/auth/request-code') ||
|
|
||||||
config.url?.includes('/admin/auth/verify-code')
|
|
||||||
if (!isPublicAuthEndpoint) {
|
if (!isPublicAuthEndpoint) {
|
||||||
console.warn('No admin token found in localStorage for request:', config.url)
|
console.error('[API Client] No admin token found in localStorage for request:', config.url)
|
||||||
|
console.error('[API Client] localStorage.getItem("admin_token"):', localStorage.getItem('admin_token'))
|
||||||
|
console.error('[API Client] All localStorage keys:', Object.keys(localStorage))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flag to prevent multiple logout calls
|
||||||
|
let isLoggingOut = false
|
||||||
|
|
||||||
// Response interceptor for error handling
|
// Response interceptor for error handling
|
||||||
const handleAuthError = (error: any) => {
|
const handleAuthError = (error: any) => {
|
||||||
if (error.response?.status === 401) {
|
if (error.response?.status === 401) {
|
||||||
|
// Check if we're already on login page
|
||||||
|
const currentPath = window.location.pathname
|
||||||
|
const isPublicAuthEndpoint =
|
||||||
|
error.config?.url?.includes('/admin/auth/request-code') ||
|
||||||
|
error.config?.url?.includes('/admin/auth/verify-code') ||
|
||||||
|
error.config?.url?.includes('/admin/auth/code-status')
|
||||||
|
|
||||||
|
// Don't logout for public auth endpoints or if already on login page
|
||||||
|
if (currentPath === '/login' || isPublicAuthEndpoint) {
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent multiple logout calls
|
||||||
|
if (isLoggingOut) {
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoggingOut = true
|
||||||
|
|
||||||
|
// Remove token and update auth store
|
||||||
|
// React Router will automatically redirect to /login when isAuthenticated becomes false
|
||||||
localStorage.removeItem('admin_token')
|
localStorage.removeItem('admin_token')
|
||||||
window.location.href = '/login'
|
useAuthStore.getState().logout()
|
||||||
|
|
||||||
|
// Reset flag after a short delay to allow React Router to handle redirect
|
||||||
|
setTimeout(() => {
|
||||||
|
isLoggingOut = false
|
||||||
|
}, 1000)
|
||||||
}
|
}
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,11 @@ export const useAuthStore = create<AuthStore>()(
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
login: (token: string, user: UserDto) => {
|
login: (token: string, user: UserDto) => {
|
||||||
|
console.log('[AuthStore] Saving token to localStorage, length:', token.length)
|
||||||
localStorage.setItem('admin_token', token)
|
localStorage.setItem('admin_token', token)
|
||||||
|
// Verify it was saved
|
||||||
|
const savedToken = localStorage.getItem('admin_token')
|
||||||
|
console.log('[AuthStore] Token saved, verification:', savedToken ? `Token exists, length: ${savedToken.length}` : 'Token NOT found!')
|
||||||
set({
|
set({
|
||||||
user,
|
user,
|
||||||
token,
|
token,
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,17 @@ Middleware authorizeV2(UserManager userManager, JwtService jwtService) {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Extract Bearer token from Authorization header
|
// Extract Bearer token from Authorization header
|
||||||
|
// Shelf normalizes headers to lowercase, so we check 'authorization'
|
||||||
final authHeader = request.headers['authorization'];
|
final authHeader = request.headers['authorization'];
|
||||||
|
|
||||||
|
// Debug logging for admin endpoints
|
||||||
|
if (normalizedPath.startsWith('/admin/')) {
|
||||||
|
print('[AUTH DEBUG] Path: $normalizedPath');
|
||||||
|
print('[AUTH DEBUG] All headers: ${request.headers}');
|
||||||
|
print('[AUTH DEBUG] Authorization header: $authHeader');
|
||||||
|
print('[AUTH DEBUG] Authorization header type: ${authHeader.runtimeType}');
|
||||||
|
}
|
||||||
|
|
||||||
final hasBearerToken =
|
final hasBearerToken =
|
||||||
authHeader != null && authHeader.startsWith('Bearer ');
|
authHeader != null && authHeader.startsWith('Bearer ');
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue