diff --git a/app/soapbox/actions/consumer-auth.ts b/app/soapbox/actions/consumer-auth.ts new file mode 100644 index 000000000..b669c6393 --- /dev/null +++ b/app/soapbox/actions/consumer-auth.ts @@ -0,0 +1,55 @@ +import axios from 'axios'; + +import * as BuildConfig from 'soapbox/build_config'; +import { isURL } from 'soapbox/utils/auth'; +import sourceCode from 'soapbox/utils/code'; +import { getFeatures } from 'soapbox/utils/features'; + +import { createApp } from './apps'; + +import type { AppDispatch, RootState } from 'soapbox/store'; + +const createProviderApp = () => { + return async(dispatch: AppDispatch, getState: () => RootState) => { + const state = getState(); + const { scopes } = getFeatures(state.instance); + + const params = { + client_name: sourceCode.displayName, + redirect_uris: `${window.location.origin}/login/external`, + website: sourceCode.homepage, + scopes, + }; + + return dispatch(createApp(params)); + }; +}; + +export const prepareRequest = (provider: string) => { + return async(dispatch: AppDispatch, getState: () => RootState) => { + const baseURL = isURL(BuildConfig.BACKEND_URL) ? BuildConfig.BACKEND_URL : ''; + + const state = getState(); + const { scopes } = getFeatures(state.instance); + const app = await dispatch(createProviderApp()); + const { client_id, redirect_uri } = app; + + localStorage.setItem('soapbox:external:app', JSON.stringify(app)); + localStorage.setItem('soapbox:external:baseurl', baseURL); + localStorage.setItem('soapbox:external:scopes', scopes); + + const params = { + provider, + authorization: { + client_id, + redirect_uri, + scope: scopes, + }, + }; + + const formdata = axios.toFormData(params); + const query = new URLSearchParams(formdata as any); + + location.href = `${baseURL}/oauth/prepare_request?${query.toString()}`; + }; +}; diff --git a/app/soapbox/features/auth_login/components/consumer-button.tsx b/app/soapbox/features/auth_login/components/consumer-button.tsx index 63ca9d3df..8ce78e799 100644 --- a/app/soapbox/features/auth_login/components/consumer-button.tsx +++ b/app/soapbox/features/auth_login/components/consumer-button.tsx @@ -1,7 +1,9 @@ import React from 'react'; import { useIntl, defineMessages } from 'react-intl'; +import { prepareRequest } from 'soapbox/actions/consumer-auth'; import { IconButton, Tooltip } from 'soapbox/components/ui'; +import { useAppDispatch } from 'soapbox/hooks'; const messages = defineMessages({ tooltip: { id: 'oauth_consumer.tooltip', defaultMessage: 'Sign in with {provider}' }, @@ -30,14 +32,21 @@ interface IConsumerButton { /** OAuth consumer button for logging in with a third-party service. */ const ConsumerButton: React.FC = ({ provider }) => { const intl = useIntl(); + const dispatch = useAppDispatch(); + const icon = BRAND_ICONS[provider] || require('@tabler/icons/key.svg'); + const handleClick = () => { + dispatch(prepareRequest(provider)); + }; + return ( );