oauth2 changes

This commit is contained in:
lohxt1
2025-04-02 19:42:15 +05:30
parent bd25097e44
commit 3c0d0c95ea
5 changed files with 549 additions and 4 deletions

View File

@@ -0,0 +1,216 @@
import { useDispatch } from "react-redux";
import React, { useRef, forwardRef, useState } from 'react';
import get from 'lodash/get';
import { useTheme } from 'providers/Theme';
import { IconPlus } from '@tabler/icons';
import Dropdown from 'components/Dropdown';
import { cloneDeep } from "lodash";
const AdditionalParams = ({ item = {}, request, updateAuth, collection }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const dropdownTippyRef = useRef();
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
const [activeTab, setActiveTab] = useState('authorization');
const oAuth = get(request, 'auth.oauth2', {});
const {
grantType,
callbackUrl,
authorizationUrl,
accessTokenUrl,
clientId,
clientSecret,
scope,
credentialsPlacement,
state,
pkce,
credentialsId,
tokenPlacement,
tokenHeaderPrefix,
tokenQueryKey,
refreshTokenUrl,
autoRefreshToken,
autoFetchToken,
additionalParams = {}
} = oAuth;
const handleUpdateAdditionalParam = ({ paramType, key, paramIndex, value }) => {
const updatedAdditionalParams = cloneDeep(additionalParams);
updatedAdditionalParams[paramType][paramIndex][key] = value;
dispatch(
updateAuth({
mode: 'oauth2',
collectionUid: collection.uid,
itemUid: item.uid,
content: {
grantType,
callbackUrl,
authorizationUrl,
accessTokenUrl,
clientId,
clientSecret,
state,
scope,
pkce,
credentialsPlacement,
credentialsId,
tokenPlacement,
tokenHeaderPrefix,
tokenQueryKey,
refreshTokenUrl,
autoRefreshToken,
autoFetchToken,
additionalParams: updatedAdditionalParams,
}
})
);
}
const handleAddNewAdditionalParam = () => {
const paramType = activeTab;
const updatedAdditionalParams = cloneDeep(additionalParams);
if (!updatedAdditionalParams?.[paramType]) {
updatedAdditionalParams[paramType] = [];
}
updatedAdditionalParams[paramType] = [
...updatedAdditionalParams[paramType],
{
name: '',
value: '',
sendIn: 'header'
}
];
dispatch(
updateAuth({
mode: 'oauth2',
collectionUid: collection.uid,
itemUid: item.uid,
content: {
grantType,
callbackUrl,
authorizationUrl,
accessTokenUrl,
clientId,
clientSecret,
state,
scope,
pkce,
credentialsPlacement,
credentialsId,
tokenPlacement,
tokenHeaderPrefix,
tokenQueryKey,
refreshTokenUrl,
autoRefreshToken,
autoFetchToken,
additionalParams: updatedAdditionalParams,
}
})
);
}
return (
<div>
<div className="tabs">
<div className="tab">Authorization</div>
<div className="tab">Token</div>
<div className="tab">Refresh</div>
</div>
<table className="w-full">
<thead>
<tr>
<th className="py-2 px-4 font-semibold w-32">Key</th>
<th className="py-2 px-4 font-semibold w-32">Value</th>
<th className="py-2 px-4 font-semibold w-32">Send In</th>
</tr>
</thead>
<tbody>
{additionalParams?.[activeTab]?.map((param, index) =>
<tr>
<td>
<SingleLineEditor
value={param?.name}
theme={storedTheme}
onSave={handleSave}
onChange={(value) => handleUpdateAdditionalParam({
paramType: activeTab,
key: 'name',
paramIndex: index,
value
})}
collection={collection}
/>
</td>
<td>
<SingleLineEditor
value={param?.value}
theme={storedTheme}
onSave={handleSave}
onChange={(value) => handleUpdateAdditionalParam({
paramType: activeTab,
key: 'value',
paramIndex: index,
value
})}
collection={collection}
/>
</td>
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
handleUpdateAdditionalParam({
paramType: activeTab,
key: 'sendIn',
paramIndex: index,
value: 'header'
})
}}
>
Header
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
handleUpdateAdditionalParam({
paramType: activeTab,
key: 'sendIn',
paramIndex: index,
value: 'queryparams'
})
}}
>
Query Params
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
handleUpdateAdditionalParam({
paramType: activeTab,
key: 'sendIn',
paramIndex: index,
value: 'body'
})
}}
>
Body
</div>
</Dropdown>
</tr>
)}
</tbody>
</table>
<div className="add-additional-param-actions">
<IconPlus size={16} strokeWidth={1.5} style={{ marginLeft: '2px' }} onClick={handleAddNewAdditionalParam} />
</div>
</div>
)
}
export default AdditionalParams;

View File

@@ -9,6 +9,7 @@ import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import Oauth2TokenViewer from '../Oauth2TokenViewer/index';
import Oauth2ActionButtons from '../Oauth2ActionButtons/index';
import AdditionalParams from '../AdditionalParams/index';
const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAuth, collection, folder }) => {
const dispatch = useDispatch();
@@ -326,6 +327,7 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
</div>
</div>
</div>
<AdditionalParams item={item} request={request} collection={collection} url={accessTokenUrl} />
<Oauth2ActionButtons item={item} request={request} collection={collection} url={accessTokenUrl} credentialsId={credentialsId} />
</StyledWrapper>
);

View File

@@ -22,12 +22,18 @@ const { safeParseJson, outdentString } = require('./utils');
*
*/
const grammar = ohm.grammar(`Bru {
BruFile = (meta | http | query | params | headers | auths | bodies | varsandassert | script | tests | docs)*
BruFile = (meta | http | query | params | headers | auths | bodies | varsandassert | script | tests | docs | authOAuth2Configs)*
auths = authawsv4 | authbasic | authbearer | authdigest | authNTLM | authOAuth2 | authwsse | authapikey
bodies = bodyjson | bodytext | bodyxml | bodysparql | bodygraphql | bodygraphqlvars | bodyforms | body
bodyforms = bodyformurlencoded | bodymultipart | bodyfile
params = paramspath | paramsquery
// Oauth2 additional parameters
authOAuth2Configs = oAuth2AuthorizationConfig | oAuth2TokenConfig | oAuth2RefreshConfig
oAuth2AuthorizationConfig = oAuth2AuthorizationHeaders | oAuth2AuthorizationQueryParams
oAuth2TokenConfig = oAuth2TokenHeaders | oAuth2TokenQueryParams | oAuth2TokenBodyValues
oAuth2RefreshConfig = oAuth2RefreshHeaders | oAuth2RefreshQueryParams | oAuth2RefreshBodyValues
nl = "\\r"? "\\n"
st = " " | "\\t"
stnl = st | nl
@@ -92,6 +98,15 @@ const grammar = ohm.grammar(`Bru {
authwsse = "auth:wsse" dictionary
authapikey = "auth:apikey" dictionary
oAuth2AuthorizationHeaders = "auth:oauth2:authorization_headers" dictionary
oAuth2AuthorizationQueryParams = "auth:oauth2:authorization_queryparams" dictionary
oAuth2TokenHeaders = "auth:oauth2:token_headers" dictionary
oAuth2TokenQueryParams = "auth:oauth2:token_queryparams" dictionary
oAuth2TokenBodyValues = "auth:oauth2:token_bodyvalues" dictionary
oAuth2RefreshHeaders = "auth:oauth2:authorization_headers" dictionary
oAuth2RefreshQueryParams = "auth:oauth2:authorization_queryparams" dictionary
oAuth2RefreshBodyValues = "auth:oauth2:authorization_bodyvalues" dictionary
body = "body" st* "{" nl* textblock tagend
bodyjson = "body:json" st* "{" nl* textblock tagend
bodytext = "body:text" st* "{" nl* textblock tagend
@@ -588,6 +603,146 @@ const sem = grammar.createSemantics().addAttribute('ast', {
}
};
},
oAuth2AuthorizationHeaders(_1, dictionary) {
const authorizationHeaders = [...mapPairListToKeyValPairs(dictionary.ast)]?.map(_ => ({
..._,
sendIn: 'headers'
}));
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
authorization: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.authorization || []),
...authorizationHeaders
]
}
}
}
};
},
oAuth2AuthorizationQueryParams(_1, dictionary) {
const authorizationQueryParams = [...mapPairListToKeyValPairs(dictionary.ast)]?.map(_ => ({
..._,
sendIn: 'queryparams'
}));
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
authorization: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.authorization || []),
...authorizationQueryParams
]
}
}
}
};
},
oAuth2TokenHeaders(_1, dictionary) {
const tokenHeaders = [...mapPairListToKeyValPairs(dictionary.ast)]?.map(_ => ({
..._,
sendIn: 'headers'
}));
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
token: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.token || []),
...tokenHeaders
]
}
}
}
};
},
oAuth2TokenQueryParams(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
tokenQueryParams: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.tokenQueryParams || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2TokenBodyValues(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
tokenBodyValues: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.tokenBodyValues || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2RefreshHeaders(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
refreshHeaders: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.refreshHeaders || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2RefreshQueryParams(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
refreshQueryParams: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.refreshQueryParams || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2RefreshBodyValues(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
refreshBodyValues: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.refreshBodyValues || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
authwsse(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
@@ -782,4 +937,4 @@ const parser = (input) => {
};
module.exports = parser;

View File

@@ -3,9 +3,15 @@ const _ = require('lodash');
const { safeParseJson, outdentString } = require('./utils');
const grammar = ohm.grammar(`Bru {
BruFile = (meta | query | headers | auth | auths | vars | script | tests | docs)*
BruFile = (meta | query | headers | auth | auths | vars | script | tests | docs | authOAuth2Configs)*
auths = authawsv4 | authbasic | authbearer | authdigest | authNTLM |authOAuth2 | authwsse | authapikey
// Oauth2 additional parameters
authOAuth2Configs = oAuth2AuthorizationConfig | oAuth2TokenConfig | oAuth2RefreshConfig
oAuth2AuthorizationConfig = oAuth2AuthorizationHeaders | oAuth2AuthorizationQueryParams
oAuth2TokenConfig = oAuth2TokenHeaders | oAuth2TokenQueryParams | oAuth2TokenBodyValues
oAuth2RefreshConfig = oAuth2RefreshHeaders | oAuth2RefreshQueryParams | oAuth2RefreshBodyValues
nl = "\\r"? "\\n"
st = " " | "\\t"
stnl = st | nl
@@ -30,6 +36,15 @@ const grammar = ohm.grammar(`Bru {
auth = "auth" dictionary
oAuth2AuthorizationHeaders = "auth:oauth2:authorization_headers" dictionary
oAuth2AuthorizationQueryParams = "auth:oauth2:authorization_queryparams" dictionary
oAuth2TokenHeaders = "auth:oauth2:token_headers" dictionary
oAuth2TokenQueryParams = "auth:oauth2:token_queryparams" dictionary
oAuth2TokenBodyValues = "auth:oauth2:token_bodyvalues" dictionary
oAuth2RefreshHeaders = "auth:oauth2:authorization_headers" dictionary
oAuth2RefreshQueryParams = "auth:oauth2:authorization_queryparams" dictionary
oAuth2RefreshBodyValues = "auth:oauth2:authorization_bodyvalues" dictionary
headers = "headers" dictionary
query = "query" dictionary
@@ -348,6 +363,134 @@ const sem = grammar.createSemantics().addAttribute('ast', {
}
};
},
oAuth2AuthorizationHeaders(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
authorizationHeaders: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.authorizationHeaders || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2AuthorizationQueryParams(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
authorizationQueryParams: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.authorizationQueryParams || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2TokenHeaders(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
tokenHeaders: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.tokenHeaders || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2TokenQueryParams(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
tokenQueryParams: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.tokenQueryParams || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2TokenBodyValues(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
tokenBodyValues: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.tokenBodyValues || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2RefreshHeaders(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
refreshHeaders: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.refreshHeaders || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2RefreshQueryParams(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
refreshQueryParams: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.refreshQueryParams || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
oAuth2RefreshBodyValues(_1, dictionary) {
return {
auth: {
oauth2: {
...(dictionary?.ast?.auth?.oauth2 || {}),
additionalParameters: {
...(dictionary?.ast?.auth?.oauth2?.additionalParameters || {}),
refreshBodyValues: [
...(dictionary?.ast?.auth?.oauth2?.additionalParameters?.refreshBodyValues || []),
...mapPairListToKeyValPairs(dictionary.ast)
]
}
}
}
};
},
authwsse(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
const userKey = _.find(auth, { name: 'username' });

View File

@@ -249,6 +249,35 @@ ${indentString(`auto_refresh_token: ${(auth?.oauth2?.autoRefreshToken ?? false).
`;
break;
}
if (auth?.oauth2?.additionalParameters) {
switch(auth?.oauth2?.additionalParameters) {
case 'authorizationHeaders' :
let authorizationHeaders = auth?.oauth2?.additionalParameters?.authorizationHeaders;
bru += `auth:oauth2:authorization_headers {
${enabled(authorizationHeaders)
.map((item) => `${item.name}: ${item.value}`)
.join('\n')}
}`;
break;
case 'authorizationQueryParams' :
let authorizationQueryParams = auth?.oauth2?.additionalParameters?.authorizationQueryParams;
bru += `auth:oauth2:authorization_queryparams {
${enabled(authorizationQueryParams)
.map((item) => `${item.name}: ${item.value}`)
.join('\n')}
}`;
break;
case 'authorizationBodyValues' :
let authorizationBodyValues = auth?.oauth2?.additionalParameters?.authorizationBodyValues;
bru += `auth:oauth2:authorization_queryparams {
${enabled(authorizationBodyValues)
.map((item) => `${item.name}: ${item.value}`)
.join('\n')}
}`;
break;
}
}
}
if (auth && auth.apikey) {