From bb6be9a7345d7f1b96a13a3e62ad4d9d351b4d18 Mon Sep 17 00:00:00 2001 From: Belen Curcio Date: Thu, 25 May 2017 11:53:40 -0300 Subject: [PATCH] BE implementation --- client/coral-framework/actions/auth.js | 108 +++++++++++---------- client/coral-framework/helpers/response.js | 4 +- routes/api/auth/index.js | 29 +++++- services/passport.js | 7 ++ 4 files changed, 90 insertions(+), 58 deletions(-) diff --git a/client/coral-framework/actions/auth.js b/client/coral-framework/actions/auth.js index 071235ce3..7798e165f 100644 --- a/client/coral-framework/actions/auth.js +++ b/client/coral-framework/actions/auth.js @@ -9,7 +9,7 @@ const lang = new I18n(translations); import translations from './../translations'; import I18n from '../../coral-framework/modules/i18n/i18n'; -export const showSignInDialog = () => (dispatch) => { +export const showSignInDialog = () => dispatch => { const signInPopUp = window.open( '/embed/stream/login', 'Login', @@ -32,7 +32,7 @@ export const showSignInDialog = () => (dispatch) => { dispatch({type: actions.SHOW_SIGNIN_DIALOG}); }; -export const hideSignInDialog = () => (dispatch) => { +export const hideSignInDialog = () => dispatch => { dispatch({type: actions.HIDE_SIGNIN_DIALOG}); window.close(); }; @@ -51,7 +51,7 @@ const createUsernameSuccess = () => ({ type: actions.CREATE_USERNAME_SUCCESS }); -const createUsernameFailure = (error) => ({ +const createUsernameFailure = error => ({ type: actions.CREATE_USERNAME_FAILURE, error }); @@ -61,7 +61,7 @@ export const updateUsername = ({username}) => ({ username }); -export const createUsername = (userId, formData) => (dispatch) => { +export const createUsername = (userId, formData) => dispatch => { dispatch(createUsernameRequest()); coralApi('/account/username', {method: 'PUT', body: formData}) .then(() => { @@ -69,26 +69,26 @@ export const createUsername = (userId, formData) => (dispatch) => { dispatch(hideCreateUsernameDialog()); dispatch(updateUsername(formData)); }) - .catch((error) => { + .catch(error => { dispatch(createUsernameFailure(lang.t(`error.${error.translation_key}`))); }); }; -export const changeView = (view) => (dispatch) => { +export const changeView = view => dispatch => { dispatch({ type: actions.CHANGE_VIEW, view }); switch (view) { - case 'SIGNUP': - window.resizeTo(500, 800); - break; - case 'FORGOT': - window.resizeTo(500, 400); - break; - default: - window.resizeTo(500, 550); + case 'SIGNUP': + window.resizeTo(500, 800); + break; + case 'FORGOT': + window.resizeTo(500, 400); + break; + default: + window.resizeTo(500, 550); } }; @@ -102,7 +102,7 @@ const signInRequest = () => ({ type: actions.FETCH_SIGNIN_REQUEST }); -const signInFailure = (error) => ({ +const signInFailure = error => ({ type: actions.FETCH_SIGNIN_FAILURE, error }); @@ -111,7 +111,7 @@ const signInFailure = (error) => ({ // AUTH TOKEN //============================================================================== -export const handleAuthToken = (token) => (dispatch) => { +export const handleAuthToken = token => dispatch => { if (!browser || browser.name !== 'safari') { Storage.setItem('exp', jwtDecode(token).exp); Storage.setItem('token', token); @@ -123,26 +123,29 @@ export const handleAuthToken = (token) => (dispatch) => { // SIGN IN //============================================================================== -export const fetchSignIn = (formData) => (dispatch) => { - dispatch(signInRequest()); - return coralApi('/auth/local', {method: 'POST', body: formData}) - .then(({token}) => { - dispatch(handleAuthToken(token)); - dispatch(hideSignInDialog()); - }) - .catch((error) => { - if (error.metadata) { +export const fetchSignIn = formData => { + return dispatch => { + dispatch(signInRequest()); - // the user might not have a valid email. prompt the user user re-request the confirmation email - dispatch( - signInFailure(lang.t('error.emailNotVerified', error.metadata)) - ); - } else { + return coralApi('/auth/local', {method: 'POST', body: formData}) + .then(({token}) => { + dispatch(handleAuthToken(token)); + dispatch(hideSignInDialog()); + }) + .catch(error => { + if (error.metadata) { - // invalid credentials - dispatch(signInFailure(lang.t('error.emailPasswordError'))); - } - }); + // the user might not have a valid email. prompt the user user re-request the confirmation email + dispatch( + signInFailure(lang.t('error.emailNotVerified', error.metadata)) + ); + } else { + + // invalid credentials + dispatch(signInFailure(lang.t('error.emailPasswordError'))); + } + }); + }; }; //============================================================================== @@ -153,17 +156,17 @@ const signInFacebookRequest = () => ({ type: actions.FETCH_SIGNIN_FACEBOOK_REQUEST }); -const signInFacebookSuccess = (user) => ({ +const signInFacebookSuccess = user => ({ type: actions.FETCH_SIGNIN_FACEBOOK_SUCCESS, user }); -const signInFacebookFailure = (error) => ({ +const signInFacebookFailure = error => ({ type: actions.FETCH_SIGNIN_FACEBOOK_FAILURE, error }); -export const fetchSignInFacebook = () => (dispatch) => { +export const fetchSignInFacebook = () => dispatch => { dispatch(signInFacebookRequest()); window.open( `${base}/auth/facebook`, @@ -180,7 +183,7 @@ const signUpFacebookRequest = () => ({ type: actions.FETCH_SIGNUP_FACEBOOK_REQUEST }); -export const fetchSignUpFacebook = () => (dispatch) => { +export const fetchSignUpFacebook = () => dispatch => { dispatch(signUpFacebookRequest()); window.open( `${base}/auth/facebook`, @@ -213,10 +216,10 @@ export const facebookCallback = (err, data) => (dispatch, getState) => { //============================================================================== const signUpRequest = () => ({type: actions.FETCH_SIGNUP_REQUEST}); -const signUpSuccess = (user) => ({type: actions.FETCH_SIGNUP_SUCCESS, user}); -const signUpFailure = (error) => ({type: actions.FETCH_SIGNUP_FAILURE, error}); +const signUpSuccess = user => ({type: actions.FETCH_SIGNUP_SUCCESS, user}); +const signUpFailure = error => ({type: actions.FETCH_SIGNUP_FAILURE, error}); -export const fetchSignUp = (formData, redirectUri) => (dispatch) => { +export const fetchSignUp = (formData, redirectUri) => dispatch => { dispatch(signUpRequest()); coralApi('/users', { @@ -227,7 +230,7 @@ export const fetchSignUp = (formData, redirectUri) => (dispatch) => { .then(({user}) => { dispatch(signUpSuccess(user)); }) - .catch((error) => { + .catch(error => { let errorMessage = lang.t(`error.${error.message}`); // if there is no translation defined, just show the error string @@ -254,7 +257,7 @@ const forgotPasswordFailure = () => ({ type: actions.FETCH_FORGOT_PASSWORD_FAILURE }); -export const fetchForgotPassword = (email) => (dispatch) => { +export const fetchForgotPassword = email => dispatch => { dispatch(forgotPasswordRequest(email)); const redirectUri = pym.parentUrl || location.href; coralApi('/account/password/reset', { @@ -262,14 +265,14 @@ export const fetchForgotPassword = (email) => (dispatch) => { body: {email, loc: redirectUri} }) .then(() => dispatch(forgotPasswordSuccess())) - .catch((error) => dispatch(forgotPasswordFailure(error))); + .catch(error => dispatch(forgotPasswordFailure(error))); }; //============================================================================== // LOGOUT //============================================================================== -export const logout = () => (dispatch) => { +export const logout = () => dispatch => { return coralApi('/auth', {method: 'DELETE'}).then(() => { if (!browser || browser.name !== 'safari') { Storage.removeItem('token'); @@ -283,7 +286,7 @@ export const logout = () => (dispatch) => { //============================================================================== const checkLoginRequest = () => ({type: actions.CHECK_LOGIN_REQUEST}); -const checkLoginFailure = (error) => ({type: actions.CHECK_LOGIN_FAILURE, error}); +const checkLoginFailure = error => ({type: actions.CHECK_LOGIN_FAILURE, error}); const checkLoginSuccess = (user, isAdmin) => ({ type: actions.CHECK_LOGIN_SUCCESS, @@ -291,10 +294,10 @@ const checkLoginSuccess = (user, isAdmin) => ({ isAdmin }); -export const checkLogin = () => (dispatch) => { +export const checkLogin = () => dispatch => { dispatch(checkLoginRequest()); coralApi('/auth') - .then((result) => { + .then(result => { if (!result.user) { if (!browser || browser.name !== 'safari') { Storage.removeItem('token'); @@ -304,14 +307,14 @@ export const checkLogin = () => (dispatch) => { dispatch(checkLoginSuccess(result.user)); }) - .catch((error) => { + .catch(error => { console.error(error); dispatch(checkLoginFailure(`${error.translation_key}`)); }); }; export const validForm = () => ({type: actions.VALID_FORM}); -export const invalidForm = (error) => ({type: actions.INVALID_FORM, error}); +export const invalidForm = error => ({type: actions.INVALID_FORM, error}); //============================================================================== // VERIFY EMAIL @@ -329,7 +332,7 @@ const verifyEmailFailure = () => ({ type: actions.VERIFY_EMAIL_FAILURE }); -export const requestConfirmEmail = (email, redirectUri) => (dispatch) => { +export const requestConfirmEmail = (email, redirectUri) => dispatch => { dispatch(verifyEmailRequest()); return coralApi('/users/resend-verify', { method: 'POST', @@ -339,8 +342,7 @@ export const requestConfirmEmail = (email, redirectUri) => (dispatch) => { .then(() => { dispatch(verifyEmailSuccess()); }) - .catch((err) => { - + .catch(err => { // email might have already been verifyed dispatch(verifyEmailFailure(err)); }); diff --git a/client/coral-framework/helpers/response.js b/client/coral-framework/helpers/response.js index bad2e52f7..b6e48abb3 100644 --- a/client/coral-framework/helpers/response.js +++ b/client/coral-framework/helpers/response.js @@ -5,13 +5,13 @@ const buildOptions = (inputOptions = {}) => { method: 'GET', headers: { Accept: 'application/json', - 'Content-Type': 'application/json' + 'Content-Type': 'application/json', }, credentials: 'same-origin' }; let options = { - defaultOptions, + ...defaultOptions, ...inputOptions }; diff --git a/routes/api/auth/index.js b/routes/api/auth/index.js index 6f610e2b0..90fe31b1e 100644 --- a/routes/api/auth/index.js +++ b/routes/api/auth/index.js @@ -3,6 +3,14 @@ const {passport, HandleGenerateCredentials, HandleLogout} = require('../../../se const router = express.Router(); +const lookup = (i) => { + switch (i) { + case 0: return 'header'; + case 1: return 'cookie'; + case 2: return 'query'; + } +}; + /** * This returns the user if they are logged in. */ @@ -15,16 +23,31 @@ router.get('/', (req, res, next) => { res.status(204).end(); }, (req, res) => { - // Send back the user object. - res.json({user: req.user}); + const authorizations = [ + req.headers.authorization, + req.cookies ? req.cookies.authorization : [], + req.query.authorization + ]; + + res.set('Cache-Control', 'no-cache, no-store, must-revalidate'); + + let i = authorizations.findIndex((source) => source !== null && typeof source != 'undefined' && source.length > 0); + if (i >= 0) { + let authorization = authorizations[i]; + let source = lookup(i); + + // Send back the user object. + res.json({authorization, source, user: req.user}); + } }); /** * This blacklists the token used to authenticate. */ + router.delete('/', HandleLogout); -//============================================================================== +// ============================================================================= // PASSPORT ROUTES //============================================================================== diff --git a/services/passport.js b/services/passport.js index c64bb2334..5e993be51 100644 --- a/services/passport.js +++ b/services/passport.js @@ -47,6 +47,12 @@ const HandleGenerateCredentials = (req, res, next) => (err, user) => { // Generate the token to re-issue to the frontend. const token = GenerateToken(user); + // handling cookie + res.cookie('authorization', token, { + httpOnly: true, + expires: new Date(Date.now() + 900000) + }); + // Send back the details! res.json({user, token}); }; @@ -134,6 +140,7 @@ const HandleLogout = (req, res, next) => { return next(err); } + res.clearCookie('authorization'); res.status(204).end(); }); };