143 lines
5.0 KiB
JavaScript
143 lines
5.0 KiB
JavaScript
import axios from "axios";
|
|
import {getUser} from "./user_service";
|
|
|
|
const current_host = `${window.location.protocol}//${window.location.host}`
|
|
const oauth_url = `${process.env.REACT_APP_API_SERVER}/oauth`;
|
|
const client_id = process.env["REACT_APP_CLIENT_ID"];
|
|
|
|
const generate_challenge = () => {
|
|
return {
|
|
code: '5d2309e5bb73b864f989753887fe52f79ce5270395e25862da6940d5',
|
|
challenge: 'MChCW5vD-3h03HMGFZYskOSTir7II_MMTb8a9rJNhnI',
|
|
method: 'S256',
|
|
}
|
|
}
|
|
|
|
export const redirect_to_code = () => {
|
|
const challenge = generate_challenge()
|
|
const params = {
|
|
response_type: 'code',
|
|
client_id: client_id,
|
|
redirect_uri: `${current_host}/login`,
|
|
scope: 'read write',
|
|
code_challenge: challenge.challenge,
|
|
code_challenge_method: challenge.method
|
|
};
|
|
const url = `${oauth_url}/authorize/?${new URLSearchParams(params).toString()}`;
|
|
|
|
window.localStorage.setItem('code_verifier', challenge.code);
|
|
window.location.href = url;
|
|
|
|
return null;
|
|
}
|
|
|
|
export const do_auth = async (code, code_verifier) => {
|
|
const params = {
|
|
code: code,
|
|
code_verifier: code_verifier,
|
|
grant_type: 'authorization_code',
|
|
redirect_uri: `${current_host}/login`,
|
|
client_id: client_id,
|
|
};
|
|
const url = `${oauth_url}/token/`
|
|
const response = await axios.post(url, new URLSearchParams(params));
|
|
|
|
return response.data
|
|
}
|
|
|
|
export const do_refresh = async (token) => {
|
|
const params = {
|
|
grant_type: 'refresh_token',
|
|
refresh_token: token,
|
|
client_id: client_id,
|
|
};
|
|
|
|
const url = `${oauth_url}/token/`
|
|
const response = await axios.post(url, new URLSearchParams(params));
|
|
return response.data;
|
|
}
|
|
|
|
export const auth = async (params) => {
|
|
// Como response se puede obtener desde refresh o desde un auth regular, se almacena al inicio
|
|
let response;
|
|
|
|
// Preámbulo, puede existir un refresh_token usable asi que debe hacer el flow de renew
|
|
if (window.localStorage.getItem('refresh_token')) {
|
|
const refresh_token = window.localStorage.getItem('refresh_token');
|
|
response = await do_refresh(refresh_token);
|
|
}
|
|
|
|
if (!response) {
|
|
// Primera fase, obtener código
|
|
// Si es que no se tiene se tiene que redirigir a la pagina de oauth que entregara el código
|
|
// a la pagina de redirect como parámetro GET, este trabajo lo hace redirect y se volverá a
|
|
// ejecutar este método cuando se entre a esa ruta
|
|
if (!window.localStorage.getItem('code_verifier')) {
|
|
redirect_to_code();
|
|
return {status: 'redirect_to_code'};
|
|
}
|
|
|
|
// Segunda fase, se llama a auth con los parámetros de la ruta.
|
|
// Estos parámetros puede contener un error, en ese caso se elimina el code_verifier del storage
|
|
// porque no sera util y fallo la request.
|
|
if (params.error) {
|
|
window.localStorage.clear()
|
|
return {status: 'code_error', value: params.error};
|
|
}
|
|
|
|
// Teniendo el código en los parámetros se intenta obtener el código de autorización.
|
|
const code = params.code;
|
|
const code_verifier = window.localStorage.getItem('code_verifier');
|
|
response = await do_auth(code, code_verifier)
|
|
}
|
|
|
|
// Puede que la respuesta sea errónea por varias razones
|
|
if (response.error) {
|
|
return {status: response.error}
|
|
}
|
|
|
|
// Una vez se tiene la respuesta se almacena el refresh_token y el expires_in
|
|
// en localstorage para ser utilizado mas tarde para renovar el access_token
|
|
window.localStorage.clear()
|
|
|
|
const access_token = response.access_token;
|
|
const refresh = response.refresh_token;
|
|
const expires = new Date(new Date().getTime() + ((response.expires_in) * 1000))
|
|
|
|
window.localStorage.setItem('refresh_token', refresh);
|
|
window.localStorage.setItem('expires', expires);
|
|
|
|
// Almacenar el usuario en localStorage
|
|
const user = await getUser(access_token);
|
|
window.localStorage.setItem('user', JSON.stringify(user))
|
|
|
|
// Finalmente se retorna el access_token para ser utilizado en el estado de la app
|
|
return {status: 'done', access_token: access_token};
|
|
}
|
|
|
|
export const logout = async (access_token) => {
|
|
// Para hacer logout de un usuario es necesario eliminar el refresh token de su localStorage
|
|
// y se llama a revocar los tokens en el servidor oauth
|
|
const revoke_access_params = {
|
|
token: access_token,
|
|
client_id: client_id,
|
|
token_type_hint: 'access_token'
|
|
}
|
|
const revoke_refresh_params = {
|
|
token: window.localStorage.getItem('refresh_token'),
|
|
client_id: client_id,
|
|
token_type_hint: 'refresh_token'
|
|
}
|
|
|
|
window.localStorage.clear();
|
|
|
|
const url = `${oauth_url}/revoke_token/`;
|
|
const response_access_revoke = await axios.post(url, new URLSearchParams(revoke_access_params));
|
|
const response_refresh_revoke = await axios.post(url, new URLSearchParams(revoke_refresh_params));
|
|
|
|
return {
|
|
access_revoke: response_access_revoke,
|
|
refresh_revoke: response_refresh_revoke,
|
|
}
|
|
}
|