Auth: refactor OAuth token actions

merge-requests/680/head
Alex Gleason 3 years ago
parent a1cbbfcb02
commit 74f4c59004
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7

@ -6,6 +6,7 @@ import { createAccount } from 'soapbox/actions/accounts';
import { fetchMeSuccess, fetchMeFail } from 'soapbox/actions/me'; import { fetchMeSuccess, fetchMeFail } from 'soapbox/actions/me';
import { getLoggedInAccount } from 'soapbox/utils/auth'; import { getLoggedInAccount } from 'soapbox/utils/auth';
import { createApp } from 'soapbox/actions/apps'; import { createApp } from 'soapbox/actions/apps';
import { obtainOAuthToken, revokeOAuthToken } from 'soapbox/actions/oauth';
export const SWITCH_ACCOUNT = 'SWITCH_ACCOUNT'; export const SWITCH_ACCOUNT = 'SWITCH_ACCOUNT';
@ -34,14 +35,6 @@ export const CHANGE_PASSWORD_REQUEST = 'CHANGE_PASSWORD_REQUEST';
export const CHANGE_PASSWORD_SUCCESS = 'CHANGE_PASSWORD_SUCCESS'; export const CHANGE_PASSWORD_SUCCESS = 'CHANGE_PASSWORD_SUCCESS';
export const CHANGE_PASSWORD_FAIL = 'CHANGE_PASSWORD_FAIL'; export const CHANGE_PASSWORD_FAIL = 'CHANGE_PASSWORD_FAIL';
export const FETCH_TOKENS_REQUEST = 'FETCH_TOKENS_REQUEST';
export const FETCH_TOKENS_SUCCESS = 'FETCH_TOKENS_SUCCESS';
export const FETCH_TOKENS_FAIL = 'FETCH_TOKENS_FAIL';
export const REVOKE_TOKEN_REQUEST = 'REVOKE_TOKEN_REQUEST';
export const REVOKE_TOKEN_SUCCESS = 'REVOKE_TOKEN_SUCCESS';
export const REVOKE_TOKEN_FAIL = 'REVOKE_TOKEN_FAIL';
const messages = defineMessages({ const messages = defineMessages({
loggedOut: { id: 'auth.logged_out', defaultMessage: 'Logged out.' }, loggedOut: { id: 'auth.logged_out', defaultMessage: 'Logged out.' },
invalidCredentials: { id: 'auth.invalid_credentials', defaultMessage: 'Wrong username or password' }, invalidCredentials: { id: 'auth.invalid_credentials', defaultMessage: 'Wrong username or password' },
@ -80,13 +73,15 @@ function createAppToken() {
return (dispatch, getState) => { return (dispatch, getState) => {
const app = getState().getIn(['auth', 'app']); const app = getState().getIn(['auth', 'app']);
return api(getState, 'app').post('/oauth/token', { const params = {
client_id: app.get('client_id'), client_id: app.get('client_id'),
client_secret: app.get('client_secret'), client_secret: app.get('client_secret'),
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
grant_type: 'client_credentials', grant_type: 'client_credentials',
}).then(response => { };
return dispatch(authAppAuthorized(response.data));
return dispatch(obtainOAuthToken(params)).then(token => {
return dispatch({ type: AUTH_APP_AUTHORIZED, app, token });
}); });
}; };
} }
@ -94,14 +89,17 @@ function createAppToken() {
function createUserToken(username, password) { function createUserToken(username, password) {
return (dispatch, getState) => { return (dispatch, getState) => {
const app = getState().getIn(['auth', 'app']); const app = getState().getIn(['auth', 'app']);
return api(getState, 'app').post('/oauth/token', {
const params = {
client_id: app.get('client_id'), client_id: app.get('client_id'),
client_secret: app.get('client_secret'), client_secret: app.get('client_secret'),
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
grant_type: 'password', grant_type: 'password',
username: username, username: username,
password: password, password: password,
}).then(({ data: token }) => { };
return dispatch(obtainOAuthToken(params)).then(token => {
dispatch(authLoggedIn(token)); dispatch(authLoggedIn(token));
return token; return token;
}); });
@ -115,14 +113,16 @@ export function refreshUserToken() {
if (!refreshToken) return dispatch(noOp()); if (!refreshToken) return dispatch(noOp());
return api(getState, 'app').post('/oauth/token', { const params = {
client_id: app.get('client_id'), client_id: app.get('client_id'),
client_secret: app.get('client_secret'), client_secret: app.get('client_secret'),
refresh_token: refreshToken, refresh_token: refreshToken,
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
grant_type: 'refresh_token', grant_type: 'refresh_token',
}).then(response => { };
dispatch(authLoggedIn(response.data));
return dispatch(obtainOAuthToken(params)).then(token => {
dispatch(authLoggedIn(token));
}); });
}; };
} }
@ -182,11 +182,13 @@ export function logOut(intl) {
const state = getState(); const state = getState();
const account = getLoggedInAccount(state); const account = getLoggedInAccount(state);
return api(getState).post('/oauth/revoke', { const params = {
client_id: state.getIn(['auth', 'app', 'client_id']), client_id: state.getIn(['auth', 'app', 'client_id']),
client_secret: state.getIn(['auth', 'app', 'client_secret']), client_secret: state.getIn(['auth', 'app', 'client_secret']),
token: state.getIn(['auth', 'users', account.get('url'), 'access_token']), token: state.getIn(['auth', 'users', account.get('url'), 'access_token']),
}).finally(() => { };
return dispatch(revokeOAuthToken(params)).finally(() => {
dispatch({ type: AUTH_LOGGED_OUT, account }); dispatch({ type: AUTH_LOGGED_OUT, account });
dispatch(snackbar.success(intl.formatMessage(messages.loggedOut))); dispatch(snackbar.success(intl.formatMessage(messages.loggedOut)));
}); });
@ -299,35 +301,6 @@ export function changePassword(oldPassword, newPassword, confirmation) {
}; };
} }
export function fetchOAuthTokens() {
return (dispatch, getState) => {
dispatch({ type: FETCH_TOKENS_REQUEST });
return api(getState).get('/api/oauth_tokens.json').then(response => {
dispatch({ type: FETCH_TOKENS_SUCCESS, tokens: response.data });
}).catch(error => {
dispatch({ type: FETCH_TOKENS_FAIL });
});
};
}
export function revokeOAuthToken(id) {
return (dispatch, getState) => {
dispatch({ type: REVOKE_TOKEN_REQUEST, id });
return api(getState).delete(`/api/oauth_tokens/${id}`).then(response => {
dispatch({ type: REVOKE_TOKEN_SUCCESS, id });
}).catch(error => {
dispatch({ type: REVOKE_TOKEN_FAIL, id });
});
};
}
export function authAppAuthorized(app) {
return {
type: AUTH_APP_AUTHORIZED,
app,
};
}
export function authLoggedIn(token) { export function authLoggedIn(token) {
return { return {
type: AUTH_LOGGED_IN, type: AUTH_LOGGED_IN,

@ -0,0 +1,35 @@
import { baseClient } from '../api';
export const OAUTH_TOKEN_CREATE_REQUEST = 'OAUTH_TOKEN_CREATE_REQUEST';
export const OAUTH_TOKEN_CREATE_SUCCESS = 'OAUTH_TOKEN_CREATE_SUCCESS';
export const OAUTH_TOKEN_CREATE_FAIL = 'OAUTH_TOKEN_CREATE_FAIL';
export const OAUTH_TOKEN_REVOKE_REQUEST = 'OAUTH_TOKEN_REVOKE_REQUEST';
export const OAUTH_TOKEN_REVOKE_SUCCESS = 'OAUTH_TOKEN_REVOKE_SUCCESS';
export const OAUTH_TOKEN_REVOKE_FAIL = 'OAUTH_TOKEN_REVOKE_FAIL';
export function obtainOAuthToken(params) {
return (dispatch, getState) => {
dispatch({ type: OAUTH_TOKEN_CREATE_REQUEST, params });
return baseClient().post('/oauth/token', params).then(({ data: token }) => {
dispatch({ type: OAUTH_TOKEN_CREATE_SUCCESS, params, token });
return token;
}).catch(error => {
dispatch({ type: OAUTH_TOKEN_CREATE_FAIL, params, error });
throw error;
});
};
}
export function revokeOAuthToken(params) {
return (dispatch, getState) => {
dispatch({ type: OAUTH_TOKEN_REVOKE_REQUEST, params });
return baseClient().post('/oauth/revoke', params).then(({ data }) => {
dispatch({ type: OAUTH_TOKEN_REVOKE_SUCCESS, params, data });
return data;
}).catch(error => {
dispatch({ type: OAUTH_TOKEN_REVOKE_FAIL, params, error });
throw error;
});
};
}

@ -0,0 +1,31 @@
import api from '../api';
export const FETCH_TOKENS_REQUEST = 'FETCH_TOKENS_REQUEST';
export const FETCH_TOKENS_SUCCESS = 'FETCH_TOKENS_SUCCESS';
export const FETCH_TOKENS_FAIL = 'FETCH_TOKENS_FAIL';
export const REVOKE_TOKEN_REQUEST = 'REVOKE_TOKEN_REQUEST';
export const REVOKE_TOKEN_SUCCESS = 'REVOKE_TOKEN_SUCCESS';
export const REVOKE_TOKEN_FAIL = 'REVOKE_TOKEN_FAIL';
export function fetchOAuthTokens() {
return (dispatch, getState) => {
dispatch({ type: FETCH_TOKENS_REQUEST });
return api(getState).get('/api/oauth_tokens.json').then(({ data: tokens }) => {
dispatch({ type: FETCH_TOKENS_SUCCESS, tokens });
}).catch(error => {
dispatch({ type: FETCH_TOKENS_FAIL });
});
};
}
export function revokeOAuthTokenById(id) {
return (dispatch, getState) => {
dispatch({ type: REVOKE_TOKEN_REQUEST, id });
return api(getState).delete(`/api/oauth_tokens/${id}`).then(() => {
dispatch({ type: REVOKE_TOKEN_SUCCESS, id });
}).catch(error => {
dispatch({ type: REVOKE_TOKEN_FAIL, id });
});
};
}

@ -15,10 +15,9 @@ import {
import { import {
changeEmail, changeEmail,
changePassword, changePassword,
fetchOAuthTokens,
revokeOAuthToken,
deleteAccount, deleteAccount,
} from 'soapbox/actions/auth'; } from 'soapbox/actions/auth';
import { fetchOAuthTokens, revokeOAuthTokenById } from 'soapbox/actions/security';
import { fetchUserMfaSettings } from '../../actions/mfa'; import { fetchUserMfaSettings } from '../../actions/mfa';
import snackbar from 'soapbox/actions/snackbar'; import snackbar from 'soapbox/actions/snackbar';
import { changeSetting, getSettings } from 'soapbox/actions/settings'; import { changeSetting, getSettings } from 'soapbox/actions/settings';
@ -306,7 +305,7 @@ class AuthTokenList extends ImmutablePureComponent {
handleRevoke = id => { handleRevoke = id => {
return e => { return e => {
this.props.dispatch(revokeOAuthToken(id)); this.props.dispatch(revokeOAuthTokenById(id));
}; };
} }

@ -222,7 +222,7 @@ const reducer = (state, action) => {
case AUTH_APP_CREATED: case AUTH_APP_CREATED:
return state.set('app', fromJS(action.app)); return state.set('app', fromJS(action.app));
case AUTH_APP_AUTHORIZED: case AUTH_APP_AUTHORIZED:
return state.update('app', ImmutableMap(), app => app.merge(fromJS(action.app))); return state.update('app', ImmutableMap(), app => app.merge(fromJS(action.token)));
case AUTH_LOGGED_IN: case AUTH_LOGGED_IN:
return importToken(state, action.token); return importToken(state, action.token);
case AUTH_LOGGED_OUT: case AUTH_LOGGED_OUT:

@ -1,7 +1,7 @@
import { import {
FETCH_TOKENS_SUCCESS, FETCH_TOKENS_SUCCESS,
REVOKE_TOKEN_SUCCESS, REVOKE_TOKEN_SUCCESS,
} from '../actions/auth'; } from '../actions/security';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
const initialState = ImmutableMap({ const initialState = ImmutableMap({

Loading…
Cancel
Save