mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-25 05:35:41 +00:00
oauth2 workflow improvements (#3874)
~ basic auth credentials should be assigned to `request.basicAuth` instead `request.auth` object ~ added credentials_placement option, fixed headers issue client credentials flow ~ cache input field values when grant type select box value changes ~ updated logic for - cache input field values when grant type select box value changes ~ updated token expiry timer component logic
This commit is contained in:
@@ -22,9 +22,9 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
|
||||
|
||||
const oAuth = get(request, 'auth.oauth2', {});
|
||||
|
||||
const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, state, pkce, credentialsId, tokenPlacement, tokenPrefix, tokenQueryParamKey, reuseToken } = oAuth;
|
||||
const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, credentialsPlacement, state, pkce, credentialsId, tokenPlacement, tokenPrefix, tokenQueryKey, reuseToken } = oAuth;
|
||||
|
||||
const Icon = forwardRef((props, ref) => {
|
||||
const TokenPlacementIcon = forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-end token-placement-label select-none">
|
||||
{tokenPlacement == 'url' ? 'URL' : 'Headers'}
|
||||
@@ -33,6 +33,16 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
|
||||
);
|
||||
});
|
||||
|
||||
const CredentialsPlacementIcon = forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-end token-placement-label select-none">
|
||||
{credentialsPlacement == 'body' ? 'Request Body' : 'Basic Auth Header'}
|
||||
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
const handleFetchOauth2Credentials = async () => {
|
||||
let requestCopy = cloneDeep(request);
|
||||
requestCopy.oauth2 = requestCopy?.auth.oauth2;
|
||||
@@ -41,11 +51,12 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
|
||||
try {
|
||||
await dispatch(fetchOauth2Credentials({ request: requestCopy, collection }));
|
||||
toggleFetchingToken(false);
|
||||
toast.success('token fetched successfully!');
|
||||
}
|
||||
catch(error) {
|
||||
console.error('could not fetch the token!');
|
||||
console.error(error);
|
||||
toggleFetchingToken(false);
|
||||
toast.error('An error occured while fetching token!');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,10 +78,11 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
|
||||
state,
|
||||
scope,
|
||||
pkce,
|
||||
credentialsPlacement,
|
||||
credentialsId,
|
||||
tokenPlacement,
|
||||
tokenPrefix,
|
||||
tokenQueryParamKey,
|
||||
tokenQueryKey,
|
||||
reuseToken,
|
||||
[key]: value
|
||||
}
|
||||
@@ -93,10 +105,11 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
|
||||
clientSecret,
|
||||
state,
|
||||
scope,
|
||||
credentialsPlacement,
|
||||
credentialsId,
|
||||
tokenPlacement,
|
||||
tokenPrefix,
|
||||
tokenQueryParamKey,
|
||||
tokenQueryKey,
|
||||
reuseToken,
|
||||
pkce: !Boolean(oAuth?.['pkce'])
|
||||
}
|
||||
@@ -146,6 +159,31 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="flex items-center gap-4 w-full" key={`input-credentials-placement`}>
|
||||
<label className="block min-w-[140px]">Add Credentials to</label>
|
||||
<div className="inline-flex items-center cursor-pointer token-placement-selector">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<CredentialsPlacementIcon />} placement="bottom-end">
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={() => {
|
||||
dropdownTippyRef.current.hide();
|
||||
handleChange('credentialsPlacement', 'body');
|
||||
}}
|
||||
>
|
||||
Request Body
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={() => {
|
||||
dropdownTippyRef.current.hide();
|
||||
handleChange('credentialsPlacement', 'basic_auth_header');
|
||||
}}
|
||||
>
|
||||
Basic Auth Header
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row w-full gap-4" key="pkce">
|
||||
<label className="block">Use PKCE</label>
|
||||
<input
|
||||
@@ -180,7 +218,7 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
|
||||
<div className="flex items-center gap-4 w-full" key={`input-token-placement`}>
|
||||
<label className="block min-w-[140px]">Add token to</label>
|
||||
<div className="inline-flex items-center cursor-pointer token-placement-selector">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<TokenPlacementIcon />} placement="bottom-end">
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={() => {
|
||||
@@ -222,10 +260,10 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
|
||||
<label className="block font-medium min-w-[140px]">Query Param Key</label>
|
||||
<div className="single-line-editor-wrapper flex-1">
|
||||
<SingleLineEditor
|
||||
value={oAuth['tokenQueryParamKey'] || ''}
|
||||
value={oAuth['tokenQueryKey'] || ''}
|
||||
theme={storedTheme}
|
||||
onSave={handleSave}
|
||||
onChange={(val) => handleChange('tokenQueryParamKey', val)}
|
||||
onChange={(val) => handleChange('tokenQueryKey', val)}
|
||||
onRun={handleRun}
|
||||
collection={collection}
|
||||
/>
|
||||
|
||||
@@ -22,7 +22,7 @@ const OAuth2ClientCredentials = ({ save, item = {}, request, handleRun, updateAu
|
||||
|
||||
const oAuth = get(request, 'auth.oauth2', {});
|
||||
|
||||
const { accessTokenUrl, clientId, clientSecret, scope, credentialsId, tokenPlacement, tokenPrefix, tokenQueryParamKey, reuseToken } = oAuth;
|
||||
const { accessTokenUrl, clientId, clientSecret, scope, credentialsPlacement, credentialsId, tokenPlacement, tokenPrefix, tokenQueryKey, reuseToken } = oAuth;
|
||||
|
||||
const handleFetchOauth2Credentials = async () => {
|
||||
let requestCopy = cloneDeep(request);
|
||||
@@ -32,24 +32,34 @@ const OAuth2ClientCredentials = ({ save, item = {}, request, handleRun, updateAu
|
||||
try {
|
||||
await dispatch(fetchOauth2Credentials({ request: requestCopy, collection }));
|
||||
toggleFetchingToken(false);
|
||||
toast.success('Token fetched successfully!');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('could not fetch the token!');
|
||||
console.error(error);
|
||||
toggleFetchingToken(false);
|
||||
toast.error('An error occured while fetching token!');
|
||||
}
|
||||
}
|
||||
const handleSave = () => { save(); };
|
||||
|
||||
const Icon = forwardRef((props, ref) => {
|
||||
const TokenPlacementIcon = forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-end token-placement-label select-none">
|
||||
{tokenPlacement == 'url' ? 'URL' : 'Headers'}
|
||||
{tokenPlacement == 'url' ? 'URL' : 'Headers'}
|
||||
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const CredentialsPlacementIcon = forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-end token-placement-label select-none">
|
||||
{credentialsPlacement == 'body' ? 'Request Body' : 'Basic Auth Header'}
|
||||
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const handleChange = (key, value) => {
|
||||
dispatch(
|
||||
@@ -63,10 +73,11 @@ const OAuth2ClientCredentials = ({ save, item = {}, request, handleRun, updateAu
|
||||
clientId,
|
||||
clientSecret,
|
||||
scope,
|
||||
credentialsPlacement,
|
||||
credentialsId,
|
||||
tokenPlacement,
|
||||
tokenPrefix,
|
||||
tokenQueryParamKey,
|
||||
tokenQueryKey,
|
||||
reuseToken,
|
||||
[key]: value
|
||||
}
|
||||
@@ -116,6 +127,31 @@ const OAuth2ClientCredentials = ({ save, item = {}, request, handleRun, updateAu
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="flex items-center gap-4 w-full" key={`input-credentials-placement`}>
|
||||
<label className="block min-w-[140px]">Add Credentials to</label>
|
||||
<div className="inline-flex items-center cursor-pointer token-placement-selector">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<CredentialsPlacementIcon />} placement="bottom-end">
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={() => {
|
||||
dropdownTippyRef.current.hide();
|
||||
handleChange('credentialsPlacement', 'body');
|
||||
}}
|
||||
>
|
||||
Request Body
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={() => {
|
||||
dropdownTippyRef.current.hide();
|
||||
handleChange('credentialsPlacement', 'basic_auth_header');
|
||||
}}
|
||||
>
|
||||
Basic Auth Header
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2.5 mt-2">
|
||||
<div className="flex items-center px-2.5 py-1.5 bg-indigo-50/50 dark:bg-indigo-500/10 rounded-md">
|
||||
<IconKey size={14} className="text-indigo-500 dark:text-indigo-400" />
|
||||
@@ -141,7 +177,7 @@ const OAuth2ClientCredentials = ({ save, item = {}, request, handleRun, updateAu
|
||||
<div className="flex items-center gap-4 w-full" key={`input-token-placement`}>
|
||||
<label className="block min-w-[140px]">Add token to</label>
|
||||
<div className="inline-flex items-center cursor-pointer token-placement-selector w-fit">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<TokenPlacementIcon />} placement="bottom-end">
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={() => {
|
||||
@@ -183,10 +219,10 @@ const OAuth2ClientCredentials = ({ save, item = {}, request, handleRun, updateAu
|
||||
<label className="block font-medium min-w-[140px]">Query Param Key</label>
|
||||
<div className="single-line-editor-wrapper flex-1">
|
||||
<SingleLineEditor
|
||||
value={oAuth['tokenQueryParamKey'] || ''}
|
||||
value={oAuth['tokenQueryKey'] || ''}
|
||||
theme={storedTheme}
|
||||
onSave={handleSave}
|
||||
onChange={(val) => handleChange('tokenQueryParamKey', val)}
|
||||
onChange={(val) => handleChange('tokenQueryKey', val)}
|
||||
onRun={handleRun}
|
||||
collection={collection}
|
||||
/>
|
||||
|
||||
@@ -6,13 +6,16 @@ import StyledWrapper from './StyledWrapper';
|
||||
import { IconCaretDown, IconKey } from '@tabler/icons';
|
||||
import { humanizeGrantType } from 'utils/collections';
|
||||
import { useEffect } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
const GrantTypeSelector = ({ item = {}, request, updateAuth, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
const dropdownTippyRef = useRef();
|
||||
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||
|
||||
const oAuth = get(request, 'auth.oauth2', {});
|
||||
const [valuesCache, setValuesCache] = useState({
|
||||
...oAuth
|
||||
});
|
||||
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||
|
||||
const Icon = forwardRef((props, ref) => {
|
||||
return (
|
||||
@@ -23,13 +26,19 @@ const GrantTypeSelector = ({ item = {}, request, updateAuth, collection }) => {
|
||||
});
|
||||
|
||||
const onGrantTypeChange = (grantType) => {
|
||||
let updatedValues = {
|
||||
...valuesCache,
|
||||
...oAuth,
|
||||
grantType
|
||||
};
|
||||
setValuesCache(updatedValues);
|
||||
dispatch(
|
||||
updateAuth({
|
||||
mode: 'oauth2',
|
||||
collectionUid: collection.uid,
|
||||
itemUid: item.uid,
|
||||
content: {
|
||||
...(defaultValues?.[grantType] || {})
|
||||
...updatedValues
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -52,10 +61,11 @@ const GrantTypeSelector = ({ item = {}, request, updateAuth, collection }) => {
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
scope: '',
|
||||
credentialsPlacement: 'body',
|
||||
credentialsId: 'credentials',
|
||||
tokenPlacement: 'header',
|
||||
tokenPrefix: 'Bearer',
|
||||
tokenQueryParamKey: 'access_token',
|
||||
tokenQueryKey: 'access_token',
|
||||
reuseToken: false
|
||||
}
|
||||
})
|
||||
@@ -106,47 +116,4 @@ const GrantTypeSelector = ({ item = {}, request, updateAuth, collection }) => {
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
export default GrantTypeSelector;
|
||||
|
||||
const defaultValues = {
|
||||
'authorization_code': {
|
||||
grantType: 'authorization_code',
|
||||
accessTokenUrl: '',
|
||||
username: '',
|
||||
password: '',
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
scope: '',
|
||||
credentialsId: 'credentials',
|
||||
tokenPlacement: 'header',
|
||||
tokenPrefix: 'Bearer',
|
||||
tokenQueryParamKey: 'access_token',
|
||||
reuseToken: false
|
||||
},
|
||||
'client_credentials': {
|
||||
grantType: 'client_credentials',
|
||||
accessTokenUrl: '',
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
scope: '',
|
||||
credentialsId: 'credentials',
|
||||
tokenPlacement: 'header',
|
||||
tokenPrefix: 'Bearer',
|
||||
tokenQueryParamKey: 'access_token',
|
||||
reuseToken: false
|
||||
},
|
||||
'password': {
|
||||
grantType: 'password',
|
||||
accessTokenUrl: '',
|
||||
username: '',
|
||||
password: '',
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
scope: '',
|
||||
credentialsId: 'credentials',
|
||||
tokenPlacement: 'header',
|
||||
tokenPrefix: 'Bearer',
|
||||
tokenQueryParamKey: 'access_token',
|
||||
reuseToken: false
|
||||
}
|
||||
}
|
||||
export default GrantTypeSelector;
|
||||
@@ -37,12 +37,15 @@ const TokenSection = ({ title, token }) => {
|
||||
className="flex items-center justify-between px-3 py-2 bg-gray-50 dark:bg-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-750 transition-colors"
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="flex items-center space-x-2 w-full">
|
||||
{isExpanded ?
|
||||
<IconChevronDown size={18} className="text-gray-500" /> :
|
||||
<IconChevronRight size={18} className="text-gray-500" />
|
||||
}
|
||||
<div className="flex flex-row justify-between w-full">
|
||||
<h3 className="text-sm font-medium">{title}</h3>
|
||||
{decodedToken?.exp && <ExpiryTimer expiresIn={decodedToken?.exp}/>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{isExpanded && (
|
||||
@@ -86,62 +89,48 @@ const TokenSection = ({ title, token }) => {
|
||||
};
|
||||
|
||||
const formatExpiryTime = (seconds) => {
|
||||
if (seconds < 60) {
|
||||
return `${seconds}s`;
|
||||
} else if (seconds < 3600) {
|
||||
const mins = Math.floor(seconds / 60);
|
||||
const secs = seconds % 60;
|
||||
return `${mins}m ${secs}s`;
|
||||
} else {
|
||||
const hours = Math.floor(seconds / 3600);
|
||||
const mins = Math.floor((seconds % 3600) / 60);
|
||||
return `${hours}h ${mins}m`;
|
||||
}
|
||||
if (seconds < 60) return `${seconds}s`;
|
||||
if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
||||
return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m`;
|
||||
};
|
||||
|
||||
const ExpiryTimer = ({ initialExpiresIn }) => {
|
||||
const [timeLeft, setTimeLeft] = useState(initialExpiresIn);
|
||||
const ExpiryTimer = ({ expiresIn }) => {
|
||||
if (!expiresIn) return null;
|
||||
|
||||
const [timeLeft, setTimeLeft] = useState(() => Math.max(0, Math.floor((expiresIn - Date.now() / 1000))));
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setTimeLeft(prev => {
|
||||
if (prev <= 0) {
|
||||
clearInterval(timer);
|
||||
return 0;
|
||||
}
|
||||
return prev - 1;
|
||||
});
|
||||
setTimeLeft((prev) => (prev > 0 ? prev - 1 : 0));
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={`text-xs px-2 py-1 rounded-full ${
|
||||
timeLeft <= 30
|
||||
? 'bg-red-50 dark:bg-red-900/30 text-red-600 dark:text-red-400'
|
||||
: 'bg-blue-50 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400'
|
||||
}`}>
|
||||
Expires in {formatExpiryTime(timeLeft)}
|
||||
<div
|
||||
className={`text-xs px-2 py-1 rounded-full ${
|
||||
timeLeft <= 30
|
||||
? "bg-red-50 dark:bg-red-900/30 text-red-600 dark:text-red-400"
|
||||
: "bg-blue-50 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400"
|
||||
}`}
|
||||
>
|
||||
{timeLeft > 0 ? `Expires in ${formatExpiryTime(timeLeft)}` : `Expired` }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const Oauth2TokenViewer = ({ collection, item, url, credentialsId, handleRun }) => {
|
||||
const { uid: collectionUid } = collection;
|
||||
const interpolatedUrl = interpolateStringUsingCollectionAndItem({ collection, item, string: url });
|
||||
const credentialsData = find(collection?.oauth2Credentials, creds => creds?.url == interpolatedUrl && creds?.collectionUid == collectionUid && creds?.credentialsId == credentialsId);
|
||||
const creds = credentialsData?.credentials;
|
||||
const creds = credentialsData?.credentials || {};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="relative w-auto h-fit mt-2">
|
||||
{creds ? (
|
||||
{Object.keys(creds)?.length ? (
|
||||
<div className="border border-gray-200 dark:border-gray-700 rounded-lg p-4 shadow-sm">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h2 className="text-sm font-medium">Token</h2>
|
||||
{creds?.expires_in && <ExpiryTimer initialExpiresIn={creds.expires_in} />}
|
||||
</div>
|
||||
|
||||
<TokenSection title="Access Token" token={creds.access_token} />
|
||||
<TokenSection title="Refresh Token" token={creds.refresh_token} />
|
||||
<TokenSection title="ID Token" token={creds.id_token} />
|
||||
|
||||
@@ -22,7 +22,7 @@ const OAuth2PasswordCredentials = ({ save, item = {}, request, handleRun, update
|
||||
|
||||
const oAuth = get(request, 'auth.oauth2', {});
|
||||
|
||||
const { accessTokenUrl, username, password, clientId, clientSecret, scope, credentialsId, tokenPlacement, tokenPrefix, tokenQueryParamKey, reuseToken } = oAuth;
|
||||
const { accessTokenUrl, username, password, clientId, clientSecret, scope, credentialsPlacement, credentialsId, tokenPlacement, tokenPrefix, tokenQueryKey, reuseToken } = oAuth;
|
||||
|
||||
const handleFetchOauth2Credentials = async () => {
|
||||
let requestCopy = cloneDeep(request);
|
||||
@@ -32,20 +32,30 @@ const OAuth2PasswordCredentials = ({ save, item = {}, request, handleRun, update
|
||||
try {
|
||||
await dispatch(fetchOauth2Credentials({ request: requestCopy, collection }));
|
||||
toggleFetchingToken(false);
|
||||
toast.success('Token fetched successfully!');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('could not fetch the token!');
|
||||
console.error(error);
|
||||
toggleFetchingToken(false);
|
||||
toast.error('An error occured while fetching token!');
|
||||
}
|
||||
}
|
||||
|
||||
const handleSave = () => { save(); }
|
||||
|
||||
const Icon = forwardRef((props, ref) => {
|
||||
const TokenPlacementIcon = forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-end token-placement-label select-none">
|
||||
{tokenPlacement == 'url' ? 'URL' : 'Headers'}
|
||||
{tokenPlacement == 'url' ? 'URL' : 'Headers'}
|
||||
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const CredentialsPlacementIcon = forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-end token-placement-label select-none">
|
||||
{credentialsPlacement == 'body' ? 'Request Body' : 'Basic Auth Header'}
|
||||
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
|
||||
</div>
|
||||
);
|
||||
@@ -65,10 +75,11 @@ const OAuth2PasswordCredentials = ({ save, item = {}, request, handleRun, update
|
||||
clientId,
|
||||
clientSecret,
|
||||
scope,
|
||||
credentialsPlacement,
|
||||
credentialsId,
|
||||
tokenPlacement,
|
||||
tokenPrefix,
|
||||
tokenQueryParamKey,
|
||||
tokenQueryKey,
|
||||
reuseToken,
|
||||
[key]: value
|
||||
}
|
||||
@@ -118,6 +129,31 @@ const OAuth2PasswordCredentials = ({ save, item = {}, request, handleRun, update
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="flex items-center gap-4 w-full" key={`input-credentials-placement`}>
|
||||
<label className="block min-w-[140px]">Add Credentials to</label>
|
||||
<div className="inline-flex items-center cursor-pointer token-placement-selector">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<CredentialsPlacementIcon />} placement="bottom-end">
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={() => {
|
||||
dropdownTippyRef.current.hide();
|
||||
handleChange('credentialsPlacement', 'body');
|
||||
}}
|
||||
>
|
||||
Request Body
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={() => {
|
||||
dropdownTippyRef.current.hide();
|
||||
handleChange('credentialsPlacement', 'basic_auth_header');
|
||||
}}
|
||||
>
|
||||
Basic Auth Header
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2.5 mt-2">
|
||||
<div className="flex items-center px-2.5 py-1.5 bg-indigo-50/50 dark:bg-indigo-500/10 rounded-md">
|
||||
<IconKey size={14} className="text-indigo-500 dark:text-indigo-400" />
|
||||
@@ -143,7 +179,7 @@ const OAuth2PasswordCredentials = ({ save, item = {}, request, handleRun, update
|
||||
<div className="flex items-center gap-4 w-full" key={`input-token-placement`}>
|
||||
<label className="block min-w-[140px]">Add token to</label>
|
||||
<div className="inline-flex items-center cursor-pointer token-placement-selector">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<TokenPlacementIcon />} placement="bottom-end">
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={() => {
|
||||
@@ -185,10 +221,10 @@ const OAuth2PasswordCredentials = ({ save, item = {}, request, handleRun, update
|
||||
<label className="block font-medium min-w-[140px]">Query Param Key</label>
|
||||
<div className="single-line-editor-wrapper flex-1">
|
||||
<SingleLineEditor
|
||||
value={oAuth['tokenQueryParamKey'] || ''}
|
||||
value={oAuth['tokenQueryKey'] || ''}
|
||||
theme={storedTheme}
|
||||
onSave={handleSave}
|
||||
onChange={(val) => handleChange('tokenQueryParamKey', val)}
|
||||
onChange={(val) => handleChange('tokenQueryKey', val)}
|
||||
onRun={handleRun}
|
||||
collection={collection}
|
||||
/>
|
||||
|
||||
@@ -1225,7 +1225,7 @@ export const clearOauth2Cache = (payload) => async (dispatch, getState) => {
|
||||
const { collectionUid, url, credentialsId } = payload;
|
||||
return new Promise((resolve, reject) => {
|
||||
const { ipcRenderer } = window;
|
||||
ipcRenderer.invoke('clear-oauth2-cache', collectionUid, url, credentialsId).then(resolve => {
|
||||
ipcRenderer.invoke('clear-oauth2-cache', collectionUid, url, credentialsId).then(() => {
|
||||
dispatch(collectionClearOauth2CredentialsByUrl({ collectionUid, url, credentialsId }));
|
||||
resolve();
|
||||
}).catch(reject);
|
||||
|
||||
@@ -361,10 +361,11 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
|
||||
clientId: get(si.request, 'auth.oauth2.clientId', ''),
|
||||
clientSecret: get(si.request, 'auth.oauth2.clientSecret', ''),
|
||||
scope: get(si.request, 'auth.oauth2.scope', ''),
|
||||
credentialsPlacement: get(si.request, 'auth.oauth2.credentialsPlacement', 'body'),
|
||||
credentialsId: get(si.request, 'auth.oauth2.credentialsId', 'credentials'),
|
||||
tokenPlacement: get(si.request, 'auth.oauth2.tokenPlacement', 'header'),
|
||||
tokenPrefix: get(si.request, 'auth.oauth2.tokenPrefix', 'Bearer'),
|
||||
tokenQueryParamKey: get(si.request, 'auth.oauth2.tokenQueryParamKey', ''),
|
||||
tokenQueryKey: get(si.request, 'auth.oauth2.tokenQueryKey', ''),
|
||||
reuseToken: get(si.request, 'auth.oauth2.reuseToken', false)
|
||||
};
|
||||
break;
|
||||
@@ -377,11 +378,12 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
|
||||
clientId: get(si.request, 'auth.oauth2.clientId', ''),
|
||||
clientSecret: get(si.request, 'auth.oauth2.clientSecret', ''),
|
||||
scope: get(si.request, 'auth.oauth2.scope', ''),
|
||||
credentialsPlacement: get(si.request, 'auth.oauth2.credentialsPlacement', 'body'),
|
||||
pkce: get(si.request, 'auth.oauth2.pkce', false),
|
||||
credentialsId: get(si.request, 'auth.oauth2.credentialsId', 'credentials'),
|
||||
tokenPlacement: get(si.request, 'auth.oauth2.tokenPlacement', 'header'),
|
||||
tokenPrefix: get(si.request, 'auth.oauth2.tokenPrefix', 'Bearer'),
|
||||
tokenQueryParamKey: get(si.request, 'auth.oauth2.tokenQueryParamKey', ''),
|
||||
tokenQueryKey: get(si.request, 'auth.oauth2.tokenQueryKey', ''),
|
||||
reuseToken: get(si.request, 'auth.oauth2.reuseToken', false)
|
||||
};
|
||||
break;
|
||||
@@ -392,10 +394,11 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
|
||||
clientId: get(si.request, 'auth.oauth2.clientId', ''),
|
||||
clientSecret: get(si.request, 'auth.oauth2.clientSecret', ''),
|
||||
scope: get(si.request, 'auth.oauth2.scope', ''),
|
||||
credentialsPlacement: get(si.request, 'auth.oauth2.credentialsPlacement', 'body'),
|
||||
credentialsId: get(si.request, 'auth.oauth2.credentialsId', 'credentials'),
|
||||
tokenPlacement: get(si.request, 'auth.oauth2.tokenPlacement', 'header'),
|
||||
tokenPrefix: get(si.request, 'auth.oauth2.tokenPrefix', 'Bearer'),
|
||||
tokenQueryParamKey: get(si.request, 'auth.oauth2.tokenQueryParamKey', ''),
|
||||
tokenQueryKey: get(si.request, 'auth.oauth2.tokenQueryKey', ''),
|
||||
reuseToken: get(si.request, 'auth.oauth2.reuseToken', false)
|
||||
};
|
||||
break;
|
||||
@@ -1045,7 +1048,7 @@ export const getFormattedCollectionOauth2Credentials = ({ oauth2Credentials = []
|
||||
let credentialsVariables = {};
|
||||
oauth2Credentials.forEach(({ credentialsId, credentials }) => {
|
||||
Object.entries(credentials).forEach(([key, value]) => {
|
||||
credentialsVariables[`$auth.${credentialsId}.${key}`] = value;
|
||||
credentialsVariables[`$oauth2.${credentialsId}.${key}`] = value;
|
||||
});
|
||||
});
|
||||
return credentialsVariables;
|
||||
|
||||
@@ -147,13 +147,13 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
|
||||
// todo: we have things happening in two places w.r.t basic auth
|
||||
// need to refactor this in the future
|
||||
// the request.auth (basic auth) object gets set inside the prepare-request.js file
|
||||
if (request.auth) {
|
||||
const username = _interpolate(request.auth.username) || '';
|
||||
const password = _interpolate(request.auth.password) || '';
|
||||
if (request.basicAuth) {
|
||||
const username = _interpolate(request.basicAuth.username) || '';
|
||||
const password = _interpolate(request.basicAuth.password) || '';
|
||||
|
||||
// use auth header based approach and delete the request.auth object
|
||||
request.headers['Authorization'] = `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`;
|
||||
delete request.auth;
|
||||
delete request.basicAuth;
|
||||
}
|
||||
|
||||
if (request.awsv4config) {
|
||||
@@ -165,12 +165,14 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
|
||||
request.awsv4config.profileName = _interpolate(request.awsv4config.profileName) || '';
|
||||
}
|
||||
|
||||
// interpolate vars for ntlmConfig auth
|
||||
if (request.ntlmConfig) {
|
||||
request.ntlmConfig.username = _interpolate(request.ntlmConfig.username) || '';
|
||||
request.ntlmConfig.password = _interpolate(request.ntlmConfig.password) || '';
|
||||
request.ntlmConfig.domain = _interpolate(request.ntlmConfig.domain) || '';
|
||||
}
|
||||
// interpolate vars for ntlmConfig auth
|
||||
if (request.ntlmConfig) {
|
||||
request.ntlmConfig.username = _interpolate(request.ntlmConfig.username) || '';
|
||||
request.ntlmConfig.password = _interpolate(request.ntlmConfig.password) || '';
|
||||
request.ntlmConfig.domain = _interpolate(request.ntlmConfig.domain) || '';
|
||||
}
|
||||
|
||||
if(request?.auth) delete request.auth;
|
||||
|
||||
if (request) return request;
|
||||
};
|
||||
|
||||
@@ -38,7 +38,7 @@ const prepareRequest = (item = {}, collection = {}) => {
|
||||
const collectionAuth = get(collection, 'root.request.auth');
|
||||
if (collectionAuth && request.auth?.mode === 'inherit') {
|
||||
if (collectionAuth.mode === 'basic') {
|
||||
axiosRequest.auth = {
|
||||
axiosRequest.basicAuth = {
|
||||
username: get(collectionAuth, 'basic.username'),
|
||||
password: get(collectionAuth, 'basic.password')
|
||||
};
|
||||
@@ -69,7 +69,7 @@ const prepareRequest = (item = {}, collection = {}) => {
|
||||
|
||||
if (request.auth && request.auth.mode !== 'inherit') {
|
||||
if (request.auth.mode === 'basic') {
|
||||
axiosRequest.auth = {
|
||||
axiosRequest.basicAuth = {
|
||||
username: get(request, 'auth.basic.username'),
|
||||
password: get(request, 'auth.basic.password')
|
||||
};
|
||||
|
||||
@@ -149,12 +149,12 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
|
||||
// todo: we have things happening in two places w.r.t basic auth
|
||||
// need to refactor this in the future
|
||||
// the request.auth (basic auth) object gets set inside the prepare-request.js file
|
||||
if (request.auth) {
|
||||
const username = _interpolate(request.auth.username) || '';
|
||||
const password = _interpolate(request.auth.password) || '';
|
||||
if (request.basicAuth) {
|
||||
const username = _interpolate(request.basicAuth.username) || '';
|
||||
const password = _interpolate(request.basicAuth.password) || '';
|
||||
// use auth header based approach and delete the request.auth object
|
||||
request.headers['Authorization'] = `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`;
|
||||
delete request.auth;
|
||||
delete request.basicAuth;
|
||||
}
|
||||
|
||||
if (request?.oauth2?.grantType) {
|
||||
@@ -167,10 +167,11 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
|
||||
request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
|
||||
request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
|
||||
request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
|
||||
request.oauth2.credentialsPlacement = _interpolate(request.oauth2.credentialsPlacement) || '';
|
||||
request.oauth2.credentialsId = _interpolate(request.oauth2.credentialsId) || '';
|
||||
request.oauth2.tokenPlacement = _interpolate(request.oauth2.tokenPlacement) || '';
|
||||
request.oauth2.tokenPrefix = _interpolate(request.oauth2.tokenPrefix) || '';
|
||||
request.oauth2.tokenQueryParamKey = _interpolate(request.oauth2.tokenQueryParamKey) || '';
|
||||
request.oauth2.tokenQueryKey = _interpolate(request.oauth2.tokenQueryKey) || '';
|
||||
request.oauth2.reuseToken = _interpolate(request.oauth2.reuseToken) || false;
|
||||
break;
|
||||
case 'authorization_code':
|
||||
@@ -182,10 +183,11 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
|
||||
request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
|
||||
request.oauth2.state = _interpolate(request.oauth2.state) || '';
|
||||
request.oauth2.pkce = _interpolate(request.oauth2.pkce) || false;
|
||||
request.oauth2.credentialsPlacement = _interpolate(request.oauth2.credentialsPlacement) || '';
|
||||
request.oauth2.credentialsId = _interpolate(request.oauth2.credentialsId) || '';
|
||||
request.oauth2.tokenPlacement = _interpolate(request.oauth2.tokenPlacement) || '';
|
||||
request.oauth2.tokenPrefix = _interpolate(request.oauth2.tokenPrefix) || '';
|
||||
request.oauth2.tokenQueryParamKey = _interpolate(request.oauth2.tokenQueryParamKey) || '';
|
||||
request.oauth2.tokenQueryKey = _interpolate(request.oauth2.tokenQueryKey) || '';
|
||||
request.oauth2.reuseToken = _interpolate(request.oauth2.reuseToken) || false;
|
||||
break;
|
||||
case 'client_credentials':
|
||||
@@ -193,10 +195,11 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
|
||||
request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
|
||||
request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
|
||||
request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
|
||||
request.oauth2.credentialsPlacement = _interpolate(request.oauth2.credentialsPlacement) || '';
|
||||
request.oauth2.credentialsId = _interpolate(request.oauth2.credentialsId) || '';
|
||||
request.oauth2.tokenPlacement = _interpolate(request.oauth2.tokenPlacement) || '';
|
||||
request.oauth2.tokenPrefix = _interpolate(request.oauth2.tokenPrefix) || '';
|
||||
request.oauth2.tokenQueryParamKey = _interpolate(request.oauth2.tokenQueryParamKey) || '';
|
||||
request.oauth2.tokenQueryKey = _interpolate(request.oauth2.tokenQueryKey) || '';
|
||||
request.oauth2.reuseToken = _interpolate(request.oauth2.reuseToken) || false;
|
||||
break;
|
||||
default:
|
||||
@@ -234,6 +237,8 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
|
||||
request.ntlmConfig.domain = _interpolate(request.ntlmConfig.domain) || '';
|
||||
}
|
||||
|
||||
if(request?.auth) delete request.auth;
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ const getFormattedCollectionOauth2Credentials = ({ oauth2Credentials = [] }) =>
|
||||
let credentialsVariables = {};
|
||||
oauth2Credentials.forEach(({ credentialsId, credentials }) => {
|
||||
Object.entries(credentials).forEach(([key, value]) => {
|
||||
credentialsVariables[`$auth.${credentialsId}.${key}`] = value;
|
||||
credentialsVariables[`$oauth2.${credentialsId}.${key}`] = value;
|
||||
});
|
||||
});
|
||||
return credentialsVariables;
|
||||
|
||||
@@ -3,7 +3,7 @@ const crypto = require('crypto');
|
||||
const { authorizeUserInWindow } = require('../ipc/network/authorize-user-in-window');
|
||||
const Oauth2Store = require('../store/oauth2');
|
||||
const { makeAxiosInstance } = require('./axios-instance');
|
||||
const { safeParseJSON } = require('./common');
|
||||
const { safeParseJSON, safeStringifyJSON } = require('./common');
|
||||
|
||||
const oauth2Store = new Oauth2Store();
|
||||
|
||||
@@ -31,38 +31,46 @@ const getOAuth2TokenUsingAuthorizationCode = async ({ request, collectionUid, fo
|
||||
|
||||
let requestCopy = cloneDeep(request);
|
||||
const oAuth = get(requestCopy, 'oauth2', {});
|
||||
const { clientId, clientSecret, callbackUrl, scope, pkce, authorizationUrl, credentialsId, reuseToken } = oAuth;
|
||||
const { clientId, clientSecret, callbackUrl, scope, pkce, credentialsPlacement, authorizationUrl, credentialsId, reuseToken } = oAuth;
|
||||
const url = requestCopy?.oauth2?.accessTokenUrl;
|
||||
|
||||
if ((reuseToken || ALWAYS_REUSE_ACCESS_TOKEN____UNLESS_FETCHED_MANUALLY) && !forceFetch) {
|
||||
const credentials = getStoredOauth2Credentials({ collectionUid, url, credentialsId }) || {};
|
||||
return { collectionUid, url, credentials, credentialsId };
|
||||
}
|
||||
|
||||
const { authorizationCode } = await getOAuth2AuthorizationCode(requestCopy, codeChallenge, collectionUid);
|
||||
const data = {
|
||||
grant_type: 'authorization_code',
|
||||
code: authorizationCode,
|
||||
redirect_uri: callbackUrl,
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret
|
||||
};
|
||||
if (pkce) {
|
||||
data['code_verifier'] = codeVerifier;
|
||||
}
|
||||
|
||||
requestCopy.method = 'POST';
|
||||
requestCopy.headers['content-type'] = 'application/x-www-form-urlencoded';
|
||||
requestCopy.headers['Accept'] = 'application/json';
|
||||
requestCopy.data = data;
|
||||
if (credentialsPlacement == "basic_auth_header") {
|
||||
requestCopy.headers['Authorization'] = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`;
|
||||
}
|
||||
else {
|
||||
const data = {
|
||||
grant_type: 'authorization_code',
|
||||
code: authorizationCode,
|
||||
redirect_uri: callbackUrl,
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret
|
||||
};
|
||||
if (pkce) {
|
||||
data['code_verifier'] = codeVerifier;
|
||||
}
|
||||
requestCopy.data = data;
|
||||
}
|
||||
requestCopy.url = url;
|
||||
|
||||
const axiosInstance = makeAxiosInstance();
|
||||
const response = await axiosInstance(requestCopy);
|
||||
const responseData = Buffer.isBuffer(response.data) ? response.data?.toString() : response.data;
|
||||
const parsedResponseData = safeParseJSON(responseData);
|
||||
persistOauth2Credentials({ collectionUid, url, credentials: parsedResponseData, credentialsId });
|
||||
return { collectionUid, url, credentials: parsedResponseData, credentialsId };
|
||||
try {
|
||||
const axiosInstance = makeAxiosInstance();
|
||||
const response = await axiosInstance(requestCopy);
|
||||
const responseData = Buffer.isBuffer(response.data) ? response.data?.toString() : response.data;
|
||||
const parsedResponseData = safeParseJSON(responseData);
|
||||
persistOauth2Credentials({ collectionUid, url, credentials: parsedResponseData, credentialsId });
|
||||
return { collectionUid, url, credentials: parsedResponseData, credentialsId };
|
||||
}
|
||||
catch (error) {
|
||||
return Promise.reject(safeStringifyJSON(error?.response?.data));
|
||||
}
|
||||
};
|
||||
|
||||
const getOAuth2AuthorizationCode = (request, codeChallenge, collectionUid) => {
|
||||
@@ -105,15 +113,7 @@ const getOAuth2AuthorizationCode = (request, codeChallenge, collectionUid) => {
|
||||
const getOAuth2TokenUsingClientCredentials = async ({ request, collectionUid, forceFetch = false }) => {
|
||||
let requestCopy = cloneDeep(request);
|
||||
const oAuth = get(requestCopy, 'oauth2', {});
|
||||
const { clientId, clientSecret, scope, credentialsId, reuseToken } = oAuth;
|
||||
const data = {
|
||||
grant_type: 'client_credentials',
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret
|
||||
};
|
||||
if (scope) {
|
||||
data.scope = scope;
|
||||
}
|
||||
const { clientId, clientSecret, scope, credentialsPlacement, credentialsId, reuseToken } = oAuth;
|
||||
|
||||
const url = requestCopy?.oauth2?.accessTokenUrl;
|
||||
|
||||
@@ -125,16 +125,34 @@ const getOAuth2TokenUsingClientCredentials = async ({ request, collectionUid, fo
|
||||
requestCopy.method = 'POST';
|
||||
requestCopy.headers['content-type'] = 'application/x-www-form-urlencoded';
|
||||
requestCopy.headers['Accept'] = 'application/json';
|
||||
requestCopy.data = data;
|
||||
if (credentialsPlacement == "basic_auth_header") {
|
||||
requestCopy.headers['Authorization'] = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`;
|
||||
}
|
||||
else {
|
||||
const data = {
|
||||
grant_type: 'client_credentials',
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret
|
||||
};
|
||||
if (scope) {
|
||||
data.scope = scope;
|
||||
}
|
||||
requestCopy.data = data;
|
||||
}
|
||||
requestCopy.url = url;
|
||||
|
||||
const axiosInstance = makeAxiosInstance();
|
||||
|
||||
const response = await axiosInstance(requestCopy);
|
||||
const responseData = Buffer.isBuffer(response.data) ? response.data?.toString() : response.data;
|
||||
const parsedResponseData = safeParseJSON(responseData);
|
||||
persistOauth2Credentials({ collectionUid, url, credentials: parsedResponseData, credentialsId });
|
||||
return { collectionUid, url, credentials: parsedResponseData, credentialsId };
|
||||
try {
|
||||
const response = await axiosInstance(requestCopy);
|
||||
const responseData = Buffer.isBuffer(response.data) ? response.data?.toString() : response.data;
|
||||
const parsedResponseData = safeParseJSON(responseData);
|
||||
persistOauth2Credentials({ collectionUid, url, credentials: parsedResponseData, credentialsId });
|
||||
return { collectionUid, url, credentials: parsedResponseData, credentialsId };
|
||||
}
|
||||
catch (error) {
|
||||
return Promise.reject(safeStringifyJSON(error?.response?.data));
|
||||
}
|
||||
};
|
||||
|
||||
// PASSWORD CREDENTIALS
|
||||
@@ -142,17 +160,7 @@ const getOAuth2TokenUsingClientCredentials = async ({ request, collectionUid, fo
|
||||
const getOAuth2TokenUsingPasswordCredentials = async ({ request, collectionUid, forceFetch = false }) => {
|
||||
let requestCopy = cloneDeep(request);
|
||||
const oAuth = get(requestCopy, 'oauth2', {});
|
||||
const { username, password, clientId, clientSecret, scope, credentialsId, reuseToken } = oAuth;
|
||||
const data = {
|
||||
grant_type: 'password',
|
||||
username,
|
||||
password,
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret
|
||||
};
|
||||
if (scope) {
|
||||
data.scope = scope;
|
||||
}
|
||||
const { username, password, clientId, clientSecret, scope, credentialsPlacement, credentialsId, reuseToken } = oAuth;
|
||||
const url = requestCopy?.oauth2?.accessTokenUrl;
|
||||
|
||||
if ((reuseToken || ALWAYS_REUSE_ACCESS_TOKEN____UNLESS_FETCHED_MANUALLY) && !forceFetch) {
|
||||
@@ -163,15 +171,35 @@ const getOAuth2TokenUsingPasswordCredentials = async ({ request, collectionUid,
|
||||
requestCopy.method = 'POST';
|
||||
requestCopy.headers['content-type'] = 'application/x-www-form-urlencoded';
|
||||
requestCopy.headers['Accept'] = 'application/json';
|
||||
requestCopy.data = data;
|
||||
if (credentialsPlacement == "basic_auth_header") {
|
||||
requestCopy.headers['Authorization'] = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`;
|
||||
}
|
||||
else {
|
||||
const data = {
|
||||
grant_type: 'password',
|
||||
username,
|
||||
password,
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret
|
||||
};
|
||||
if (scope) {
|
||||
data.scope = scope;
|
||||
}
|
||||
requestCopy.data = data;
|
||||
}
|
||||
requestCopy.url = url;
|
||||
|
||||
const axiosInstance = makeAxiosInstance();
|
||||
const response = await axiosInstance(requestCopy);
|
||||
const responseData = Buffer.isBuffer(response.data) ? response.data?.toString() : response.data;
|
||||
const parsedResponseData = safeParseJSON(responseData);
|
||||
persistOauth2Credentials({ collectionUid, url, credentials: parsedResponseData, credentialsId });
|
||||
return { collectionUid, url, credentials: parsedResponseData, credentialsId };
|
||||
try {
|
||||
const axiosInstance = makeAxiosInstance();
|
||||
const response = await axiosInstance(requestCopy);
|
||||
const responseData = Buffer.isBuffer(response.data) ? response.data?.toString() : response.data;
|
||||
const parsedResponseData = safeParseJSON(responseData);
|
||||
persistOauth2Credentials({ collectionUid, url, credentials: parsedResponseData, credentialsId });
|
||||
return { collectionUid, url, credentials: parsedResponseData, credentialsId };
|
||||
}
|
||||
catch (error) {
|
||||
return Promise.reject(safeStringifyJSON(error?.response?.data));
|
||||
}
|
||||
};
|
||||
|
||||
const refreshOauth2Token = async (request, collectionUid) => {
|
||||
@@ -207,9 +235,9 @@ const refreshOauth2Token = async (request, collectionUid) => {
|
||||
persistOauth2Credentials({ collectionUid, url, credentials: parsedResponseData, credentialsId });
|
||||
return { collectionUid, url, credentials: parsedResponseData, credentialsId };
|
||||
}
|
||||
catch(error) {
|
||||
catch (error) {
|
||||
clearOauth2Credentials({ collectionUid, url, credentialsId });
|
||||
return Promise.reject(error);
|
||||
return Promise.reject(safeStringifyJSON(error?.response?.data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
||||
};
|
||||
break;
|
||||
case 'basic':
|
||||
axiosRequest.auth = {
|
||||
axiosRequest.basicAuth = {
|
||||
username: get(collectionAuth, 'basic.username'),
|
||||
password: get(collectionAuth, 'basic.password')
|
||||
};
|
||||
@@ -97,10 +97,11 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
||||
clientId: get(collectionAuth, 'oauth2.clientId'),
|
||||
clientSecret: get(collectionAuth, 'oauth2.clientSecret'),
|
||||
scope: get(collectionAuth, 'oauth2.scope'),
|
||||
credentialsPlacement: get(collectionAuth, 'oauth2.credentialsPlacement'),
|
||||
credentialsId: get(collectionAuth, 'oauth2.credentialsId'),
|
||||
tokenPlacement: get(collectionAuth, 'oauth2.tokenPlacement'),
|
||||
tokenPrefix: get(collectionAuth, 'oauth2.tokenPrefix'),
|
||||
tokenQueryParamKey: get(collectionAuth, 'oauth2.tokenQueryParamKey'),
|
||||
tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey'),
|
||||
reuseToken: get(collectionAuth, 'oauth2.reuseToken')
|
||||
};
|
||||
break;
|
||||
@@ -115,10 +116,11 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
||||
scope: get(collectionAuth, 'oauth2.scope'),
|
||||
state: get(collectionAuth, 'oauth2.state'),
|
||||
pkce: get(collectionAuth, 'oauth2.pkce'),
|
||||
credentialsPlacement: get(collectionAuth, 'oauth2.credentialsPlacement'),
|
||||
credentialsId: get(collectionAuth, 'oauth2.credentialsId'),
|
||||
tokenPlacement: get(collectionAuth, 'oauth2.tokenPlacement'),
|
||||
tokenPrefix: get(collectionAuth, 'oauth2.tokenPrefix'),
|
||||
tokenQueryParamKey: get(collectionAuth, 'oauth2.tokenQueryParamKey'),
|
||||
tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey'),
|
||||
reuseToken: get(collectionAuth, 'oauth2.reuseToken')
|
||||
};
|
||||
break;
|
||||
@@ -129,10 +131,11 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
||||
clientId: get(collectionAuth, 'oauth2.clientId'),
|
||||
clientSecret: get(collectionAuth, 'oauth2.clientSecret'),
|
||||
scope: get(collectionAuth, 'oauth2.scope'),
|
||||
credentialsPlacement: get(collectionAuth, 'oauth2.credentialsPlacement'),
|
||||
credentialsId: get(collectionAuth, 'oauth2.credentialsId'),
|
||||
tokenPlacement: get(collectionAuth, 'oauth2.tokenPlacement'),
|
||||
tokenPrefix: get(collectionAuth, 'oauth2.tokenPrefix'),
|
||||
tokenQueryParamKey: get(collectionAuth, 'oauth2.tokenQueryParamKey'),
|
||||
tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey'),
|
||||
reuseToken: get(collectionAuth, 'oauth2.reuseToken')
|
||||
};
|
||||
break;
|
||||
@@ -154,7 +157,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
||||
};
|
||||
break;
|
||||
case 'basic':
|
||||
axiosRequest.auth = {
|
||||
axiosRequest.basicAuth = {
|
||||
username: get(request, 'auth.basic.username'),
|
||||
password: get(request, 'auth.basic.password')
|
||||
};
|
||||
@@ -186,10 +189,11 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
||||
clientId: get(request, 'auth.oauth2.clientId'),
|
||||
clientSecret: get(request, 'auth.oauth2.clientSecret'),
|
||||
scope: get(request, 'auth.oauth2.scope'),
|
||||
credentialsPlacement: get(request, 'auth.oauth2.credentialsPlacement'),
|
||||
credentialsId: get(request, 'auth.oauth2.credentialsId'),
|
||||
tokenPlacement: get(request, 'auth.oauth2.tokenPlacement'),
|
||||
tokenPrefix: get(request, 'auth.oauth2.tokenPrefix'),
|
||||
tokenQueryParamKey: get(request, 'auth.oauth2.tokenQueryParamKey'),
|
||||
tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey'),
|
||||
reuseToken: get(request, 'auth.oauth2.reuseToken')
|
||||
};
|
||||
break;
|
||||
@@ -204,10 +208,11 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
||||
scope: get(request, 'auth.oauth2.scope'),
|
||||
state: get(request, 'auth.oauth2.state'),
|
||||
pkce: get(request, 'auth.oauth2.pkce'),
|
||||
credentialsPlacement: get(request, 'auth.oauth2.credentialsPlacement'),
|
||||
credentialsId: get(request, 'auth.oauth2.credentialsId'),
|
||||
tokenPlacement: get(request, 'auth.oauth2.tokenPlacement'),
|
||||
tokenPrefix: get(request, 'auth.oauth2.tokenPrefix'),
|
||||
tokenQueryParamKey: get(request, 'auth.oauth2.tokenQueryParamKey'),
|
||||
tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey'),
|
||||
reuseToken: get(request, 'auth.oauth2.reuseToken')
|
||||
};
|
||||
break;
|
||||
@@ -218,10 +223,11 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
||||
clientId: get(request, 'auth.oauth2.clientId'),
|
||||
clientSecret: get(request, 'auth.oauth2.clientSecret'),
|
||||
scope: get(request, 'auth.oauth2.scope'),
|
||||
credentialsPlacement: get(request, 'auth.oauth2.credentialsPlacement'),
|
||||
credentialsId: get(request, 'auth.oauth2.credentialsId'),
|
||||
tokenPlacement: get(request, 'auth.oauth2.tokenPlacement'),
|
||||
tokenPrefix: get(request, 'auth.oauth2.tokenPrefix'),
|
||||
tokenQueryParamKey: get(request, 'auth.oauth2.tokenQueryParamKey'),
|
||||
tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey'),
|
||||
reuseToken: get(request, 'auth.oauth2.reuseToken')
|
||||
};
|
||||
break;
|
||||
@@ -607,7 +613,7 @@ const configureRequest = async (
|
||||
|
||||
if (request.oauth2) {
|
||||
let requestCopy = cloneDeep(request);
|
||||
const { oauth2: { grantType, tokenPlacement, tokenPrefix, tokenQueryParamKey } = {} } = requestCopy || {};
|
||||
const { oauth2: { grantType, tokenPlacement, tokenPrefix, tokenQueryKey } = {} } = requestCopy || {};
|
||||
let credentials, credentialsId;
|
||||
switch (grantType) {
|
||||
case 'authorization_code':
|
||||
@@ -620,7 +626,7 @@ const configureRequest = async (
|
||||
else {
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
url?.searchParams?.set(tokenQueryParamKey, credentials?.access_token);
|
||||
url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
|
||||
request.url = url?.toString();
|
||||
}
|
||||
catch(error) {}
|
||||
@@ -636,7 +642,7 @@ const configureRequest = async (
|
||||
else {
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
url?.searchParams?.set(tokenQueryParamKey, credentials?.access_token);
|
||||
url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
|
||||
request.url = url?.toString();
|
||||
}
|
||||
catch(error) {}
|
||||
@@ -652,7 +658,7 @@ const configureRequest = async (
|
||||
else {
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
url?.searchParams?.set(tokenQueryParamKey, credentials?.access_token);
|
||||
url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
|
||||
request.url = url?.toString();
|
||||
}
|
||||
catch(error) {}
|
||||
|
||||
@@ -484,11 +484,12 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
const scopeKey = _.find(auth, { name: 'scope' });
|
||||
const stateKey = _.find(auth, { name: 'state' });
|
||||
const pkceKey = _.find(auth, { name: 'pkce' });
|
||||
const credentialsIdKey = _.find(auth, { name: 'credentialsId' });
|
||||
const tokenPlacementKey = _.find(auth, { name: 'tokenPlacement' });
|
||||
const tokenPrefixKey = _.find(auth, { name: 'tokenPrefix' });
|
||||
const tokenQueryParamKeyKey = _.find(auth, { name: 'tokenQueryParamKey' });
|
||||
const reuseTokenKey = _.find(auth, { name: 'reuseToken' });
|
||||
const credentialsPlacementKey = _.find(auth, { name: 'credentials_placement' });
|
||||
const credentialsIdKey = _.find(auth, { name: 'credentials_id' });
|
||||
const tokenPlacementKey = _.find(auth, { name: 'token_placement' });
|
||||
const tokenPrefixKey = _.find(auth, { name: 'token_prefix' });
|
||||
const tokenQueryKeyKey = _.find(auth, { name: 'token_query_key' });
|
||||
const reuseTokenKey = _.find(auth, { name: 'reuse_token' });
|
||||
return {
|
||||
auth: {
|
||||
oauth2:
|
||||
@@ -501,10 +502,11 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
clientId: clientIdKey ? clientIdKey.value : '',
|
||||
clientSecret: clientSecretKey ? clientSecretKey.value : '',
|
||||
scope: scopeKey ? scopeKey.value : '',
|
||||
credentialsPlacement: credentialsPlacementKey?.value ? credentialsPlacementKey.value : 'body',
|
||||
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
|
||||
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
|
||||
tokenPrefix: tokenPrefixKey?.value ? tokenPrefixKey.value : 'Bearer',
|
||||
tokenQueryParamKey: tokenQueryParamKeyKey?.value ? tokenQueryParamKeyKey.value : 'access_token',
|
||||
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
|
||||
reuseToken: reuseTokenKey?.value ? JSON.parse(reuseTokenKey?.value || false) : false
|
||||
}
|
||||
: grantTypeKey?.value && grantTypeKey?.value == 'authorization_code'
|
||||
@@ -518,10 +520,11 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
scope: scopeKey ? scopeKey.value : '',
|
||||
state: stateKey ? stateKey.value : '',
|
||||
pkce: pkceKey ? JSON.parse(pkceKey?.value || false) : false,
|
||||
credentialsPlacement: credentialsPlacementKey?.value ? credentialsPlacementKey.value : 'body',
|
||||
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
|
||||
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
|
||||
tokenPrefix: tokenPrefixKey?.value ? tokenPrefixKey.value : 'Bearer',
|
||||
tokenQueryParamKey: tokenQueryParamKeyKey?.value ? tokenQueryParamKeyKey.value : 'access_token',
|
||||
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
|
||||
reuseToken: reuseTokenKey?.value ? JSON.parse(reuseTokenKey?.value || false) : false
|
||||
}
|
||||
: grantTypeKey?.value && grantTypeKey?.value == 'client_credentials'
|
||||
@@ -531,10 +534,11 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
clientId: clientIdKey ? clientIdKey.value : '',
|
||||
clientSecret: clientSecretKey ? clientSecretKey.value : '',
|
||||
scope: scopeKey ? scopeKey.value : '',
|
||||
credentialsPlacement: credentialsPlacementKey?.value ? credentialsPlacementKey.value : 'body',
|
||||
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
|
||||
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
|
||||
tokenPrefix: tokenPrefixKey?.value ? tokenPrefixKey.value : 'Bearer',
|
||||
tokenQueryParamKey: tokenQueryParamKeyKey?.value ? tokenQueryParamKeyKey.value : 'access_token',
|
||||
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
|
||||
reuseToken: reuseTokenKey?.value ? JSON.parse(reuseTokenKey?.value || false) : false
|
||||
}
|
||||
: {}
|
||||
|
||||
@@ -279,10 +279,11 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
const scopeKey = _.find(auth, { name: 'scope' });
|
||||
const stateKey = _.find(auth, { name: 'state' });
|
||||
const pkceKey = _.find(auth, { name: 'pkce' });
|
||||
const credentialsIdKey = _.find(auth, { name: 'credentialsId' });
|
||||
const tokenPlacementKey = _.find(auth, { name: 'tokenPlacement' });
|
||||
const tokenPrefixKey = _.find(auth, { name: 'tokenPrefix' });
|
||||
const tokenQueryParamKeyKey = _.find(auth, { name: 'tokenQueryParamKey' });
|
||||
const credentialsPlacementKey = _.find(auth, { name: 'credentials_placement' });
|
||||
const credentialsIdKey = _.find(auth, { name: 'credentials_id' });
|
||||
const tokenPlacementKey = _.find(auth, { name: 'token_placement' });
|
||||
const tokenPrefixKey = _.find(auth, { name: 'token_prefix' });
|
||||
const tokenQueryKeyKey = _.find(auth, { name: 'token_query_key' });
|
||||
const reuseTokenKey = _.find(auth, { name: 'reuseToken' });
|
||||
return {
|
||||
auth: {
|
||||
@@ -296,10 +297,11 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
clientId: clientIdKey ? clientIdKey.value : '',
|
||||
clientSecret: clientSecretKey ? clientSecretKey.value : '',
|
||||
scope: scopeKey ? scopeKey.value : '',
|
||||
credentialsPlacement: credentialsPlacementKey?.value ? credentialsPlacementKey.value : 'body',
|
||||
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
|
||||
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
|
||||
tokenPrefix: tokenPrefixKey?.value ? tokenPrefixKey.value : 'Bearer',
|
||||
tokenQueryParamKey: tokenQueryParamKeyKey?.value ? tokenQueryParamKeyKey.value : 'access_token',
|
||||
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
|
||||
reuseToken: reuseTokenKey?.value ? JSON.parse(reuseTokenKey?.value || false) : false
|
||||
}
|
||||
: grantTypeKey?.value && grantTypeKey?.value == 'authorization_code'
|
||||
@@ -313,10 +315,11 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
scope: scopeKey ? scopeKey.value : '',
|
||||
state: stateKey ? stateKey.value : '',
|
||||
pkce: pkceKey ? JSON.parse(pkceKey?.value || false) : false,
|
||||
credentialsPlacement: credentialsPlacementKey?.value ? credentialsPlacementKey.value : 'body',
|
||||
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
|
||||
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
|
||||
tokenPrefix: tokenPrefixKey?.value ? tokenPrefixKey.value : 'Bearer',
|
||||
tokenQueryParamKey: tokenQueryParamKeyKey?.value ? tokenQueryParamKeyKey.value : 'access_token',
|
||||
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
|
||||
reuseToken: reuseTokenKey?.value ? JSON.parse(reuseTokenKey?.value || false) : false
|
||||
}
|
||||
: grantTypeKey?.value && grantTypeKey?.value == 'client_credentials'
|
||||
@@ -326,10 +329,11 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
clientId: clientIdKey ? clientIdKey.value : '',
|
||||
clientSecret: clientSecretKey ? clientSecretKey.value : '',
|
||||
scope: scopeKey ? scopeKey.value : '',
|
||||
credentialsPlacement: credentialsPlacementKey?.value ? credentialsPlacementKey.value : 'body',
|
||||
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
|
||||
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
|
||||
tokenPrefix: tokenPrefixKey?.value ? tokenPrefixKey.value : 'Bearer',
|
||||
tokenQueryParamKey: tokenQueryParamKeyKey?.value ? tokenQueryParamKeyKey.value : 'access_token',
|
||||
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
|
||||
reuseToken: reuseTokenKey?.value ? JSON.parse(reuseTokenKey?.value || false) : false
|
||||
}
|
||||
: {}
|
||||
|
||||
@@ -188,11 +188,14 @@ ${indentString(`password: ${auth?.oauth2?.password || ''}`)}
|
||||
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
|
||||
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
||||
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||
${indentString(`credentialsId: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`tokenPlacement: ${auth?.oauth2?.tokenPlacement || ''}`)}
|
||||
${indentString(`tokenPrefix: ${auth?.oauth2?.tokenPrefix || ''}`)}
|
||||
${indentString(`tokenQueryParamKey: ${auth?.oauth2?.tokenQueryParamKey || ''}`)}
|
||||
${indentString(`reuseToken: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
${indentString(`credentials_placement: ${auth?.oauth2?.credentialsPlacement || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_prefix: ${auth?.oauth2?.tokenPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`reuse_token: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
}
|
||||
|
||||
`;
|
||||
@@ -208,11 +211,14 @@ ${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
||||
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||
${indentString(`state: ${auth?.oauth2?.state || ''}`)}
|
||||
${indentString(`pkce: ${(auth?.oauth2?.pkce || false).toString()}`)}
|
||||
${indentString(`credentialsId: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`tokenPlacement: ${auth?.oauth2?.tokenPlacement || ''}`)}
|
||||
${indentString(`tokenPrefix: ${auth?.oauth2?.tokenPrefix || ''}`)}
|
||||
${indentString(`tokenQueryParamKey: ${auth?.oauth2?.tokenQueryParamKey || ''}`)}
|
||||
${indentString(`reuseToken: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
${indentString(`credentials_placement: ${auth?.oauth2?.credentialsPlacement || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_prefix: ${auth?.oauth2?.tokenPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`reuse_token: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
}
|
||||
|
||||
`;
|
||||
@@ -224,11 +230,14 @@ ${indentString(`access_token_url: ${auth?.oauth2?.accessTokenUrl || ''}`)}
|
||||
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
|
||||
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
||||
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||
${indentString(`credentialsId: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`tokenPlacement: ${auth?.oauth2?.tokenPlacement || ''}`)}
|
||||
${indentString(`tokenPrefix: ${auth?.oauth2?.tokenPrefix || ''}`)}
|
||||
${indentString(`tokenQueryParamKey: ${auth?.oauth2?.tokenQueryParamKey || ''}`)}
|
||||
${indentString(`reuseToken: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
${indentString(`credentials_placement: ${auth?.oauth2?.credentialsPlacement || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_prefix: ${auth?.oauth2?.tokenPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`reuse_token: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
@@ -154,11 +154,14 @@ ${indentString(`password: ${auth?.oauth2?.password || ''}`)}
|
||||
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
|
||||
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
||||
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||
${indentString(`credentialsId: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`tokenPlacement: ${auth?.oauth2?.tokenPlacement || ''}`)}
|
||||
${indentString(`tokenPrefix: ${auth?.oauth2?.tokenPrefix || ''}`)}
|
||||
${indentString(`tokenQueryParamKey: ${auth?.oauth2?.tokenQueryParamKey || ''}`)}
|
||||
${indentString(`reuseToken: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
${indentString(`credentials_placement: ${auth?.oauth2?.credentialsPlacement || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_prefix: ${auth?.oauth2?.tokenPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`reuse_token: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
}
|
||||
|
||||
`;
|
||||
@@ -174,11 +177,14 @@ ${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
||||
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||
${indentString(`state: ${auth?.oauth2?.state || ''}`)}
|
||||
${indentString(`pkce: ${(auth?.oauth2?.pkce || false).toString()}`)}
|
||||
${indentString(`credentialsId: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`tokenPlacement: ${auth?.oauth2?.tokenPlacement || ''}`)}
|
||||
${indentString(`tokenPrefix: ${auth?.oauth2?.tokenPrefix || ''}`)}
|
||||
${indentString(`tokenQueryParamKey: ${auth?.oauth2?.tokenQueryParamKey || ''}`)}
|
||||
${indentString(`reuseToken: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
${indentString(`credentials_placement: ${auth?.oauth2?.credentialsPlacement || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_prefix: ${auth?.oauth2?.tokenPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`reuse_token: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
}
|
||||
|
||||
`;
|
||||
@@ -190,11 +196,14 @@ ${indentString(`access_token_url: ${auth?.oauth2?.accessTokenUrl || ''}`)}
|
||||
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
|
||||
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
||||
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||
${indentString(`credentialsId: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`tokenPlacement: ${auth?.oauth2?.tokenPlacement || ''}`)}
|
||||
${indentString(`tokenPrefix: ${auth?.oauth2?.tokenPrefix || ''}`)}
|
||||
${indentString(`tokenQueryParamKey: ${auth?.oauth2?.tokenQueryParamKey || ''}`)}
|
||||
${indentString(`reuseToken: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
${indentString(`credentials_placement: ${auth?.oauth2?.credentialsPlacement || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_prefix: ${auth?.oauth2?.tokenPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`reuse_token: ${auth?.oauth2?.reuseToken || ''}`)}
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
@@ -200,6 +200,11 @@ const oauth2Schema = Yup.object({
|
||||
then: Yup.boolean().default(false),
|
||||
otherwise: Yup.boolean()
|
||||
}),
|
||||
credentialsPlacement: Yup.string().when('grantType', {
|
||||
is: (val) => ['client_credentials', 'password', 'authorization_code'].includes(val),
|
||||
then: Yup.string().nullable(),
|
||||
otherwise: Yup.string().nullable().strip()
|
||||
}),
|
||||
credentialsId: Yup.string().when('grantType', {
|
||||
is: (val) => ['client_credentials', 'password', 'authorization_code'].includes(val),
|
||||
then: Yup.string().nullable(),
|
||||
@@ -216,7 +221,7 @@ const oauth2Schema = Yup.object({
|
||||
then: Yup.string().nullable(),
|
||||
otherwise: Yup.string().nullable().strip()
|
||||
}),
|
||||
tokenQueryParamKey: Yup.string().when(['grantType', 'tokenPlacement'], {
|
||||
tokenQueryKey: Yup.string().when(['grantType', 'tokenPlacement'], {
|
||||
is: (grantType, tokenPlacement) =>
|
||||
['client_credentials', 'password', 'authorization_code'].includes(grantType) && tokenPlacement === 'url',
|
||||
then: Yup.string().nullable(),
|
||||
|
||||
@@ -12,9 +12,9 @@ auth:oauth2 {
|
||||
scope: openid
|
||||
state:
|
||||
pkce: true
|
||||
credentialsId: keycloak
|
||||
tokenPlacement: header
|
||||
tokenPrefix: Bearer
|
||||
tokenQueryParamKey: access_token
|
||||
reuseToken:
|
||||
credentials_placement: body
|
||||
credentials_id: credentials
|
||||
token_placement: header
|
||||
token_prefix: Bearer
|
||||
reuse_token:
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@ get {
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{$auth.keycloak.access_token}}
|
||||
token: {{$oauth2.keycloak.access_token}}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ auth:oauth2 {
|
||||
scope: openid
|
||||
state:
|
||||
pkce: true
|
||||
credentialsId: keycloak_request
|
||||
tokenPlacement: header
|
||||
tokenPrefix: Bearer
|
||||
tokenQueryParamKey: token
|
||||
reuseToken:
|
||||
credentials_placement: body
|
||||
credentials_id: credentials
|
||||
token_placement: header
|
||||
token_prefix: Bearer
|
||||
reuse_token:
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"version": "1",
|
||||
"name": "keycloak-client-credentials",
|
||||
"type": "collection",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
".git"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
auth {
|
||||
mode: oauth2
|
||||
}
|
||||
|
||||
auth:oauth2 {
|
||||
grant_type: authorization_code
|
||||
callback_url: {{key-host}}/realms/bruno/account
|
||||
authorization_url: {{key-host}}/realms/bruno/protocol/openid-connect/auth
|
||||
access_token_url: {{key-host}}/realms/bruno/protocol/openid-connect/token
|
||||
client_id: account
|
||||
client_secret: Lh3NkRikMZpO12rwSBwVimde9v89B5Rw
|
||||
scope: openid
|
||||
state:
|
||||
pkce: true
|
||||
tokenId: keycloak
|
||||
tokenPlacement: header
|
||||
tokenPrefix: Bearer
|
||||
tokenQueryKey: access_token
|
||||
reuseToken:
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
vars {
|
||||
host: http://localhost:8080
|
||||
bearer_auth_token: your_secret_token
|
||||
basic_auth_password: della
|
||||
client_id: client_id_1
|
||||
client_secret: client_secret_1
|
||||
password_credentials_access_token_url: http://localhost:8081/api/auth/oauth2/password_credentials/token
|
||||
password_credentials_username: foo
|
||||
password_credentials_password: bar
|
||||
password_credentials_scope:
|
||||
authorization_code_authorize_url: http://localhost:8081/api/auth/oauth2/authorization_code/authorize
|
||||
authorization_code_callback_url: http://localhost:8081/api/auth/oauth2/authorization_code/callback
|
||||
authorization_code_access_token_url: http://localhost:8081/api/auth/oauth2/authorization_code/token
|
||||
authorization_code_access_token: null
|
||||
client_credentials_access_token_url: http://localhost:8081/api/auth/oauth2/client_credentials/token
|
||||
client_credentials_client_id: client_id_1
|
||||
client_credentials_client_secret: client_secret_1
|
||||
client_credentials_scope: admin
|
||||
client_credentials_access_token: 870132a2ed28a3c94d34f868e6514720
|
||||
key-host: http://localhost:8080
|
||||
key-host-1: http://localhost:8082
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: user_info_coll-auth
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{key-host}}/realms/bruno/protocol/openid-connect/userinfo
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
meta {
|
||||
name: user_info_custom
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{key-host}}/realms/bruno/protocol/openid-connect/userinfo
|
||||
body: none
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{$oauth2.keycloak.access_token}}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
meta {
|
||||
name: user_info_request-auth
|
||||
type: http
|
||||
seq: 3
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{key-host}}/realms/bruno/protocol/openid-connect/userinfo
|
||||
body: none
|
||||
auth: oauth2
|
||||
}
|
||||
|
||||
auth:oauth2 {
|
||||
grant_type: client_credentials
|
||||
access_token_url: {{key-host}}/realms/bruno/protocol/openid-connect/token
|
||||
client_id: account
|
||||
client_secret: Lh3NkRikMZpO12rwSBwVimde9v89B5Rw
|
||||
scope: openid
|
||||
credentials_placement: body
|
||||
credentials_id: credentials
|
||||
token_placement: header
|
||||
token_prefix: Bearer
|
||||
reuse_token:
|
||||
}
|
||||
Reference in New Issue
Block a user