Hi,
We are using REST API in our React Front End. When we try to logout using the redirect URL: http://localhost:8080/logout. (In Jmix 2.6.0). The Vaadin UI is successfully logout. But in REST API, still we can access the entities using the existing access token.
Hi,
This requires investigation.
Can you add mode details about how your Frontend authenticates? Library, settings, etc.
Regards,
Ivan
Hi @i.gavrilov ,
Thanks for your reply. I have attached the Front-end and Back-end Projects. The React Application can access the entities even after the logout.
JMIX Project - auth-test.zip (1.1 MB)
React Project - access-token-ui.zip (53.2 KB)
Login:
import axios from "axios";
const clientId = import.meta.env.VITE_OAUTH2_CLIENT_ID!;
const redirectUri = import.meta.env.VITE_REDIRECT_URL!;
const tokenUrl = import.meta.env.VITE_OAUTH2_TOKEN_URL!;
const authUrlBase = import.meta.env.VITE_OAUTH2_AUTH_URL!;
function base64UrlEncode(str: ArrayBuffer): string {
return btoa(String.fromCharCode(...new Uint8Array(str)))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
}
async function generateCodeChallenge(codeVerifier: string): Promise<string> {
const data = new TextEncoder().encode(codeVerifier);
const digest = await crypto.subtle.digest("SHA-256", data);
return base64UrlEncode(digest);
}
export async function loginWithPKCE() {
const codeVerifier = crypto.randomUUID();
const codeChallenge = await generateCodeChallenge(codeVerifier);
sessionStorage.setItem("pkce_code_verifier", codeVerifier);
const authUrl = `${
import.meta.env.VITE_OAUTH2_AUTH_URL
}?response_type=code&client_id=${
import.meta.env.VITE_OAUTH2_CLIENT_ID
}&state=ZJmte7fGrWadWyUaBMnTFg&code_challenge=${codeChallenge}&code_challenge_method=S256&redirect_uri=${encodeURIComponent(
import.meta.env.VITE_REDIRECT_URL
)}`;
window.location.href = authUrl;
}
export async function exchangeCodeForToken(code: string): Promise<{ accessToken: string }> {
const codeVerifier = sessionStorage.getItem("pkce_code_verifier");
if (!codeVerifier) throw new Error("Missing code verifier");
const payload = new URLSearchParams({
grant_type: "authorization_code",
code,
redirect_uri: redirectUri,
client_id: clientId,
code_verifier: codeVerifier,
});
try {
const res = await axios.post(tokenUrl, payload, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Accept: "application/json",
},
});
return {
accessToken: res.data.access_token,
};
} catch (error: any) {
console.error("❌ Token exchange failed", error.response?.data || error.message);
throw new Error("Token exchange failed");
}
}
Logout:
const handleLogout = () => {
const authUrl = `${import.meta.env.VITE_BASE_API_URL}/logout?redirect_to=${
window.location.origin
}`;
// 🚫 Don't remove token from localStorage
console.log("Redirecting to logout URL:", authUrl);
window.location.href = authUrl;
};
Hi,
In fresh Jmix 2.6.1 we add new logout handler - it removes token found in request (so you have to provide this token within your logout request).
See Authorization Server: Invalidate token on logout · Issue #4608 · jmix-framework/jmix · GitHub and Configuration :: Jmix Documentation
Regards,
Ivan