Auth basico completado
This commit is contained in:
@@ -1,64 +1,52 @@
|
||||
import React, {useState} from 'react';
|
||||
import React from 'react';
|
||||
import {Redirect} from "react-router-dom";
|
||||
import queryString from "query-string";
|
||||
|
||||
import {get_auth, obtain_code} from "../services/auth_service";
|
||||
import {auth, logout} from "../services/auth_service";
|
||||
import {useStateValue} from "../services/State";
|
||||
|
||||
export const AuthCallback = (props) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
export const AuthLogin = (props) => {
|
||||
const [response, setResponse] = useState(null);
|
||||
const [context, dispatch] = useStateValue();
|
||||
|
||||
if (window.localStorage.getItem('refresh_token')) {
|
||||
if (context.user.auth) {
|
||||
// El usuario ya esta logeado, no hay nada que hacer
|
||||
props.history.push('/')
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
if (context.user.auth) {
|
||||
return <Redirect to='/'/>
|
||||
}
|
||||
const params = queryString.parse(props.location.search);
|
||||
auth(params).then((response) => {
|
||||
console.debug(response, window.localStorage);
|
||||
|
||||
if (!window.localStorage.getItem('code_verifier')) {
|
||||
const {redirect, code_verifier} = obtain_code();
|
||||
window.localStorage.setItem('code_verifier', code_verifier);
|
||||
window.location.href = redirect;
|
||||
if(response.status === 'redirect_to_code'){
|
||||
// Se va o ya se redirigió hacia la pagina que obtiene el código, no hay nada que hacer.
|
||||
return null;
|
||||
} else if (response.status === 'code_error') {
|
||||
// Hubo un error al obtener el código
|
||||
props.history.push('/error')
|
||||
} else if (response.status === 'done') {
|
||||
// Termino gud, refresh_token y expires debería estar en local storage y access_token
|
||||
// debió ser retornado con la response
|
||||
props.history.push('/')
|
||||
dispatch({type: 'login', user:{auth: true, access_token: response.access_token}});
|
||||
} else {
|
||||
// Ocurrió un error inesperado al hacer auth :c
|
||||
props.history.push('/error')
|
||||
}
|
||||
})
|
||||
|
||||
const parsedParams = queryString.parse(props.location.search);
|
||||
if (parsedParams.error) {
|
||||
console.log(parsedParams.error);
|
||||
window.localStorage.removeItem('code_verifier');
|
||||
return <Redirect to={'/error'}/>
|
||||
}
|
||||
|
||||
const code = parsedParams.code;
|
||||
const code_verifier = window.localStorage.getItem('code_verifier');
|
||||
get_auth(code, code_verifier).then((response) => setResponse(response));
|
||||
|
||||
return null;
|
||||
} else {
|
||||
console.log(response);
|
||||
|
||||
window.localStorage.removeItem('code_verifier');
|
||||
|
||||
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);
|
||||
|
||||
dispatch({type: 'login', user: {auth: true, access_token: response.access_token}});
|
||||
|
||||
return <Redirect to={'/'}/>
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export const AuthLogout = (props) => {
|
||||
const [context, dispatch] = useStateValue();
|
||||
dispatch({action: 'logout', user: {auth: false}})
|
||||
if (!context.user.auth) {
|
||||
return <Redirect to='/'/>
|
||||
}
|
||||
|
||||
logout(context.user.access_token).then(result => {
|
||||
console.log(result);
|
||||
});
|
||||
|
||||
dispatch({type: 'logout', user: {auth: false}})
|
||||
return <Redirect to='/'/>
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ const App = () => (
|
||||
|
||||
<Route exact path='/login' component={AuthLogin}/>
|
||||
<Route exact path='/logout' component={AuthLogout}/>
|
||||
<Route exact path='/auth_callback' component={AuthCallback}/>
|
||||
|
||||
<Route exact path='/' component={Main}/>
|
||||
<Route path='*' component={NoRoute}/>
|
||||
|
||||
@@ -11,7 +11,13 @@ const reducer = (state, action) => {
|
||||
...state,
|
||||
user: action.user
|
||||
}
|
||||
default: return state;
|
||||
case 'logout':
|
||||
return {
|
||||
...state,
|
||||
user: action.user
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,7 +26,7 @@ export const StateContext = createContext(null);
|
||||
export const StateProvider = ({children}) => {
|
||||
|
||||
return (
|
||||
<StateContext.Provider value={useReducer(reducer, initialState )}>
|
||||
<StateContext.Provider value={useReducer(reducer, initialState)}>
|
||||
{children}
|
||||
</StateContext.Provider>
|
||||
);
|
||||
|
||||
@@ -12,7 +12,7 @@ const generate_challenge = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const obtain_code = () => {
|
||||
export const redirect_to_code = () => {
|
||||
const challenge = generate_challenge()
|
||||
const params = {
|
||||
response_type: 'code',
|
||||
@@ -24,10 +24,10 @@ export const obtain_code = () => {
|
||||
};
|
||||
const url = `${oauth_url}/authorize/?${new URLSearchParams(params).toString()}`;
|
||||
|
||||
return {
|
||||
redirect: url,
|
||||
code_verifier: challenge.code
|
||||
}
|
||||
window.localStorage.setItem('code_verifier', challenge.code);
|
||||
window.location.href = url;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export const get_auth = async (code, code_verifier) => {
|
||||
@@ -43,3 +43,71 @@ export const get_auth = async (code, code_verifier) => {
|
||||
|
||||
return response.data
|
||||
}
|
||||
|
||||
export const auth = async (params) => {
|
||||
// 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');
|
||||
const response = await get_auth(code, code_verifier)
|
||||
|
||||
// Puede que la respuesta sea erronea 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 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);
|
||||
|
||||
// Finalmente se retorna el access_token para ser utilizado en el estado de la app
|
||||
return {status: 'done', access_token: response.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,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user