Skip to content

Commit

Permalink
feat: OAuth 2.0 Client Credentials as Basic Auth - user interface
Browse files Browse the repository at this point in the history
  • Loading branch information
pietrygamat committed Apr 25, 2024
1 parent af1efd9 commit 1178efa
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { inputsConfig } from './inputsConfig';
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections/index';
import { clearOauth2Cache } from 'utils/network/index';
import toast from 'react-hot-toast';
import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector';

const OAuth2AuthorizationCode = ({ collection }) => {
const dispatch = useDispatch();
Expand All @@ -22,7 +23,8 @@ const OAuth2AuthorizationCode = ({ collection }) => {

const handleSave = () => dispatch(saveCollectionRoot(collection.uid));

const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, pkce } = oAuth;
const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, clientSecretMethod, scope, pkce } =
oAuth;

const handleChange = (key, value) => {
dispatch(
Expand All @@ -36,6 +38,7 @@ const OAuth2AuthorizationCode = ({ collection }) => {
accessTokenUrl,
clientId,
clientSecret,
clientSecretMethod,
scope,
pkce,
[key]: value
Expand All @@ -56,6 +59,7 @@ const OAuth2AuthorizationCode = ({ collection }) => {
accessTokenUrl,
clientId,
clientSecret,
clientSecretMethod,
scope,
pkce: !Boolean(oAuth?.['pkce'])
}
Expand Down Expand Up @@ -102,6 +106,7 @@ const OAuth2AuthorizationCode = ({ collection }) => {
onChange={handlePKCEToggle}
/>
</div>
<ClientCredentialsMethodSelector collection={collection} oAuth={oAuth} />
<div className="flex flex-row gap-4">
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { saveCollectionRoot, sendCollectionOauth2Request } from 'providers/Redux
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections/index';
import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector';

const OAuth2ClientCredentials = ({ collection }) => {
const dispatch = useDispatch();
Expand All @@ -20,7 +21,7 @@ const OAuth2ClientCredentials = ({ collection }) => {

const handleSave = () => dispatch(saveCollectionRoot(collection.uid));

const { accessTokenUrl, clientId, clientSecret, scope } = oAuth;
const { accessTokenUrl, clientId, clientSecret, clientSecretMethod, scope } = oAuth;

const handleChange = (key, value) => {
dispatch(
Expand All @@ -32,6 +33,7 @@ const OAuth2ClientCredentials = ({ collection }) => {
accessTokenUrl,
clientId,
clientSecret,
clientSecretMethod,
scope,
[key]: value
}
Expand Down Expand Up @@ -59,6 +61,7 @@ const OAuth2ClientCredentials = ({ collection }) => {
</div>
);
})}
<ClientCredentialsMethodSelector collection={collection} oAuth={oAuth} />
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { saveCollectionRoot, sendCollectionOauth2Request } from 'providers/Redux
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections/index';
import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector';

const OAuth2AuthorizationCode = ({ item, collection }) => {
const dispatch = useDispatch();
Expand All @@ -20,7 +21,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {

const handleSave = () => dispatch(saveCollectionRoot(collection.uid));

const { accessTokenUrl, username, password, clientId, clientSecret, scope } = oAuth;
const { accessTokenUrl, username, password, clientId, clientSecret, clientSecretMethod, scope } = oAuth;

const handleChange = (key, value) => {
dispatch(
Expand All @@ -34,6 +35,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
password,
clientId,
clientSecret,
clientSecretMethod,
scope,
[key]: value
}
Expand Down Expand Up @@ -61,6 +63,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
</div>
);
})}
<ClientCredentialsMethodSelector collection={collection} oAuth={oAuth} />
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import { clearOauth2Cache } from 'utils/network/index';
import toast from 'react-hot-toast';
import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector';

const OAuth2AuthorizationCode = ({ item, collection }) => {
const dispatch = useDispatch();
Expand All @@ -22,7 +23,8 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {

const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));

const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, pkce } = oAuth;
const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, clientSecretMethod, scope, pkce } =
oAuth;

const handleChange = (key, value) => {
dispatch(
Expand All @@ -37,6 +39,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
accessTokenUrl,
clientId,
clientSecret,
clientSecretMethod,
scope,
pkce,
[key]: value
Expand All @@ -58,6 +61,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
accessTokenUrl,
clientId,
clientSecret,
clientSecretMethod,
scope,
pkce: !Boolean(oAuth?.['pkce'])
}
Expand Down Expand Up @@ -104,6 +108,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
onChange={handlePKCEToggle}
/>
</div>
<ClientCredentialsMethodSelector item={item} collection={collection} oAuth={oAuth} />
<div className="flex flex-row gap-4">
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { updateAuth } from 'providers/ReduxStore/slices/collections';
import { saveRequest, sendRequest } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector';

const OAuth2ClientCredentials = ({ item, collection }) => {
const dispatch = useDispatch();
Expand All @@ -20,7 +21,7 @@ const OAuth2ClientCredentials = ({ item, collection }) => {

const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));

const { accessTokenUrl, clientId, clientSecret, scope } = oAuth;
const { accessTokenUrl, clientId, clientSecret, clientSecretMethod, scope } = oAuth;

const handleChange = (key, value) => {
dispatch(
Expand All @@ -33,6 +34,7 @@ const OAuth2ClientCredentials = ({ item, collection }) => {
accessTokenUrl,
clientId,
clientSecret,
clientSecretMethod,
scope,
[key]: value
}
Expand Down Expand Up @@ -60,6 +62,7 @@ const OAuth2ClientCredentials = ({ item, collection }) => {
</div>
);
})}
<ClientCredentialsMethodSelector item={item} collection={collection} oAuth={oAuth} />
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import styled from 'styled-components';

const Wrapper = styled.div`
font-size: 0.8125rem;
.client-credentials-secret-mode-selector {
padding: 0.5rem 0px;
border-radius: 3px;
border: solid 1px ${(props) => props.theme.input.border};
background-color: ${(props) => props.theme.input.bg};
.dropdown {
width: fit-content;
div[data-tippy-root] {
width: fit-content;
}
.tippy-box {
width: fit-content;
max-width: none !important;
.tippy-content: {
width: fit-content;
max-width: none !important;
}
}
}
.client-credentials-secret-label {
width: fit-content;
color: ${(props) => props.theme.colors.text.yellow};
justify-content: space-between;
padding: 0 0.5rem;
}
.dropdown-item {
padding: 0.2rem 0.6rem !important;
}
.label-item {
padding: 0.2rem 0.6rem !important;
}
}
.caret {
color: rgb(140, 140, 140);
fill: rgb(140 140 140);
}
label {
font-size: 0.8125rem;
}
`;

export default Wrapper;
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { forwardRef, useEffect, useRef, useState } from 'react';
import Dropdown from 'components/Dropdown';
import StyledWrapper from './StyledWrapper';
import { IconCaretDown } from '@tabler/icons';
import { updateAuth, updateCollectionAuth } from 'providers/ReduxStore/slices/collections';
import { useDispatch } from 'react-redux';
import { humanizeOAuth2ClientSecretMethod } from 'utils/collections';

const ClientCredentialsMethodSelector = ({ item, collection, oAuth }) => {
const clientSecretMethods = ['client_credentials_basic', 'client_credentials_post'];

const dispatch = useDispatch();
const dropDownRef = useRef();
const onDropdownCreate = (ref) => (dropDownRef.current = ref);

const Icon = forwardRef((props, ref) => {
return (
<div ref={ref} className="flex items-center justify-end client-credentials-secret-label select-none">
{humanizeOAuth2ClientSecretMethod(oAuth?.clientSecretMethod)}{' '}
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
</div>
);
});

const onClientSecretMethodChange = (clientSecretMethod) => {
if (item) {
// Update request level authentication
dispatch(
updateAuth({
mode: 'oauth2',
collectionUid: collection.uid,
itemUid: item.uid,
content: {
...oAuth,
clientSecretMethod: clientSecretMethod
}
})
);
} else {
// Update collection level authentication
dispatch(
updateCollectionAuth({
mode: 'oauth2',
collectionUid: collection.uid,
content: {
...oAuth,
clientSecretMethod: clientSecretMethod
}
})
);
}
};

useEffect(() => {
!oAuth?.clientSecretMethod && onClientSecretMethodChange(clientSecretMethods[0]);
}, [oAuth.clientSecretMethod]);

return (
<StyledWrapper>
<label className="block font-medium mb-2">Send Client Credentials</label>
<div className="inline-flex items-center cursor-pointer client-credentials-secret-mode-selector w-fit">
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
{clientSecretMethods.map((item, index) => (
<div
key={item}
className="dropdown-item"
onClick={() => {
dropDownRef.current.hide();
onClientSecretMethodChange(item);
}}
>
{' '}
{humanizeOAuth2ClientSecretMethod(item)}
{index === 0 ? ` (Default)` : ``}
</div>
))}
</Dropdown>
</div>
</StyledWrapper>
);
};
export default ClientCredentialsMethodSelector;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { updateAuth } from 'providers/ReduxStore/slices/collections';
import { saveRequest, sendRequest } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import ClientCredentialsMethodSelector from 'components/RequestPane/Auth/OAuth2/ClientCredentialsMethodSelector';

const OAuth2AuthorizationCode = ({ item, collection }) => {
const dispatch = useDispatch();
Expand All @@ -20,7 +21,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {

const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));

const { accessTokenUrl, username, password, clientId, clientSecret, scope } = oAuth;
const { accessTokenUrl, username, password, clientId, clientSecret, clientSecretMethod, scope } = oAuth;

const handleChange = (key, value) => {
dispatch(
Expand All @@ -35,6 +36,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
password,
clientId,
clientSecret,
clientSecretMethod,
scope,
[key]: value
}
Expand Down Expand Up @@ -62,6 +64,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
</div>
);
})}
<ClientCredentialsMethodSelector item={item} collection={collection} oAuth={oAuth} />
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
Expand Down
16 changes: 16 additions & 0 deletions packages/bruno-app/src/utils/collections/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,22 @@ export const humanizeGrantType = (mode) => {
return label;
};

export const humanizeOAuth2ClientSecretMethod = (mode) => {
let label = 'N/A';
switch (mode) {
case 'client_credentials_basic': {
label = 'As Basic Auth Header';
break;
}
case 'client_credentials_post': {
label = 'In Request Body';
break;
}
}

return label;
};

export const refreshUidsInItem = (item) => {
item.uid = uuid();

Expand Down

0 comments on commit 1178efa

Please sign in to comment.