fix(OIDC): redirect to frontend, jwt, and callback handling
This commit is contained in:
parent
a23edca938
commit
943a3eefae
|
|
@ -58,7 +58,7 @@ function App(): React.ReactElement {
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/login" element={!user ? <Login /> : <Navigate to="/dashboard" />} />
|
<Route path="/login" element={!user ? <Login /> : <Navigate to="/dashboard" />} />
|
||||||
<Route path="/auth/oidc/callback" element={<OidcCallback />} />
|
<Route path="/auth/callback" element={<OidcCallback />} />
|
||||||
<Route
|
<Route
|
||||||
path="/*"
|
path="/*"
|
||||||
element={
|
element={
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,8 @@ const OidcCallback: React.FC = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleCallback = async () => {
|
const handleCallback = async () => {
|
||||||
try {
|
try {
|
||||||
const code = searchParams.get('code');
|
const token = searchParams.get('token');
|
||||||
const error = searchParams.get('error');
|
const error = searchParams.get('error');
|
||||||
const state = searchParams.get('state');
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
setError(`Authentication failed: ${error}`);
|
setError(`Authentication failed: ${error}`);
|
||||||
|
|
@ -24,26 +23,18 @@ const OidcCallback: React.FC = () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!code) {
|
if (!token) {
|
||||||
setError('No authorization code received');
|
setError('No authentication token received from server');
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the backend OIDC callback endpoint
|
// Store the token and set up API authorization
|
||||||
const response = await api.get(`/auth/oidc/callback?code=${code}&state=${state || ''}`);
|
localStorage.setItem('token', token);
|
||||||
|
api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||||
|
|
||||||
if (response.data && response.data.token) {
|
// Redirect to dashboard - the page will reload and AuthContext will pick up the token
|
||||||
// Store the token and user data
|
|
||||||
localStorage.setItem('token', response.data.token);
|
|
||||||
api.defaults.headers.common['Authorization'] = `Bearer ${response.data.token}`;
|
|
||||||
|
|
||||||
// Redirect to dashboard - the auth context will pick up the token on next page load
|
|
||||||
window.location.href = '/dashboard';
|
window.location.href = '/dashboard';
|
||||||
} else {
|
|
||||||
setError('Invalid response from authentication server');
|
|
||||||
setProcessing(false);
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error('OIDC callback error:', err);
|
console.error('OIDC callback error:', err);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Query, State},
|
extract::{Query, State},
|
||||||
http::StatusCode,
|
http::{StatusCode, HeaderMap},
|
||||||
response::{IntoResponse, Json, Response, Redirect},
|
response::{IntoResponse, Json, Response, Redirect},
|
||||||
routing::{get, post},
|
routing::{get, post},
|
||||||
Router,
|
Router,
|
||||||
|
|
@ -188,6 +188,7 @@ async fn oidc_login(State(state): State<Arc<AppState>>) -> Result<Redirect, Stat
|
||||||
)]
|
)]
|
||||||
async fn oidc_callback(
|
async fn oidc_callback(
|
||||||
State(state): State<Arc<AppState>>,
|
State(state): State<Arc<AppState>>,
|
||||||
|
headers: HeaderMap,
|
||||||
Query(params): Query<OidcCallbackQuery>,
|
Query(params): Query<OidcCallbackQuery>,
|
||||||
) -> Result<Redirect, StatusCode> {
|
) -> Result<Redirect, StatusCode> {
|
||||||
tracing::info!("OIDC callback called with params: code={:?}, state={:?}, error={:?}",
|
tracing::info!("OIDC callback called with params: code={:?}, state={:?}, error={:?}",
|
||||||
|
|
@ -326,8 +327,25 @@ async fn oidc_callback(
|
||||||
|
|
||||||
// Redirect to frontend with token in URL fragment
|
// Redirect to frontend with token in URL fragment
|
||||||
// The frontend should extract the token and store it
|
// The frontend should extract the token and store it
|
||||||
let redirect_url = format!("/#/auth/callback?token={}", urlencoding::encode(&token));
|
// Use absolute URL to ensure hash fragment is handled correctly by the browser
|
||||||
tracing::info!("OIDC authentication successful for user: {}, redirecting to: {}", user.username, redirect_url);
|
let host = headers
|
||||||
|
.get("host")
|
||||||
|
.and_then(|h| h.to_str().ok())
|
||||||
|
.unwrap_or("localhost:8000");
|
||||||
|
|
||||||
|
// Check if behind a proxy (X-Forwarded-Proto header)
|
||||||
|
let protocol = headers
|
||||||
|
.get("x-forwarded-proto")
|
||||||
|
.and_then(|h| h.to_str().ok())
|
||||||
|
.unwrap_or("https");
|
||||||
|
|
||||||
|
let redirect_url = format!(
|
||||||
|
"{}://{}/auth/callback?token={}",
|
||||||
|
protocol,
|
||||||
|
host,
|
||||||
|
urlencoding::encode(&token)
|
||||||
|
);
|
||||||
|
tracing::info!("OIDC authentication successful for user: {}, redirecting to callback", user.username);
|
||||||
|
|
||||||
Ok(Redirect::to(&redirect_url))
|
Ok(Redirect::to(&redirect_url))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue