Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,14 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
<MenuDropdown
items={[
{ id: 'header', label: 'Header', onClick: () => handleChange('tokenPlacement', 'header') },
{ id: 'url', label: 'URL', onClick: () => handleChange('tokenPlacement', 'url') }
{ id: 'url', label: 'URL', onClick: () => handleChange('tokenPlacement', 'url') },
{ id: 'none', label: 'None', onClick: () => handleChange('tokenPlacement', 'none') }
]}
selectedItemId={tokenPlacement}
placement="bottom-end"
>
<div className="flex items-center justify-end token-placement-label select-none">
{tokenPlacement == 'url' ? 'URL' : 'Headers'}
{tokenPlacement == 'url' ? 'URL' : tokenPlacement == 'none' ? 'None' : 'Headers'}
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
</div>
</MenuDropdown>
Expand All @@ -310,22 +311,24 @@ const OAuth2AuthorizationCode = ({ save, item = {}, request, handleRun, updateAu
</div>
</div>
)
: (
<div className="flex items-center gap-4 w-full" key="input-token-query-param-key">
<label className="block min-w-[140px]">Query Param Key</label>
<div className="single-line-editor-wrapper flex-1">
<SingleLineEditor
value={oAuth['tokenQueryKey'] || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleChange('tokenQueryKey', val)}
onRun={handleRun}
collection={collection}
isCompact
/>
: tokenPlacement === 'url'
? (
<div className="flex items-center gap-4 w-full" key="input-token-query-param-key">
<label className="block min-w-[140px]">Query Param Key</label>
<div className="single-line-editor-wrapper flex-1">
<SingleLineEditor
value={oAuth['tokenQueryKey'] || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleChange('tokenQueryKey', val)}
onRun={handleRun}
collection={collection}
isCompact
/>
</div>
</div>
</div>
)
)
: null
}
<div className="flex items-center gap-2.5 mt-4 mb-2">
<div className="flex items-center px-2.5 py-1.5 oauth2-icon-container rounded-md">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,14 @@ const OAuth2ClientCredentials = ({ save, item = {}, request, handleRun, updateAu
<MenuDropdown
items={[
{ id: 'header', label: 'Header', onClick: () => handleChange('tokenPlacement', 'header') },
{ id: 'url', label: 'URL', onClick: () => handleChange('tokenPlacement', 'url') }
{ id: 'url', label: 'URL', onClick: () => handleChange('tokenPlacement', 'url') },
{ id: 'none', label: 'None', onClick: () => handleChange('tokenPlacement', 'none') }
]}
selectedItemId={tokenPlacement}
placement="bottom-end"
>
<div className="flex items-center justify-end token-placement-label select-none">
{tokenPlacement == 'url' ? 'URL' : 'Headers'}
{tokenPlacement == 'url' ? 'URL' : tokenPlacement == 'none' ? 'None' : 'Headers'}
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
</div>
</MenuDropdown>
Expand All @@ -200,22 +201,24 @@ const OAuth2ClientCredentials = ({ save, item = {}, request, handleRun, updateAu
</div>
</div>
)
: (
<div className="flex items-center gap-4 w-full" key="input-token-query-param-key">
<label className="block min-w-[140px]">Query Param Key</label>
<div className="single-line-editor-wrapper flex-1">
<SingleLineEditor
value={oAuth['tokenQueryKey'] || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleChange('tokenQueryKey', val)}
onRun={handleRun}
collection={collection}
isCompact
/>
: tokenPlacement === 'url'
? (
<div className="flex items-center gap-4 w-full" key="input-token-query-param-key">
<label className="block min-w-[140px]">Query Param Key</label>
<div className="single-line-editor-wrapper flex-1">
<SingleLineEditor
value={oAuth['tokenQueryKey'] || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleChange('tokenQueryKey', val)}
onRun={handleRun}
collection={collection}
isCompact
/>
</div>
</div>
</div>
)
)
: null
}
<div className="flex items-center gap-2.5 mt-4 mb-2">
<div className="flex items-center px-2.5 py-1.5 oauth2-icon-container rounded-md">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,14 @@ const OAuth2Implicit = ({ save, item = {}, request, handleRun, updateAuth, colle
<MenuDropdown
items={[
{ id: 'header', label: 'Headers', onClick: () => handleChange('tokenPlacement', 'header') },
{ id: 'url', label: 'URL', onClick: () => handleChange('tokenPlacement', 'url') }
{ id: 'url', label: 'URL', onClick: () => handleChange('tokenPlacement', 'url') },
{ id: 'none', label: 'None', onClick: () => handleChange('tokenPlacement', 'none') }
]}
selectedItemId={tokenPlacement}
placement="bottom-end"
>
<div className="flex items-center justify-end token-placement-label select-none">
{tokenPlacement == 'url' ? 'URL' : 'Headers'}
{tokenPlacement == 'url' ? 'URL' : tokenPlacement == 'none' ? 'None' : 'Headers'}
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
</div>
</MenuDropdown>
Expand All @@ -244,7 +245,7 @@ const OAuth2Implicit = ({ save, item = {}, request, handleRun, updateAuth, colle
/>
</div>
</div>
) : (
) : tokenPlacement == 'url' ? (
<div className="flex items-center gap-4 w-full" key="input-token-query-key">
<label className="block min-w-[140px]">URL Query Key</label>
<div className="oauth2-input-wrapper flex-1">
Expand All @@ -260,7 +261,7 @@ const OAuth2Implicit = ({ save, item = {}, request, handleRun, updateAuth, colle
/>
</div>
</div>
)}
) : null}

<div className="flex items-center gap-2.5 mt-2">
<div className="flex items-center px-2.5 py-1.5 oauth2-icon-container rounded-md">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,14 @@ const OAuth2PasswordCredentials = ({ save, item = {}, request, handleRun, update
<MenuDropdown
items={[
{ id: 'header', label: 'Header', onClick: () => handleChange('tokenPlacement', 'header') },
{ id: 'url', label: 'URL', onClick: () => handleChange('tokenPlacement', 'url') }
{ id: 'url', label: 'URL', onClick: () => handleChange('tokenPlacement', 'url') },
{ id: 'none', label: 'None', onClick: () => handleChange('tokenPlacement', 'none') }
]}
selectedItemId={tokenPlacement}
placement="bottom-end"
>
<div className="flex items-center justify-end token-placement-label select-none">
{tokenPlacement == 'url' ? 'URL' : 'Headers'}
{tokenPlacement == 'url' ? 'URL' : tokenPlacement == 'none' ? 'None' : 'Headers'}
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
</div>
</MenuDropdown>
Expand All @@ -204,22 +205,24 @@ const OAuth2PasswordCredentials = ({ save, item = {}, request, handleRun, update
</div>
</div>
)
: (
<div className="flex items-center gap-4 w-full" key="input-token-query-param-key">
<label className="block min-w-[140px]">Query Param Key</label>
<div className="single-line-editor-wrapper flex-1">
<SingleLineEditor
value={oAuth['tokenQueryKey'] || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleChange('tokenQueryKey', val)}
onRun={handleRun}
collection={collection}
isCompact
/>
: tokenPlacement === 'url'
? (
<div className="flex items-center gap-4 w-full" key="input-token-query-param-key">
<label className="block min-w-[140px]">Query Param Key</label>
<div className="single-line-editor-wrapper flex-1">
<SingleLineEditor
value={oAuth['tokenQueryKey'] || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleChange('tokenQueryKey', val)}
onRun={handleRun}
collection={collection}
isCompact
/>
</div>
</div>
</div>
)
)
: null
}
<div className="flex items-center gap-2.5 mt-4 mb-2">
<div className="flex items-center px-2.5 py-1.5 oauth2-icon-container rounded-md">
Expand Down
8 changes: 4 additions & 4 deletions packages/bruno-electron/src/ipc/network/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ const configureRequest = async (
const tokenValue = tokenSource === 'id_token' ? credentials?.id_token : credentials?.access_token;
if (tokenPlacement == 'header' && tokenValue) {
request.headers['Authorization'] = `${tokenHeaderPrefix} ${tokenValue}`.trim();
} else if (tokenValue) {
} else if (tokenPlacement == 'url' && tokenValue) {
try {
const url = new URL(request.url);
url.searchParams.set(tokenQueryKey, tokenValue);
Expand All @@ -252,7 +252,7 @@ const configureRequest = async (
const tokenValue = tokenSource === 'id_token' ? credentials?.id_token : credentials?.access_token;
if (tokenPlacement == 'header' && tokenValue) {
request.headers['Authorization'] = `${tokenHeaderPrefix} ${tokenValue}`.trim();
} else if (tokenValue) {
} else if (tokenPlacement == 'url' && tokenValue) {
try {
const url = new URL(request.url);
url.searchParams.set(tokenQueryKey, tokenValue);
Expand All @@ -269,7 +269,7 @@ const configureRequest = async (
const tokenValue = tokenSource === 'id_token' ? credentials?.id_token : credentials?.access_token;
if (tokenPlacement == 'header' && tokenValue) {
request.headers['Authorization'] = `${tokenHeaderPrefix} ${tokenValue}`.trim();
} else if (tokenValue) {
} else if (tokenPlacement == 'url' && tokenValue) {
try {
const url = new URL(request.url);
url.searchParams.set(tokenQueryKey, tokenValue);
Expand All @@ -286,7 +286,7 @@ const configureRequest = async (
const tokenValue = tokenSource === 'id_token' ? credentials?.id_token : credentials?.access_token;
if (tokenPlacement == 'header' && tokenValue) {
request.headers['Authorization'] = `${tokenHeaderPrefix} ${tokenValue}`.trim();
} else if (tokenValue) {
} else if (tokenPlacement == 'url' && tokenValue) {
try {
const url = new URL(request.url);
url.searchParams.set(tokenQueryKey, tokenValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const processHeaders = (headers) => {
const placeOAuth2Token = (grpcRequest, credentials, tokenPlacement, tokenHeaderPrefix, tokenQueryKey) => {
if (tokenPlacement === 'header') {
grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
} else {
} else if (tokenPlacement === 'url') {
try {
const url = new URL(grpcRequest.url);
url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
};
if (tokenPlacement == 'header') {
wsRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
} else {
} else if (tokenPlacement == 'url') {
try {
const url = new URL(request.url);
url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
Expand Down Expand Up @@ -207,7 +207,7 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
};
if (tokenPlacement == 'header') {
wsRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
} else {
} else if (tokenPlacement == 'url') {
try {
const url = new URL(request.url);
url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
Expand Down Expand Up @@ -238,7 +238,7 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
};
if (tokenPlacement == 'header') {
wsRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
} else {
} else if (tokenPlacement == 'url') {
try {
const url = new URL(request.url);
url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
Expand Down
46 changes: 46 additions & 0 deletions packages/bruno-electron/tests/network/index.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
jest.mock('../../src/utils/oauth2', () => ({
getOAuth2TokenUsingAuthorizationCode: jest.fn(),
getOAuth2TokenUsingClientCredentials: jest.fn(),
getOAuth2TokenUsingPasswordCredentials: jest.fn(),
getOAuth2TokenUsingImplicitGrant: jest.fn(),
updateCollectionOauth2Credentials: jest.fn(),
clearOauth2CredentialsByCredentialsId: jest.fn()
}));

jest.mock('../../src/ipc/network/cert-utils', () => ({
getCertsAndProxyConfig: jest.fn().mockResolvedValue({}),
buildCertsAndProxyConfig: jest.fn()
}));

const { configureRequest } = require('../../src/ipc/network/index');
const { getOAuth2TokenUsingClientCredentials } = require('../../src/utils/oauth2');

describe('index: configureRequest', () => {
it('Should add \'http://\' to the URL if no protocol is specified', async () => {
Expand All @@ -12,4 +27,35 @@ describe('index: configureRequest', () => {
await configureRequest(null, {}, request, null, null, null, null);
expect(request.url).toEqual('ftp://test-domain');
});

it('Should not add the OAuth2 token to headers or URL if tokenPlacement is none', async () => {
getOAuth2TokenUsingClientCredentials.mockResolvedValue({
credentials: { access_token: 'test-token' },
url: 'https://auth.example.com/token',
credentialsId: 'credentials',
debugInfo: {}
});

const request = {
method: 'GET',
url: 'https://api.example.com/users?existing=1',
headers: {},
body: {},
oauth2: {
grantType: 'client_credentials',
accessTokenUrl: 'https://auth.example.com/token',
clientId: 'client-id',
clientSecret: 'client-secret',
tokenPlacement: 'none',
tokenHeaderPrefix: 'Bearer',
tokenQueryKey: 'access_token'
}
};

await configureRequest('collection-uid', { promptVariables: {} }, request, {}, {}, {}, null, {});

expect(request.headers.Authorization).toBeUndefined();
expect(request.url).toEqual('https://api.example.com/users?existing=1');
expect(request.oauth2Credentials.credentials.access_token).toBe('test-token');
});
});
Loading