Merge pull request #4446 from lohxt1/pr_4416

fix(oauth2): improve additional parameters handling and ui updates
This commit is contained in:
lohit 2025-04-06 19:05:45 +05:30 committed by GitHub
commit 84ef5b1044
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 66 additions and 54 deletions

View File

@ -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 }) => {
</div>
<div className="tabs flex w-full gap-2 my-2">
<div className={`tab ${activeTab == 'authorization' ? 'active': ''}`} onClick={e => setActiveTab('authorization')}>Authorization</div>
{grantType == 'authorization_code' && <div className={`tab ${activeTab == 'authorization' ? 'active': ''}`} onClick={e => setActiveTab('authorization')}>Authorization</div>}
<div className={`tab ${activeTab == 'token' ? 'active': ''}`} onClick={e => setActiveTab('token')}>Token</div>
<div className={`tab ${activeTab == 'refresh' ? 'active': ''}`} onClick={e => setActiveTab('refresh')}>Refresh</div>
</div>
@ -279,12 +280,10 @@ const sendInOptionsMap = {
'refresh': ['headers', 'queryparams', 'body']
},
'password': {
'authorization': ['headers', 'queryparams'],
'token': ['headers', 'queryparams', 'body'],
'refresh': ['headers', 'queryparams', 'body']
},
'client_credentials': {
'authorization': ['headers', 'queryparams'],
'token': ['headers', 'queryparams', 'body'],
'refresh': ['headers', 'queryparams', 'body']
}

View File

@ -26,7 +26,7 @@ const Request = ({ collection, request, item, width }) => {
<div>
{/* Method and URL */}
<div className="mb-1 flex gap-2">
<pre className="whitespace-pre-wrap">{url}</pre>
<pre className="whitespace-pre-wrap" title={url}>{url}</pre>
</div>
{/* Headers */}

View File

@ -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;
}

View File

@ -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

View File

@ -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) {

View File

@ -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()
})