diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AdditionalParams/index.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AdditionalParams/index.js
index b9b6f66bc..20c4923cd 100644
--- a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AdditionalParams/index.js
+++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AdditionalParams/index.js
@@ -11,7 +11,6 @@ import Table from "components/Table/index";
const AdditionalParams = ({ item = {}, request, updateAuth, collection }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
- const [activeTab, setActiveTab] = useState('authorization');
const oAuth = get(request, 'auth.oauth2', {});
const {
@@ -19,6 +18,8 @@ const AdditionalParams = ({ item = {}, request, updateAuth, collection }) => {
additionalParameters = {}
} = oAuth;
+ const [activeTab, setActiveTab] = useState(grantType == 'authorization_code' ? 'authorization' : 'token');
+
const isEmptyParam = (param) => {
return !param.name.trim() && !param.value.trim();
};
@@ -28,8 +29,8 @@ const AdditionalParams = ({ item = {}, request, updateAuth, collection }) => {
return tabParams.some(isEmptyParam);
};
- const updateAdditionalParams = ({ updatedAdditionalParams }) => {
- const filteredParams = cloneDeep(updatedAdditionalParams);
+ const updateAdditionalParameters = ({ updatedAdditionalParameters }) => {
+ const filteredParams = cloneDeep(updatedAdditionalParameters);
Object.keys(filteredParams).forEach(paramType => {
if (filteredParams[paramType]?.length) {
@@ -60,14 +61,14 @@ const AdditionalParams = ({ item = {}, request, updateAuth, collection }) => {
}
const handleUpdateAdditionalParam = ({ paramType, key, paramIndex, value }) => {
- const updatedAdditionalParams = cloneDeep(additionalParameters);
+ const updatedAdditionalParameters = cloneDeep(additionalParameters);
- if (!updatedAdditionalParams[paramType]) {
- updatedAdditionalParams[paramType] = [];
+ if (!updatedAdditionalParameters[paramType]) {
+ updatedAdditionalParameters[paramType] = [];
}
- if (!updatedAdditionalParams[paramType][paramIndex]) {
- updatedAdditionalParams[paramType][paramIndex] = {
+ if (!updatedAdditionalParameters[paramType][paramIndex]) {
+ updatedAdditionalParameters[paramType][paramIndex] = {
name: '',
value: '',
sendIn: 'headers',
@@ -75,25 +76,25 @@ const AdditionalParams = ({ item = {}, request, updateAuth, collection }) => {
};
}
- updatedAdditionalParams[paramType][paramIndex][key] = value;
+ updatedAdditionalParameters[paramType][paramIndex][key] = value;
// Only filter when updating a parameter
- updateAdditionalParams({ updatedAdditionalParams });
+ updateAdditionalParameters({ updatedAdditionalParameters });
}
const handleDeleteAdditionalParam = ({ paramType, paramIndex }) => {
- const updatedAdditionalParams = cloneDeep(additionalParameters);
+ const updatedAdditionalParameters = cloneDeep(additionalParameters);
- if (updatedAdditionalParams[paramType]?.length) {
- updatedAdditionalParams[paramType] = updatedAdditionalParams[paramType].filter((_, index) => index !== paramIndex);
+ if (updatedAdditionalParameters[paramType]?.length) {
+ updatedAdditionalParameters[paramType] = updatedAdditionalParameters[paramType].filter((_, index) => index !== paramIndex);
// If the array is now empty, ensure we're not sending empty arrays
- if (updatedAdditionalParams[paramType].length === 0) {
- delete updatedAdditionalParams[paramType];
+ if (updatedAdditionalParameters[paramType].length === 0) {
+ delete updatedAdditionalParameters[paramType];
}
}
- updateAdditionalParams({ updatedAdditionalParams });
+ updateAdditionalParameters({ updatedAdditionalParameters });
}
const handleAddNewAdditionalParam = () => {
@@ -149,7 +150,7 @@ const AdditionalParams = ({ item = {}, request, updateAuth, collection }) => {
{/* Method and URL */}
{/* Headers */}
diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js
index 749e32a6d..686182ee6 100644
--- a/packages/bruno-electron/src/ipc/network/prepare-request.js
+++ b/packages/bruno-electron/src/ipc/network/prepare-request.js
@@ -87,7 +87,8 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
tokenHeaderPrefix: get(collectionAuth, 'oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey'),
autoFetchToken: get(collectionAuth, 'oauth2.autoFetchToken'),
- autoRefreshToken: get(collectionAuth, 'oauth2.autoRefreshToken')
+ autoRefreshToken: get(collectionAuth, 'oauth2.autoRefreshToken'),
+ additionalParameters: get(collectionAuth, 'auth.oauth2.additionalParameters', { authorization: [], token: [], refresh: [] })
};
break;
case 'authorization_code':
@@ -108,7 +109,8 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
tokenHeaderPrefix: get(collectionAuth, 'oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey'),
autoFetchToken: get(collectionAuth, 'oauth2.autoFetchToken'),
- autoRefreshToken: get(collectionAuth, 'oauth2.autoRefreshToken')
+ autoRefreshToken: get(collectionAuth, 'oauth2.autoRefreshToken'),
+ additionalParameters: get(collectionAuth, 'auth.oauth2.additionalParameters', { authorization: [], token: [], refresh: [] })
};
break;
case 'client_credentials':
@@ -125,7 +127,8 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
tokenHeaderPrefix: get(collectionAuth, 'oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey'),
autoFetchToken: get(collectionAuth, 'oauth2.autoFetchToken'),
- autoRefreshToken: get(collectionAuth, 'oauth2.autoRefreshToken')
+ autoRefreshToken: get(collectionAuth, 'oauth2.autoRefreshToken'),
+ additionalParameters: get(collectionAuth, 'auth.oauth2.additionalParameters', { authorization: [], token: [], refresh: [] })
};
break;
}
@@ -185,7 +188,8 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
tokenHeaderPrefix: get(request, 'auth.oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey'),
autoFetchToken: get(request, 'auth.oauth2.autoFetchToken'),
- autoRefreshToken: get(request, 'auth.oauth2.autoRefreshToken')
+ autoRefreshToken: get(request, 'auth.oauth2.autoRefreshToken'),
+ additionalParameters: get(request, 'auth.oauth2.additionalParameters', { authorization: [], token: [], refresh: [] })
};
break;
case 'authorization_code':
@@ -206,7 +210,8 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
tokenHeaderPrefix: get(request, 'auth.oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey'),
autoFetchToken: get(request, 'auth.oauth2.autoFetchToken'),
- autoRefreshToken: get(request, 'auth.oauth2.autoRefreshToken')
+ autoRefreshToken: get(request, 'auth.oauth2.autoRefreshToken'),
+ additionalParameters: get(request, 'auth.oauth2.additionalParameters', { authorization: [], token: [], refresh: [] })
};
break;
case 'client_credentials':
@@ -223,7 +228,8 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
tokenHeaderPrefix: get(request, 'auth.oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey'),
autoFetchToken: get(request, 'auth.oauth2.autoFetchToken'),
- autoRefreshToken: get(request, 'auth.oauth2.autoRefreshToken')
+ autoRefreshToken: get(request, 'auth.oauth2.autoRefreshToken'),
+ additionalParameters: get(request, 'auth.oauth2.additionalParameters', { authorization: [], token: [], refresh: [] })
};
break;
}
diff --git a/packages/bruno-electron/src/utils/oauth2.js b/packages/bruno-electron/src/utils/oauth2.js
index 50b1f73ed..24cc2bfed 100644
--- a/packages/bruno-electron/src/utils/oauth2.js
+++ b/packages/bruno-electron/src/utils/oauth2.js
@@ -142,13 +142,13 @@ const getOAuth2TokenUsingAuthorizationCode = async ({ request, collectionUid, fo
data.scope = scope;
}
+ requestCopy.url = url;
// Apply additional parameters to token request
if (additionalParameters?.token?.length) {
applyAdditionalParameters(requestCopy, data, additionalParameters.token);
}
requestCopy.data = qs.stringify(data);
- requestCopy.url = url;
requestCopy.responseType = 'arraybuffer';
// Initialize variables to hold request and response data for debugging
@@ -400,12 +400,13 @@ const getOAuth2TokenUsingClientCredentials = async ({ request, collectionUid, fo
if (scope) {
data.scope = scope;
}
+
+ requestCopy.url = url;
if (additionalParameters?.token?.length) {
applyAdditionalParameters(requestCopy, data, additionalParameters.token);
}
requestCopy.data = qs.stringify(data);
- requestCopy.url = url;
requestCopy.responseType = 'arraybuffer';
// Initialize variables to hold request and response data for debugging
@@ -593,12 +594,13 @@ const getOAuth2TokenUsingPasswordCredentials = async ({ request, collectionUid,
if (scope) {
data.scope = scope;
}
+
+ requestCopy.url = url;
if (additionalParameters?.token?.length) {
applyAdditionalParameters(requestCopy, data, additionalParameters.token);
}
requestCopy.data = qs.stringify(data);
- requestCopy.url = url;
requestCopy.responseType = 'arraybuffer';
// Initialize variables to hold request and response data for debugging
@@ -714,6 +716,8 @@ const refreshOauth2Token = async ({ requestCopy, collectionUid, certsAndProxyCon
if (clientSecret) {
data.client_secret = clientSecret;
}
+
+ requestCopy.url = url;
if (oAuth.additionalParameters?.refresh?.length) {
applyAdditionalParameters(requestCopy, data, oAuth.additionalParameters.refresh);
}
@@ -722,7 +726,6 @@ const refreshOauth2Token = async ({ requestCopy, collectionUid, certsAndProxyCon
requestCopy.headers['content-type'] = 'application/x-www-form-urlencoded';
requestCopy.headers['Accept'] = 'application/json';
requestCopy.data = qs.stringify(data);
- requestCopy.url = url;
requestCopy.responseType = 'arraybuffer';
// Initialize variables to hold request and response data for debugging
@@ -845,11 +848,7 @@ const generateCodeChallenge = (codeVerifier) => {
};
// Apply additional parameters to a request
-const applyAdditionalParameters = (requestCopy, data, params) => {
- if (!params || !params.length) {
- return;
- }
-
+const applyAdditionalParameters = (requestCopy, data, params = []) => {
params.forEach(param => {
if (!param.enabled || !param.name) {
return;
@@ -861,12 +860,14 @@ const applyAdditionalParameters = (requestCopy, data, params) => {
break;
case 'queryparams':
// For query params, add to URL
- if (!requestCopy.url.includes('?')) {
- requestCopy.url += '?';
- } else if (!requestCopy.url.endsWith('&') && !requestCopy.url.endsWith('?')) {
- requestCopy.url += '&';
+ try {
+ let url = new URL(requestCopy.url);
+ url.searchParams.append(param.name, param.value);
+ requestCopy.url = url.href;
+ }
+ catch (error) {
+ console.error('invalid token/refresh url', requestCopy.url);
}
- requestCopy.url += `${encodeURIComponent(param.name)}=${encodeURIComponent(param.value || '')}`;
break;
case 'body':
// For body, add to data object
diff --git a/packages/bruno-lang/v2/src/utils.js b/packages/bruno-lang/v2/src/utils.js
index 64d377aee..aaef783c4 100644
--- a/packages/bruno-lang/v2/src/utils.js
+++ b/packages/bruno-lang/v2/src/utils.js
@@ -40,19 +40,21 @@ const mergeOauth2AdditionalParameters = (ast) => {
const refreshQueryParams = ast?.oauth2_additional_parameters_refresh_queryparams;
const refreshBodyValues = ast?.oauth2_additional_parameters_refresh_bodyvalues;
- if (authorizationHeaders?.length || authorizationQueryParams?.length) {
- additionalParameters['authorization'] = []
- }
- if (authorizationHeaders?.length) {
- additionalParameters['authorization'] = [
- ...authorizationHeaders?.map(_ => ({ ..._, sendIn: 'headers' }))
- ]
- }
- if (authorizationQueryParams?.length) {
- additionalParameters['authorization'] = [
- ...additionalParameters['authorization'] || [],
- ...authorizationQueryParams?.map(_ => ({ ..._, sendIn: 'queryparams' }))
- ]
+ if (ast?.auth?.oauth2?.grantType == 'authorization_code') {
+ if (authorizationHeaders?.length || authorizationQueryParams?.length) {
+ additionalParameters['authorization'] = []
+ }
+ if (authorizationHeaders?.length) {
+ additionalParameters['authorization'] = [
+ ...authorizationHeaders?.map(_ => ({ ..._, sendIn: 'headers' }))
+ ]
+ }
+ if (authorizationQueryParams?.length) {
+ additionalParameters['authorization'] = [
+ ...additionalParameters['authorization'] || [],
+ ...authorizationQueryParams?.map(_ => ({ ..._, sendIn: 'queryparams' }))
+ ]
+ }
}
if (tokenHeaders?.length || tokenQueryParams?.length || tokenBodyValues?.length) {
diff --git a/packages/bruno-schema/src/collections/index.js b/packages/bruno-schema/src/collections/index.js
index 253d644cd..936eee680 100644
--- a/packages/bruno-schema/src/collections/index.js
+++ b/packages/bruno-schema/src/collections/index.js
@@ -276,7 +276,11 @@ const oauth2Schema = Yup.object({
otherwise: Yup.boolean()
}),
additionalParameters: Yup.object({
- authorization: Yup.array().of(oauth2AuthorizationAdditionalParametersSchema).optional(),
+ authorization: Yup.mixed().when('grantType', {
+ is: 'authorization_code',
+ then: Yup.array().of(oauth2AuthorizationAdditionalParametersSchema).required(),
+ otherwise: Yup.mixed().nullable().optional()
+ }),
token: Yup.array().of(oauth2AdditionalParametersSchema).optional(),
refresh: Yup.array().of(oauth2AdditionalParametersSchema).optional()
})