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();