diff --git a/app/soapbox/actions/auth.js b/app/soapbox/actions/auth.js index 7b357edfa..9549abead 100644 --- a/app/soapbox/actions/auth.js +++ b/app/soapbox/actions/auth.js @@ -17,6 +17,7 @@ import { getLoggedInAccount, parseBaseURL } from 'soapbox/utils/auth'; import { createApp } from 'soapbox/actions/apps'; import { obtainOAuthToken, revokeOAuthToken } from 'soapbox/actions/oauth'; import sourceCode from 'soapbox/utils/code'; +import { getFeatures } from 'soapbox/utils/features'; export const SWITCH_ACCOUNT = 'SWITCH_ACCOUNT'; @@ -36,6 +37,12 @@ export const messages = defineMessages({ const noOp = () => () => new Promise(f => f()); +const getScopes = state => { + const instance = state.get('instance'); + const { scopes } = getFeatures(instance); + return scopes; +}; + function createAppAndToken() { return (dispatch, getState) => { return dispatch(createAuthApp()).then(() => { @@ -49,7 +56,7 @@ function createAuthApp() { const params = { client_name: sourceCode.displayName, redirect_uris: 'urn:ietf:wg:oauth:2.0:oob', - scopes: 'read write follow push admin', + scopes: getScopes(getState()), website: sourceCode.homepage, }; @@ -68,6 +75,7 @@ function createAppToken() { client_secret: app.get('client_secret'), redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', grant_type: 'client_credentials', + scope: getScopes(getState()), }; return dispatch(obtainOAuthToken(params)).then(token => { @@ -87,6 +95,7 @@ function createUserToken(username, password) { grant_type: 'password', username: username, password: password, + scope: getScopes(getState()), }; return dispatch(obtainOAuthToken(params)) @@ -107,6 +116,7 @@ export function refreshUserToken() { refresh_token: refreshToken, redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', grant_type: 'refresh_token', + scope: getScopes(getState()), }; return dispatch(obtainOAuthToken(params)) diff --git a/app/soapbox/actions/external_auth.js b/app/soapbox/actions/external_auth.js index baf10e04e..f3b52650a 100644 --- a/app/soapbox/actions/external_auth.js +++ b/app/soapbox/actions/external_auth.js @@ -6,39 +6,51 @@ * @see module:soapbox/actions/oauth */ +import { baseClient } from '../api'; import { createApp } from 'soapbox/actions/apps'; import { obtainOAuthToken } from 'soapbox/actions/oauth'; import { authLoggedIn, verifyCredentials } from 'soapbox/actions/auth'; import { parseBaseURL } from 'soapbox/utils/auth'; +import { getFeatures } from 'soapbox/utils/features'; import sourceCode from 'soapbox/utils/code'; +import { fromJS } from 'immutable'; -const scope = 'read write follow push'; +const fetchExternalInstance = baseURL => { + return baseClient(null, baseURL) + .get('/api/v1/instance') + .then(({ data: instance }) => fromJS(instance)); +}; export function createAppAndRedirect(host) { return (dispatch, getState) => { const baseURL = parseBaseURL(host) || parseBaseURL(`https://${host}`); - const params = { - client_name: sourceCode.displayName, - redirect_uris: `${window.location.origin}/auth/external`, - website: sourceCode.homepage, - scopes: scope, - }; + return fetchExternalInstance(baseURL).then(instance => { + const { scopes } = getFeatures(instance); - return dispatch(createApp(params, baseURL)).then(app => { - const { client_id, redirect_uri } = app; + const params = { + client_name: sourceCode.displayName, + redirect_uris: `${window.location.origin}/auth/external`, + website: sourceCode.homepage, + scopes, + }; - const query = new URLSearchParams({ - client_id, - redirect_uri, - response_type: 'code', - scope, + return dispatch(createApp(params, baseURL)).then(app => { + const { client_id, redirect_uri } = app; + + const query = new URLSearchParams({ + client_id, + redirect_uri, + response_type: 'code', + scope: scopes, + }); + + localStorage.setItem('soapbox:external:app', JSON.stringify(app)); + localStorage.setItem('soapbox:external:baseurl', baseURL); + localStorage.setItem('soapbox:external:scopes', scopes); + + window.location.href = `${baseURL}/oauth/authorize?${query.toString()}`; }); - - localStorage.setItem('soapbox:external:app', JSON.stringify(app)); - localStorage.setItem('soapbox:external:baseurl', baseURL); - - window.location.href = `${baseURL}/oauth/authorize?${query.toString()}`; }); }; } @@ -47,6 +59,7 @@ export function loginWithCode(code) { return (dispatch, getState) => { const { client_id, client_secret, redirect_uri } = JSON.parse(localStorage.getItem('soapbox:external:app')); const baseURL = localStorage.getItem('soapbox:external:baseurl'); + const scope = localStorage.getItem('soapbox:external:scopes'); const params = { client_id, diff --git a/app/soapbox/utils/features.js b/app/soapbox/utils/features.js index 9b520c78c..2daa50546 100644 --- a/app/soapbox/utils/features.js +++ b/app/soapbox/utils/features.js @@ -17,6 +17,7 @@ export const getFeatures = createSelector([ importMutes: v.software === 'Pleroma' && gte(v.version, '2.2.0'), emailList: f.includes('email_list'), chats: v.software === 'Pleroma' && gte(v.version, '2.1.0'), + scopes: v.software === 'Pleroma' ? 'read write follow push admin' : 'read write follow push', }; });