Support only external Ethereum auth for now
This commit is contained in:
parent
01dd53328b
commit
abcd55752d
|
@ -213,36 +213,6 @@ export function logIn(intl, username, password) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ethereumLogin(instance, baseURL) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
instance = (instance || getState().get('instance'));
|
|
||||||
|
|
||||||
const { ethereum } = window;
|
|
||||||
const { scopes } = getFeatures(instance);
|
|
||||||
const loginMessage = instance.get('login_message');
|
|
||||||
|
|
||||||
return ethereum.request({ method: 'eth_requestAccounts' }).then(walletAddresses => {
|
|
||||||
const [walletAddress] = walletAddresses;
|
|
||||||
|
|
||||||
return ethereum.request({ method: 'personal_sign', params: [loginMessage, walletAddress] }).then(signature => {
|
|
||||||
const params = {
|
|
||||||
grant_type: 'ethereum',
|
|
||||||
wallet_address: walletAddress.toLowerCase(),
|
|
||||||
password: signature,
|
|
||||||
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
|
||||||
scope: scopes,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Note: skips app creation
|
|
||||||
// TODO: add to quirks.js for Mitra
|
|
||||||
return dispatch(obtainOAuthToken(params, baseURL))
|
|
||||||
.then(token => dispatch(authLoggedIn(token)))
|
|
||||||
.then(({ access_token }) => dispatch(verifyCredentials(access_token, baseURL)));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function logOut(intl) {
|
export function logOut(intl) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
|
@ -9,10 +9,11 @@
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
import { createApp } from 'soapbox/actions/apps';
|
import { createApp } from 'soapbox/actions/apps';
|
||||||
import { authLoggedIn, verifyCredentials, switchAccount, ethereumLogin } from 'soapbox/actions/auth';
|
import { authLoggedIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth';
|
||||||
import { obtainOAuthToken } from 'soapbox/actions/oauth';
|
import { obtainOAuthToken } from 'soapbox/actions/oauth';
|
||||||
import { parseBaseURL } from 'soapbox/utils/auth';
|
import { parseBaseURL } from 'soapbox/utils/auth';
|
||||||
import sourceCode from 'soapbox/utils/code';
|
import sourceCode from 'soapbox/utils/code';
|
||||||
|
import { getWalletAndSign } from 'soapbox/utils/ethereum';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
import { getFeatures } from 'soapbox/utils/features';
|
||||||
import { getQuirks } from 'soapbox/utils/quirks';
|
import { getQuirks } from 'soapbox/utils/quirks';
|
||||||
|
|
||||||
|
@ -35,6 +36,9 @@ const fetchExternalInstance = baseURL => {
|
||||||
|
|
||||||
function createExternalApp(instance, baseURL) {
|
function createExternalApp(instance, baseURL) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
|
// Mitra: skip creating the auth app
|
||||||
|
if (getQuirks(instance).noApps) return new Promise(f => f({}));
|
||||||
|
|
||||||
const { scopes } = getFeatures(instance);
|
const { scopes } = getFeatures(instance);
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
|
@ -71,11 +75,29 @@ function externalAuthorize(instance, baseURL) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function externalEthereumLogin(instance, baseURL) {
|
export function externalEthereumLogin(instance, baseURL) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
return dispatch(ethereumLogin(instance, baseURL))
|
const loginMessage = instance.get('login_message');
|
||||||
.then(account => dispatch(switchAccount(account.id)))
|
|
||||||
.then(() => window.location.href = '/');
|
return getWalletAndSign(loginMessage).then(({ wallet, signature }) => {
|
||||||
|
return dispatch(createExternalApp(instance, baseURL)).then(app => {
|
||||||
|
const params = {
|
||||||
|
grant_type: 'ethereum',
|
||||||
|
wallet_address: wallet.toLowerCase(),
|
||||||
|
client_id: app.client_id,
|
||||||
|
client_secret: app.client_secret,
|
||||||
|
password: signature,
|
||||||
|
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
||||||
|
scope: getFeatures(instance).scopes,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dispatch(obtainOAuthToken(params, baseURL))
|
||||||
|
.then(token => dispatch(authLoggedIn(token)))
|
||||||
|
.then(({ access_token }) => dispatch(verifyCredentials(access_token, baseURL)))
|
||||||
|
.then(account => dispatch(switchAccount(account.id)))
|
||||||
|
.then(() => window.location.href = '/');
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +109,7 @@ export function externalLogin(host) {
|
||||||
const features = getFeatures(instance);
|
const features = getFeatures(instance);
|
||||||
const quirks = getQuirks(instance);
|
const quirks = getQuirks(instance);
|
||||||
|
|
||||||
if (features.ethereumLogin && quirks.ethereumLoginOnly) {
|
if (features.ethereumLogin && quirks.noOAuthForm) {
|
||||||
return dispatch(externalEthereumLogin(instance, baseURL));
|
return dispatch(externalEthereumLogin(instance, baseURL));
|
||||||
} else {
|
} else {
|
||||||
return dispatch(externalAuthorize(instance, baseURL));
|
return dispatch(externalAuthorize(instance, baseURL));
|
||||||
|
|
|
@ -50,7 +50,7 @@ const initialState = ImmutableMap({
|
||||||
|
|
||||||
// Build Mastodon configuration from Pleroma instance
|
// Build Mastodon configuration from Pleroma instance
|
||||||
const pleromaToMastodonConfig = instance => {
|
const pleromaToMastodonConfig = instance => {
|
||||||
return {
|
return ImmutableMap({
|
||||||
statuses: ImmutableMap({
|
statuses: ImmutableMap({
|
||||||
max_characters: instance.get('max_toot_chars'),
|
max_characters: instance.get('max_toot_chars'),
|
||||||
}),
|
}),
|
||||||
|
@ -60,7 +60,7 @@ const pleromaToMastodonConfig = instance => {
|
||||||
min_expiration: instance.getIn(['poll_limits', 'min_expiration']),
|
min_expiration: instance.getIn(['poll_limits', 'min_expiration']),
|
||||||
max_expiration: instance.getIn(['poll_limits', 'max_expiration']),
|
max_expiration: instance.getIn(['poll_limits', 'max_expiration']),
|
||||||
}),
|
}),
|
||||||
};
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use new value only if old value is undefined
|
// Use new value only if old value is undefined
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
export const ethereum = () => window.ethereum;
|
||||||
|
|
||||||
|
export const hasEthereum = () => Boolean(ethereum());
|
||||||
|
|
||||||
|
// Requests an Ethereum wallet from the browser
|
||||||
|
// Returns a Promise containing the Ethereum wallet address (string).
|
||||||
|
export const getWallet = () => {
|
||||||
|
return ethereum().request({ method: 'eth_requestAccounts' })
|
||||||
|
.then(wallets => wallets[0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Asks the browser to sign a message with Ethereum.
|
||||||
|
// Returns a Promise containing the signature (string).
|
||||||
|
export const signMessage = (wallet, message) => {
|
||||||
|
return ethereum().request({ method: 'personal_sign', params: [message, wallet] });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Combines the above functions.
|
||||||
|
// Returns an object with the `wallet` and `signature`
|
||||||
|
export const getWalletAndSign = message => {
|
||||||
|
return getWallet().then(wallet => {
|
||||||
|
return signMessage(wallet, message).then(signature => {
|
||||||
|
return { wallet, signature };
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
|
@ -8,7 +8,8 @@ export const getQuirks = createSelector([
|
||||||
], (v) => {
|
], (v) => {
|
||||||
return {
|
return {
|
||||||
invertedPagination: v.software === PLEROMA,
|
invertedPagination: v.software === PLEROMA,
|
||||||
ethereumLoginOnly: v.software === MITRA,
|
noApps: v.software === MITRA,
|
||||||
|
noOAuthForm: v.software === MITRA,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue