178 lines
4.6 KiB
JavaScript
178 lines
4.6 KiB
JavaScript
import * as redirect from "./redirect";
|
|
|
|
async function sendRequest(endpoint, body) {
|
|
const formData = new FormData();
|
|
|
|
for (var key in body) {
|
|
formData.append(key, body[key]);
|
|
}
|
|
|
|
const request = {
|
|
method: "POST",
|
|
// headers: {
|
|
// "Content-Type": "application/x-www-form-urlencoded",
|
|
// },
|
|
|
|
body: formData,
|
|
};
|
|
|
|
let response;
|
|
|
|
try {
|
|
response = await fetch(endpoint, request);
|
|
if (!response.ok) {
|
|
throw new Error(response.statusText);
|
|
}
|
|
} catch (err) {
|
|
console.error(err);
|
|
return null;
|
|
}
|
|
|
|
return await response.json();
|
|
}
|
|
|
|
/**
|
|
* @param {string} code the authorization code received from the OIDC
|
|
* provider
|
|
* @returns {Promise<boolean>} true if the token was fetched, false otherwise
|
|
*/
|
|
async function getToken(code) {
|
|
const auth_url = import.meta.env.VITE_URL;
|
|
const endpoint = `${auth_url}/auth-api/token`;
|
|
const formData = {
|
|
grant_type: "authorization_code",
|
|
code: code,
|
|
redirect_uri: `${auth_url}/complete/epita/`,
|
|
client_id: import.meta.env.VITE_CLIENT_ID,
|
|
};
|
|
const response = await sendRequest(endpoint, formData);
|
|
|
|
if (response === null) {
|
|
console.error("Failed to retrieve OIDC token");
|
|
alert("Failed to retrieve OIDC token");
|
|
|
|
localStorage.clear();
|
|
redirect.redirectToLoginPage();
|
|
return false;
|
|
}
|
|
|
|
localStorage.setItem("token", response.id_token);
|
|
localStorage.setItem("refresh_token", response.refresh_token);
|
|
console.debug("Saved token and refresh tokens");
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param {string} refreshToken the refresh token (optional)
|
|
* @returns {Promise<boolean>} whether the token has been refreshed or not
|
|
*/
|
|
async function refreshToken(refreshToken) {
|
|
refreshToken = refreshToken || localStorage.getItem("refresh_token");
|
|
if (!refreshToken) {
|
|
console.error("Unable to retrieve refresh token");
|
|
return false;
|
|
}
|
|
|
|
const auth_url = import.meta.env.VITE_URL;
|
|
const endpoint = `${auth_url}/auth-api/token`;
|
|
const formData = {
|
|
client_id: import.meta.env.VITE_CLIENT_ID,
|
|
// client_secret: "",
|
|
grant_type: "authorization_code",
|
|
refresh_token: refreshToken,
|
|
scope: "epita profile picture",
|
|
};
|
|
const response = await sendRequest(endpoint, formData);
|
|
|
|
if (response === null) {
|
|
console.error("Failed to retrieve OIDC token");
|
|
alert("Failed to retrieve OIDC token");
|
|
|
|
localStorage.clear();
|
|
redirect.redirectToLoginPage();
|
|
return false;
|
|
}
|
|
|
|
localStorage.setItem("token", response.id_token);
|
|
localStorage.setItem("refresh_token", response.refresh_token);
|
|
console.debug("Saved token and refresh tokens");
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @returns {Promise<boolean>} true if the user is authenticated, false otherwise
|
|
*/
|
|
async function authenticate() {
|
|
const token = localStorage.getItem("token");
|
|
|
|
if (token !== null) {
|
|
return true;
|
|
}
|
|
|
|
const refresh_token = localStorage.getItem("refresh_token");
|
|
|
|
if (refresh_token !== null) {
|
|
return true;
|
|
}
|
|
|
|
localStorage.clear();
|
|
redirect.redirectToLoginPage();
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param {string} endpoint
|
|
* @param {object} options this object should at least contain the method.
|
|
* @returns {Promise<Response>} the response or null
|
|
* We want a {Promise<Response>} so we can read the headers as well as the
|
|
* body, rather than just the body
|
|
*/
|
|
async function authedAPIRequest(endpoint, options) {
|
|
if (!authenticate()) {
|
|
return null;
|
|
}
|
|
|
|
if (!options.method) {
|
|
console.error("Invalid parameter: options (missing method)");
|
|
return null
|
|
}
|
|
|
|
if (!options.headers) {
|
|
options.headers = {};
|
|
}
|
|
|
|
options.headers.Authorization = "Bearer " + localStorage.getItem("token");
|
|
options.mode = "cors";
|
|
|
|
const full_endpoint = import.meta.env.VITE_URL + "/api" + endpoint;
|
|
let response;
|
|
|
|
try {
|
|
response = await fetch(full_endpoint, options);
|
|
if (!response.ok) {
|
|
throw new Error(response.statusText);
|
|
}
|
|
} catch (err) {
|
|
if (response.status === 401) {
|
|
const response_err = await response.text();
|
|
|
|
if (response_err.includes("Token expired")) {
|
|
refreshToken(null);
|
|
return null;
|
|
}
|
|
|
|
localStorage.clear();
|
|
alert("Redirecting to logging page")
|
|
redirect.redirectToLoginPage();
|
|
return null;
|
|
}
|
|
|
|
console.error(err);
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
export { getToken, refreshToken, authenticate, authedAPIRequest };
|