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 9db8ab84fb..1e75b4fb44 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,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 = ({ collection }) => {
const dispatch = useDispatch();
@@ -20,7 +21,8 @@ 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(
@@ -34,6 +36,7 @@ const OAuth2AuthorizationCode = ({ collection }) => {
accessTokenUrl,
clientId,
clientSecret,
+ clientSecretMethod,
scope,
state,
pkce,
@@ -55,6 +58,7 @@ const OAuth2AuthorizationCode = ({ collection }) => {
accessTokenUrl,
clientId,
clientSecret,
+ clientSecretMethod,
scope,
state,
pkce: !Boolean(oAuth?.['pkce'])
@@ -92,6 +96,7 @@ const OAuth2AuthorizationCode = ({ collection }) => {
onChange={handlePKCEToggle}
/>
+
);
};
diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/ClientCredentials/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/ClientCredentials/index.js
index 856e9373eb..a71d5c167c 100644
--- a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/ClientCredentials/index.js
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/ClientCredentials/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 OAuth2ClientCredentials = ({ collection }) => {
const dispatch = useDispatch();
@@ -20,7 +21,7 @@ const OAuth2ClientCredentials = ({ collection }) => {
const handleSave = () => dispatch(saveCollectionRoot(collection.uid));
- const { accessTokenUrl, clientId, clientSecret, scope } = oAuth;
+ const { accessTokenUrl, clientId, clientSecret, clientSecretMethod, scope } = oAuth;
const handleChange = (key, value) => {
dispatch(
@@ -32,6 +33,7 @@ const OAuth2ClientCredentials = ({ collection }) => {
accessTokenUrl,
clientId,
clientSecret,
+ clientSecretMethod,
scope,
[key]: value
}
@@ -60,6 +62,7 @@ const OAuth2ClientCredentials = ({ collection }) => {
);
})}
+
);
};
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 068f0070c4..912546adfc 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
@@ -7,6 +7,7 @@ import { saveCollectionRoot, sendCollectionOauth2Request } from 'providers/Redux
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections';
+import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector';
const OAuth2PasswordCredentials = ({ collection }) => {
const dispatch = useDispatch();
@@ -20,7 +21,7 @@ const OAuth2PasswordCredentials = ({ 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 OAuth2PasswordCredentials = ({ collection }) => {
password,
clientId,
clientSecret,
+ clientSecretMethod,
scope,
[key]: value
}
@@ -62,6 +64,7 @@ const OAuth2PasswordCredentials = ({ 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 0265ddbe43..2069d5e5dd 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,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,8 @@ 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(
@@ -35,6 +37,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
accessTokenUrl,
clientId,
clientSecret,
+ clientSecretMethod,
state,
scope,
pkce,
@@ -57,6 +60,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
accessTokenUrl,
clientId,
clientSecret,
+ clientSecretMethod,
state,
scope,
pkce: !Boolean(oAuth?.['pkce'])
@@ -96,6 +100,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
onChange={handlePKCEToggle}
/>
+
);
};
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentials/index.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentials/index.js
index 1bbee2253c..c098f0462e 100644
--- a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentials/index.js
+++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentials/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 OAuth2ClientCredentials = ({ item, collection }) => {
const dispatch = useDispatch();
@@ -20,7 +21,7 @@ const OAuth2ClientCredentials = ({ item, collection }) => {
const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));
- const { accessTokenUrl, clientId, clientSecret, scope } = oAuth;
+ const { accessTokenUrl, clientId, clientSecret, clientSecretMethod, scope } = oAuth;
const handleChange = (key, value) => {
dispatch(
@@ -33,6 +34,7 @@ const OAuth2ClientCredentials = ({ item, collection }) => {
accessTokenUrl,
clientId,
clientSecret,
+ clientSecretMethod,
scope,
[key]: value
}
@@ -62,6 +64,7 @@ const OAuth2ClientCredentials = ({ item, collection }) => {
);
})}
+
);
};
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 0000000000..2ae9cbf12e
--- /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 0000000000..a4c881155f
--- /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 authentication
+ dispatch(
+ updateAuth({
+ mode: 'oauth2',
+ collectionUid: collection.uid,
+ itemUid: item.uid,
+ content: {
+ ...oAuth,
+ clientSecretMethod: clientSecretMethod
+ }
+ })
+ );
+ } else {
+ // Update collection level authentication
+ 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 6911c6457d..962e4d6675 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
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React from 'react';
import get from 'lodash/get';
import { useTheme } from 'providers/Theme';
import { useDispatch } from 'react-redux';
@@ -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 OAuth2PasswordCredentials = ({ item, collection }) => {
const dispatch = useDispatch();
@@ -20,7 +21,7 @@ const OAuth2PasswordCredentials = ({ 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 OAuth2PasswordCredentials = ({ item, collection }) => {
password,
clientId,
clientSecret,
+ clientSecretMethod,
scope,
[key]: value
}
@@ -64,6 +66,7 @@ const OAuth2PasswordCredentials = ({ item, collection }) => {
);
})}
+
);
};
diff --git a/packages/bruno-app/src/utils/collections/index.js b/packages/bruno-app/src/utils/collections/index.js
index d770c60a3c..b09f5aa09d 100644
--- a/packages/bruno-app/src/utils/collections/index.js
+++ b/packages/bruno-app/src/utils/collections/index.js
@@ -181,7 +181,7 @@ export const moveCollectionItemToRootOfCollection = (collection, draggedItem) =>
draggedItemParent.items = filter(draggedItemParent.items, (i) => i.uid !== draggedItem.uid);
collection.items = sortBy(collection.items, (item) => item.seq);
collection.items.push(draggedItem);
- if (draggedItem.type == 'folder') {
+ if (draggedItem.type === 'folder') {
draggedItem.pathname = path.join(collection.pathname, draggedItem.name);
} else {
draggedItem.pathname = path.join(collection.pathname, draggedItem.filename);
@@ -733,6 +733,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();
diff --git a/packages/bruno-electron/src/ipc/network/interpolate-vars.js b/packages/bruno-electron/src/ipc/network/interpolate-vars.js
index 9478abf495..827f1b69b6 100644
--- a/packages/bruno-electron/src/ipc/network/interpolate-vars.js
+++ b/packages/bruno-electron/src/ipc/network/interpolate-vars.js
@@ -156,20 +156,15 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
}
if (request?.oauth2?.grantType) {
- let username, password, scope, clientId, clientSecret;
switch (request.oauth2.grantType) {
case 'password':
- username = _interpolate(request.oauth2.username) || '';
- password = _interpolate(request.oauth2.password) || '';
- clientId = _interpolate(request.oauth2.clientId) || '';
- clientSecret = _interpolate(request.oauth2.clientSecret) || '';
- scope = _interpolate(request.oauth2.scope) || '';
request.oauth2.accessTokenUrl = _interpolate(request.oauth2.accessTokenUrl) || '';
- request.oauth2.username = username;
- request.oauth2.password = password;
- request.oauth2.clientId = clientId;
- request.oauth2.clientSecret = clientSecret;
- request.oauth2.scope = scope;
+ request.oauth2.username = _interpolate(request.oauth2.username) || '';
+ request.oauth2.password = _interpolate(request.oauth2.password) || '';
+ request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
+ request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
+ request.oauth2.clientSecretMethod = _interpolate(request.oauth2.clientSecretMethod) || '';
+ request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
break;
case 'authorization_code':
request.oauth2.callbackUrl = _interpolate(request.oauth2.callbackUrl) || '';
@@ -177,18 +172,17 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
request.oauth2.accessTokenUrl = _interpolate(request.oauth2.accessTokenUrl) || '';
request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
+ request.oauth2.clientSecretMethod = _interpolate(request.oauth2.clientSecretMethod) || '';
request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
request.oauth2.state = _interpolate(request.oauth2.state) || '';
request.oauth2.pkce = _interpolate(request.oauth2.pkce) || false;
break;
case 'client_credentials':
- clientId = _interpolate(request.oauth2.clientId) || '';
- clientSecret = _interpolate(request.oauth2.clientSecret) || '';
- scope = _interpolate(request.oauth2.scope) || '';
request.oauth2.accessTokenUrl = _interpolate(request.oauth2.accessTokenUrl) || '';
- request.oauth2.clientId = clientId;
- request.oauth2.clientSecret = clientSecret;
- request.oauth2.scope = scope;
+ request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
+ request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
+ request.oauth2.clientSecretMethod = _interpolate(request.oauth2.clientSecretMethod) || '';
+ request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
break;
default:
break;
diff --git a/packages/bruno-electron/src/ipc/network/oauth2-helper.js b/packages/bruno-electron/src/ipc/network/oauth2-helper.js
index cdff9627d5..d27ed785eb 100644
--- a/packages/bruno-electron/src/ipc/network/oauth2-helper.js
+++ b/packages/bruno-electron/src/ipc/network/oauth2-helper.js
@@ -6,6 +6,22 @@ const { makeAxiosInstance } = require('./axios-instance');
const oauth2Store = new Oauth2Store();
+const setClientCredentials = (clientId, clientSecret, clientSecretMethod, request) => {
+ if (clientSecret) {
+ switch (clientSecretMethod) {
+ case 'client_credentials_post': {
+ request.data["client_id"] = clientId;
+ request.data["client_secret"] = clientSecret;
+ break;
+ }
+ case 'client_credentials_basic': {
+ request.headers["Authorization"] = 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64');
+ break;
+ }
+ }
+ }
+};
+
const generateCodeVerifier = () => {
return crypto.randomBytes(22).toString('hex');
};
@@ -44,13 +60,12 @@ const oauth2AuthorizeWithAuthorizationCode = async (request, collectionUid) => {
let requestCopy = cloneDeep(request);
const { authorizationCode } = await getOAuth2AuthorizationCode(requestCopy, codeChallenge, collectionUid);
const oAuth = get(requestCopy, 'oauth2', {});
- const { clientId, clientSecret, callbackUrl, pkce } = oAuth;
+ const { clientId, clientSecret, clientSecretMethod, callbackUrl, pkce } = oAuth;
+
const data = {
grant_type: 'authorization_code',
code: authorizationCode,
- redirect_uri: callbackUrl,
- client_id: clientId,
- client_secret: clientSecret
+ redirect_uri: callbackUrl
};
if (pkce) {
data['code_verifier'] = codeVerifier;
@@ -61,6 +76,8 @@ const oauth2AuthorizeWithAuthorizationCode = async (request, collectionUid) => {
request.data = data;
request.url = request?.oauth2?.accessTokenUrl;
+ setClientCredentials(clientId, clientSecret, clientSecretMethod, request);
+
const axiosInstance = makeAxiosInstance();
const response = await axiosInstance(request);
const credentials = JSON.parse(response.data);
@@ -113,11 +130,9 @@ const oauth2AuthorizeWithClientCredentials = async (request, collectionUid) => {
let requestCopy = cloneDeep(request);
const oAuth = get(requestCopy, 'oauth2', {});
- const { clientId, clientSecret, scope } = oAuth;
+ const { clientId, clientSecret, clientSecretMethod, scope } = oAuth;
const data = {
- grant_type: 'client_credentials',
- client_id: clientId,
- client_secret: clientSecret
+ grant_type: 'client_credentials'
};
if (scope) {
data.scope = scope;
@@ -128,6 +143,8 @@ const oauth2AuthorizeWithClientCredentials = async (request, collectionUid) => {
request.data = data;
request.url = request?.oauth2?.accessTokenUrl;
+ setClientCredentials(clientId, clientSecret, clientSecretMethod, request);
+
const axiosInstance = makeAxiosInstance();
let response = await axiosInstance(request);
let credentials = JSON.parse(response.data);
@@ -145,13 +162,11 @@ const oauth2AuthorizeWithPasswordCredentials = async (request, collectionUid) =>
}
const oAuth = get(request, 'oauth2', {});
- const { username, password, clientId, clientSecret, scope } = oAuth;
+ const { username, password, clientId, clientSecret, clientSecretMethod, scope } = oAuth;
const data = {
grant_type: 'password',
username,
- password,
- client_id: clientId,
- client_secret: clientSecret
+ password
};
if (scope) {
data.scope = scope;
@@ -162,6 +177,8 @@ const oauth2AuthorizeWithPasswordCredentials = async (request, collectionUid) =>
request.data = data;
request.url = request?.oauth2?.accessTokenUrl;
+ setClientCredentials(clientId, clientSecret, clientSecretMethod, request);
+
const axiosInstance = makeAxiosInstance();
let response = await axiosInstance(request);
let credentials = JSON.parse(response.data);
diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js
index 6b27d32d30..5df02098fb 100644
--- a/packages/bruno-electron/src/ipc/network/prepare-request.js
+++ b/packages/bruno-electron/src/ipc/network/prepare-request.js
@@ -103,6 +103,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
password: get(request, 'auth.oauth2.password'),
clientId: get(request, 'auth.oauth2.clientId'),
clientSecret: get(request, 'auth.oauth2.clientSecret'),
+ clientSecretMethod: get(request, 'auth.oauth2.clientSecretMethod'),
scope: get(request, 'auth.oauth2.scope')
};
break;
@@ -114,6 +115,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
accessTokenUrl: get(request, 'auth.oauth2.accessTokenUrl'),
clientId: get(request, 'auth.oauth2.clientId'),
clientSecret: get(request, 'auth.oauth2.clientSecret'),
+ clientSecretMethod: get(request, 'auth.oauth2.clientSecretMethod'),
scope: get(request, 'auth.oauth2.scope'),
state: get(request, 'auth.oauth2.state'),
pkce: get(request, 'auth.oauth2.pkce')
@@ -125,6 +127,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
accessTokenUrl: get(request, 'auth.oauth2.accessTokenUrl'),
clientId: get(request, 'auth.oauth2.clientId'),
clientSecret: get(request, 'auth.oauth2.clientSecret'),
+ clientSecretMethod: get(request, 'auth.oauth2.clientSecretMethod'),
scope: get(request, 'auth.oauth2.scope')
};
break;
diff --git a/packages/bruno-lang/v2/src/bruToJson.js b/packages/bruno-lang/v2/src/bruToJson.js
index 228691c1b2..1651d4544b 100644
--- a/packages/bruno-lang/v2/src/bruToJson.js
+++ b/packages/bruno-lang/v2/src/bruToJson.js
@@ -460,6 +460,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
const accessTokenUrlKey = _.find(auth, { name: 'access_token_url' });
const clientIdKey = _.find(auth, { name: 'client_id' });
const clientSecretKey = _.find(auth, { name: 'client_secret' });
+ const clientSecretMethodKey = _.find(auth, { name: 'client_secret_method' });
const scopeKey = _.find(auth, { name: 'scope' });
const stateKey = _.find(auth, { name: 'state' });
const pkceKey = _.find(auth, { name: 'pkce' });
@@ -474,6 +475,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
password: passwordKey ? passwordKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
clientSecret: clientSecretKey ? clientSecretKey.value : '',
+ clientSecretMethod: clientSecretMethodKey ? clientSecretMethodKey.value : '',
scope: scopeKey ? scopeKey.value : ''
}
: grantTypeKey?.value && grantTypeKey?.value == 'authorization_code'
@@ -484,6 +486,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
accessTokenUrl: accessTokenUrlKey ? accessTokenUrlKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
clientSecret: clientSecretKey ? clientSecretKey.value : '',
+ clientSecretMethod: clientSecretMethodKey ? clientSecretMethodKey.value : '',
scope: scopeKey ? scopeKey.value : '',
state: stateKey ? stateKey.value : '',
pkce: pkceKey ? JSON.parse(pkceKey?.value || false) : false
@@ -494,6 +497,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
accessTokenUrl: accessTokenUrlKey ? accessTokenUrlKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
clientSecret: clientSecretKey ? clientSecretKey.value : '',
+ clientSecretMethod: clientSecretMethodKey ? clientSecretMethodKey.value : '',
scope: scopeKey ? scopeKey.value : ''
}
: {}
diff --git a/packages/bruno-lang/v2/src/collectionBruToJson.js b/packages/bruno-lang/v2/src/collectionBruToJson.js
index 5180f0193d..2591890739 100644
--- a/packages/bruno-lang/v2/src/collectionBruToJson.js
+++ b/packages/bruno-lang/v2/src/collectionBruToJson.js
@@ -255,6 +255,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
const accessTokenUrlKey = _.find(auth, { name: 'access_token_url' });
const clientIdKey = _.find(auth, { name: 'client_id' });
const clientSecretKey = _.find(auth, { name: 'client_secret' });
+ const clientSecretMethodKey = _.find(auth, { name: 'client_secret_method' });
const scopeKey = _.find(auth, { name: 'scope' });
const stateKey = _.find(auth, { name: 'state' });
const pkceKey = _.find(auth, { name: 'pkce' });
@@ -269,6 +270,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
password: passwordKey ? passwordKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
clientSecret: clientSecretKey ? clientSecretKey.value : '',
+ clientSecretMethod: clientSecretMethodKey ? clientSecretMethodKey.value : '',
scope: scopeKey ? scopeKey.value : ''
}
: grantTypeKey?.value && grantTypeKey?.value == 'authorization_code'
@@ -279,6 +281,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
accessTokenUrl: accessTokenUrlKey ? accessTokenUrlKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
clientSecret: clientSecretKey ? clientSecretKey.value : '',
+ clientSecretMethod: clientSecretMethodKey ? clientSecretMethodKey.value : '',
scope: scopeKey ? scopeKey.value : '',
state: stateKey ? stateKey.value : '',
pkce: pkceKey ? JSON.parse(pkceKey?.value || false) : false
@@ -289,6 +292,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
accessTokenUrl: accessTokenUrlKey ? accessTokenUrlKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
clientSecret: clientSecretKey ? clientSecretKey.value : '',
+ clientSecretMethod: clientSecretMethodKey ? clientSecretMethodKey.value : '',
scope: scopeKey ? scopeKey.value : ''
}
: {}
diff --git a/packages/bruno-lang/v2/src/jsonToBru.js b/packages/bruno-lang/v2/src/jsonToBru.js
index 5c8a573b62..8bca9abfcc 100644
--- a/packages/bruno-lang/v2/src/jsonToBru.js
+++ b/packages/bruno-lang/v2/src/jsonToBru.js
@@ -175,6 +175,7 @@ ${indentString(`username: ${auth?.oauth2?.username || ''}`)}
${indentString(`password: ${auth?.oauth2?.password || ''}`)}
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
+${indentString(`client_secret_method: ${auth?.oauth2?.clientSecretMethod || ''}`)}
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
}
@@ -188,6 +189,7 @@ ${indentString(`authorization_url: ${auth?.oauth2?.authorizationUrl || ''}`)}
${indentString(`access_token_url: ${auth?.oauth2?.accessTokenUrl || ''}`)}
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
+${indentString(`client_secret_method: ${auth?.oauth2?.clientSecretMethod || ''}`)}
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
${indentString(`state: ${auth?.oauth2?.state || ''}`)}
${indentString(`pkce: ${(auth?.oauth2?.pkce || false).toString()}`)}
@@ -201,6 +203,7 @@ ${indentString(`grant_type: client_credentials`)}
${indentString(`access_token_url: ${auth?.oauth2?.accessTokenUrl || ''}`)}
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
+${indentString(`client_secret_method: ${auth?.oauth2?.clientSecretMethod || ''}`)}
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
}
diff --git a/packages/bruno-lang/v2/src/jsonToCollectionBru.js b/packages/bruno-lang/v2/src/jsonToCollectionBru.js
index 8b162b7a6f..5721d0345a 100644
--- a/packages/bruno-lang/v2/src/jsonToCollectionBru.js
+++ b/packages/bruno-lang/v2/src/jsonToCollectionBru.js
@@ -142,6 +142,7 @@ ${indentString(`username: ${auth?.oauth2?.username || ''}`)}
${indentString(`password: ${auth?.oauth2?.password || ''}`)}
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
+${indentString(`client_secret_method: ${auth?.oauth2?.clientSecretMethod || ''}`)}
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
}
@@ -155,6 +156,7 @@ ${indentString(`authorization_url: ${auth?.oauth2?.authorizationUrl || ''}`)}
${indentString(`access_token_url: ${auth?.oauth2?.accessTokenUrl || ''}`)}
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
+${indentString(`client_secret_method: ${auth?.oauth2?.clientSecretMethod || ''}`)}
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
${indentString(`state: ${auth?.oauth2?.state || ''}`)}
${indentString(`pkce: ${(auth?.oauth2?.pkce || false).toString()}`)}
@@ -168,6 +170,7 @@ ${indentString(`grant_type: client_credentials`)}
${indentString(`access_token_url: ${auth?.oauth2?.accessTokenUrl || ''}`)}
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
+${indentString(`client_secret_method: ${auth?.oauth2?.clientSecretMethod || ''}`)}
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
}
diff --git a/packages/bruno-lang/v2/tests/fixtures/collection.bru b/packages/bruno-lang/v2/tests/fixtures/collection.bru
index f11954ebf1..24eef68825 100644
--- a/packages/bruno-lang/v2/tests/fixtures/collection.bru
+++ b/packages/bruno-lang/v2/tests/fixtures/collection.bru
@@ -31,6 +31,19 @@ auth:digest {
password: secret
}
+auth:oauth2 {
+ grant_type: authorization_code
+ callback_url: http://localhost:8080/api/auth/oauth2/authorization_code/callback
+ authorization_url: http://localhost:8080/api/auth/oauth2/authorization_code/authorize
+ access_token_url: http://localhost:8080/api/auth/oauth2/authorization_code/token
+ client_id: client_id_1
+ client_secret: client_secret_1
+ client_secret_method: client_credentials_post
+ scope: read write
+ state: 807061d5f0be
+ pkce: false
+}
+
vars:pre-request {
departingDate: 2020-01-01
~returningDate: 2020-01-02
diff --git a/packages/bruno-lang/v2/tests/fixtures/collection.json b/packages/bruno-lang/v2/tests/fixtures/collection.json
index 102ee295cb..2a0572159f 100644
--- a/packages/bruno-lang/v2/tests/fixtures/collection.json
+++ b/packages/bruno-lang/v2/tests/fixtures/collection.json
@@ -35,6 +35,18 @@
"wsse": {
"username": "john",
"password": "secret"
+ },
+ "oauth2": {
+ "grantType": "authorization_code",
+ "clientId": "client_id_1",
+ "clientSecret": "client_secret_1",
+ "clientSecretMethod": "client_credentials_post",
+ "authorizationUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/authorize",
+ "callbackUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/callback",
+ "accessTokenUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/token",
+ "scope": "read write",
+ "state": "807061d5f0be",
+ "pkce": false
}
},
"vars": {
diff --git a/packages/bruno-lang/v2/tests/fixtures/request.bru b/packages/bruno-lang/v2/tests/fixtures/request.bru
index 1a3efeab72..a9c6dffcb7 100644
--- a/packages/bruno-lang/v2/tests/fixtures/request.bru
+++ b/packages/bruno-lang/v2/tests/fixtures/request.bru
@@ -61,6 +61,7 @@ auth:oauth2 {
access_token_url: http://localhost:8080/api/auth/oauth2/authorization_code/token
client_id: client_id_1
client_secret: client_secret_1
+ client_secret_method: client_credentials_basic
scope: read write
state: 807061d5f0be
pkce: false
diff --git a/packages/bruno-lang/v2/tests/fixtures/request.json b/packages/bruno-lang/v2/tests/fixtures/request.json
index 9c8ed143da..6f195d0877 100644
--- a/packages/bruno-lang/v2/tests/fixtures/request.json
+++ b/packages/bruno-lang/v2/tests/fixtures/request.json
@@ -77,6 +77,7 @@
"grantType": "authorization_code",
"clientId": "client_id_1",
"clientSecret": "client_secret_1",
+ "clientSecretMethod": "client_credentials_basic",
"authorizationUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/authorize",
"callbackUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/callback",
"accessTokenUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/token",
diff --git a/packages/bruno-schema/src/collections/index.js b/packages/bruno-schema/src/collections/index.js
index 3d5959f15d..76a42faa18 100644
--- a/packages/bruno-schema/src/collections/index.js
+++ b/packages/bruno-schema/src/collections/index.js
@@ -188,7 +188,14 @@ const oauth2Schema = Yup.object({
is: (val) => ['authorization_code'].includes(val),
then: Yup.boolean().default(false),
otherwise: Yup.boolean()
- })
+ }),
+ clientSecretMethod: Yup.string()
+ .oneOf(['client_credentials_basic', 'client_credentials_post'])
+ .when('clientSecret', {
+ is: (clientSecret) => clientSecret != null,
+ then: Yup.string().default('client_credentials_basic'),
+ otherwise: Yup.string().nullable().strip()
+ })
})
.noUnknown(true)
.strict();