diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/AuthorizationCode/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/AuthorizationCode/index.js index 8f3dc160..c409afae 100644 --- a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/AuthorizationCode/index.js +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/AuthorizationCode/index.js @@ -6,9 +6,10 @@ import SingleLineEditor from 'components/SingleLineEditor'; import { saveCollectionRoot, sendCollectionOauth2Request } from 'providers/ReduxStore/slices/collections/actions'; import StyledWrapper from './StyledWrapper'; import { inputsConfig } from './inputsConfig'; -import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections/index'; -import { clearOauth2Cache } from 'utils/network/index'; +import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections'; +import { clearOauth2Cache } from 'utils/network'; import toast from 'react-hot-toast'; +import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector'; const OAuth2AuthorizationCode = ({ collection }) => { const dispatch = useDispatch(); @@ -22,7 +23,17 @@ const OAuth2AuthorizationCode = ({ collection }) => { const handleSave = () => dispatch(saveCollectionRoot(collection.uid)); - const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, state, pkce } = oAuth; + const { + callbackUrl, + authorizationUrl, + accessTokenUrl, + clientId, + clientSecret, + clientSecretMethod, + scope, + state, + pkce + } = oAuth; const handleChange = (key, value) => { dispatch( @@ -36,6 +47,7 @@ const OAuth2AuthorizationCode = ({ collection }) => { accessTokenUrl, clientId, clientSecret, + clientSecretMethod, scope, state, pkce, @@ -57,6 +69,7 @@ const OAuth2AuthorizationCode = ({ collection }) => { accessTokenUrl, clientId, clientSecret, + clientSecretMethod, scope, state, pkce: !Boolean(oAuth?.['pkce']) @@ -105,6 +118,7 @@ const OAuth2AuthorizationCode = ({ collection }) => { onChange={handlePKCEToggle} /> +
); })} + diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/PasswordCredentials/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/PasswordCredentials/index.js index d2d9eed1..a30139e4 100644 --- a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/PasswordCredentials/index.js +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/PasswordCredentials/index.js @@ -6,7 +6,8 @@ import SingleLineEditor from 'components/SingleLineEditor'; import { saveCollectionRoot, sendCollectionOauth2Request } from 'providers/ReduxStore/slices/collections/actions'; import StyledWrapper from './StyledWrapper'; import { inputsConfig } from './inputsConfig'; -import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections/index'; +import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections'; +import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector'; const OAuth2AuthorizationCode = ({ item, collection }) => { const dispatch = useDispatch(); @@ -20,7 +21,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { const handleSave = () => dispatch(saveCollectionRoot(collection.uid)); - const { accessTokenUrl, username, password, clientId, clientSecret, scope } = oAuth; + const { accessTokenUrl, username, password, clientId, clientSecret, clientSecretMethod, scope } = oAuth; const handleChange = (key, value) => { dispatch( @@ -34,6 +35,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { password, clientId, clientSecret, + clientSecretMethod, scope, [key]: value } @@ -62,6 +64,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { ); })} + diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AuthorizationCode/index.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AuthorizationCode/index.js index 2bb5dcc3..495cb10e 100644 --- a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AuthorizationCode/index.js +++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AuthorizationCode/index.js @@ -7,8 +7,9 @@ import { updateAuth } from 'providers/ReduxStore/slices/collections'; import { saveRequest, sendRequest } from 'providers/ReduxStore/slices/collections/actions'; import StyledWrapper from './StyledWrapper'; import { inputsConfig } from './inputsConfig'; -import { clearOauth2Cache } from 'utils/network/index'; +import { clearOauth2Cache } from 'utils/network'; import toast from 'react-hot-toast'; +import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector'; const OAuth2AuthorizationCode = ({ item, collection }) => { const dispatch = useDispatch(); @@ -22,7 +23,17 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { const handleSave = () => dispatch(saveRequest(item.uid, collection.uid)); - const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, state, pkce } = oAuth; + const { + callbackUrl, + authorizationUrl, + accessTokenUrl, + clientId, + clientSecret, + clientSecretMethod, + scope, + state, + pkce + } = oAuth; const handleChange = (key, value) => { dispatch( @@ -37,6 +48,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { accessTokenUrl, clientId, clientSecret, + clientSecretMethod, state, scope, pkce, @@ -59,6 +71,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { accessTokenUrl, clientId, clientSecret, + clientSecretMethod, state, scope, pkce: !Boolean(oAuth?.['pkce']) @@ -108,6 +121,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { onChange={handlePKCEToggle} /> +
); })} + diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector/StyledWrapper.js new file mode 100644 index 00000000..2ae9cbf1 --- /dev/null +++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector/StyledWrapper.js @@ -0,0 +1,25 @@ +import styled from 'styled-components'; + +const Wrapper = styled.div` + font-size: 0.8125rem; + + .client-credentials-secret-mode-selector { + padding: 0.5rem 0px; + border-radius: 3px; + border: solid 1px ${(props) => props.theme.input.border}; + background-color: ${(props) => props.theme.input.bg}; + + .client-credentials-secret-label { + width: fit-content; + color: ${(props) => props.theme.colors.text.yellow}; + justify-content: space-between; + padding: 0 0.5rem; + } + + .dropdown-item { + padding: 0.2rem 0.6rem !important; + } + } +`; + +export default Wrapper; diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector/index.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector/index.js new file mode 100644 index 00000000..2a309d0f --- /dev/null +++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector/index.js @@ -0,0 +1,82 @@ +import React, { forwardRef, useEffect, useRef } from 'react'; +import Dropdown from 'components/Dropdown'; +import StyledWrapper from './StyledWrapper'; +import { IconCaretDown } from '@tabler/icons'; +import { updateAuth, updateCollectionAuth } from 'providers/ReduxStore/slices/collections'; +import { useDispatch } from 'react-redux'; +import { humanizeOAuth2ClientSecretMethod } from 'utils/collections'; + +const ClientCredentialsMethodSelector = ({ item, collection, oAuth }) => { + const clientSecretMethods = ['client_credentials_basic', 'client_credentials_post']; + + const dispatch = useDispatch(); + const dropDownRef = useRef(); + const onDropdownCreate = (ref) => (dropDownRef.current = ref); + + const Icon = forwardRef((props, ref) => { + return ( +
+ {humanizeOAuth2ClientSecretMethod(oAuth?.clientSecretMethod)}{' '} + +
+ ); + }); + + const onClientSecretMethodChange = (clientSecretMethod) => { + if (item) { + // Update request level authorization + dispatch( + updateAuth({ + mode: 'oauth2', + collectionUid: collection.uid, + itemUid: item.uid, + content: { + ...oAuth, + clientSecretMethod: clientSecretMethod + } + }) + ); + } else { + // Update collection level authorization + dispatch( + updateCollectionAuth({ + mode: 'oauth2', + collectionUid: collection.uid, + content: { + ...oAuth, + clientSecretMethod: clientSecretMethod + } + }) + ); + } + }; + + useEffect(() => { + !oAuth?.clientSecretMethod && onClientSecretMethodChange(clientSecretMethods[0]); + }, [oAuth.clientSecretMethod]); + + return ( + + +
+ } placement="bottom-end"> + {clientSecretMethods.map((item, index) => ( +
{ + dropDownRef.current.hide(); + onClientSecretMethodChange(item); + }} + > + {' '} + {humanizeOAuth2ClientSecretMethod(item)} + {index === 0 ? ` (Default)` : ``} +
+ ))} +
+
+
+ ); +}; +export default ClientCredentialsMethodSelector; diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/PasswordCredentials/index.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/PasswordCredentials/index.js index 4ec8c1fa..b041ba86 100644 --- a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/PasswordCredentials/index.js +++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/PasswordCredentials/index.js @@ -7,6 +7,7 @@ import { updateAuth } from 'providers/ReduxStore/slices/collections'; import { saveRequest, sendRequest } from 'providers/ReduxStore/slices/collections/actions'; import StyledWrapper from './StyledWrapper'; import { inputsConfig } from './inputsConfig'; +import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector'; const OAuth2AuthorizationCode = ({ item, collection }) => { const dispatch = useDispatch(); @@ -20,7 +21,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { const handleSave = () => dispatch(saveRequest(item.uid, collection.uid)); - const { accessTokenUrl, username, password, clientId, clientSecret, scope } = oAuth; + const { accessTokenUrl, username, password, clientId, clientSecret, clientSecretMethod, scope } = oAuth; const handleChange = (key, value) => { dispatch( @@ -35,6 +36,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { password, clientId, clientSecret, + clientSecretMethod, scope, [key]: value } @@ -64,6 +66,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => { ); })} + diff --git a/packages/bruno-app/src/utils/collections/index.js b/packages/bruno-app/src/utils/collections/index.js index ea8712be..7c5f6f43 100644 --- a/packages/bruno-app/src/utils/collections/index.js +++ b/packages/bruno-app/src/utils/collections/index.js @@ -723,6 +723,22 @@ export const humanizeGrantType = (mode) => { return label; }; +export const humanizeOAuth2ClientSecretMethod = (mode) => { + let label = 'N/A'; + switch (mode) { + case 'client_credentials_basic': { + label = 'As Basic Auth Header'; + break; + } + case 'client_credentials_post': { + label = 'In Request Body'; + break; + } + } + + return label; +}; + export const refreshUidsInItem = (item) => { item.uid = uuid();