feat: PKCE auth + CI/CD deploy
Some checks failed
CI/CD — Build & Deploy / Build & Deploy (push) Failing after 25s
Some checks failed
CI/CD — Build & Deploy / Build & Deploy (push) Failing after 25s
- Frontend: PKCE flow (oauth.js, api.js centralized, cookie-based AuthContext) - Backend: token introspection, cookies httpOnly, refresh endpoint - Replaced localStorage JWT with httpOnly session cookies - useSaveSync migrated to cookie auth - cookie-parser added - Gitea CI workflow (vps-runner pattern)
This commit is contained in:
@@ -1,26 +1,60 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate, useSearchParams, Link } from "react-router-dom";
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
import { exchangeCode, loadVerifier, clearVerifier } from "../lib/oauth";
|
||||
import { apiFetch } from "../lib/api";
|
||||
import { useAuth } from "../context/AuthContext";
|
||||
import "../scss/pages.scss";
|
||||
|
||||
export default function AuthCallback() {
|
||||
const [searchParams] = useSearchParams();
|
||||
const { loginWithOAuth } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const { refresh } = useAuth();
|
||||
const [error, setError] = useState(null);
|
||||
const called = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const token = searchParams.get("token");
|
||||
if (called.current) return;
|
||||
called.current = true;
|
||||
|
||||
if (!token) {
|
||||
setError("Token manquant dans l'URL.");
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const code = params.get("code");
|
||||
const err = params.get("error");
|
||||
|
||||
if (err) {
|
||||
setError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
loginWithOAuth(token)
|
||||
if (!code) {
|
||||
setError("Code manquant dans l'URL.");
|
||||
return;
|
||||
}
|
||||
|
||||
const verifier = loadVerifier();
|
||||
if (!verifier) {
|
||||
setError("Verifier PKCE manquant — réessaie la connexion.");
|
||||
return;
|
||||
}
|
||||
|
||||
const redirectUri = `${window.location.origin}/callback`;
|
||||
|
||||
exchangeCode(code, verifier, redirectUri)
|
||||
.then((tokens) => {
|
||||
clearVerifier();
|
||||
return apiFetch("/auth/session", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
token: tokens.access_token,
|
||||
refreshToken: tokens.refresh_token,
|
||||
}),
|
||||
});
|
||||
})
|
||||
.then(() => refresh())
|
||||
.then(() => navigate("/", { replace: true }))
|
||||
.catch((err) => setError(err.message || "Erreur de connexion."));
|
||||
}, []);
|
||||
.catch((e) => {
|
||||
clearVerifier();
|
||||
setError(e.message || "Erreur de connexion.");
|
||||
});
|
||||
}, [navigate, refresh]);
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user