Skip to content

Commit

Permalink
OAuth2: Implement OAuth 2.0 Implicit Grant
Browse files Browse the repository at this point in the history
  • Loading branch information
Mateusz Pietryga authored and pietrygamat committed May 7, 2024
1 parent 411289d commit 406ca82
Show file tree
Hide file tree
Showing 21 changed files with 486 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ const GrantTypeSelector = ({ collection }) => {
>
Client Credentials
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onGrantTypeChange('implicit');
}}
>
Implicit
</div>
</Dropdown>
</div>
</StyledWrapper>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import styled from 'styled-components';

const Wrapper = styled.div`
label {
font-size: 0.8125rem;
}
.single-line-editor-wrapper {
max-width: 400px;
padding: 0.15rem 0.4rem;
border-radius: 3px;
border: solid 1px ${(props) => props.theme.input.border};
background-color: ${(props) => props.theme.input.bg};
}
`;

export default Wrapper;
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import get from 'lodash/get';
import { useTheme } from 'providers/Theme';
import { useDispatch } from 'react-redux';
import SingleLineEditor from 'components/SingleLineEditor';
import { saveCollectionRoot, sendCollectionOauth2Request } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections/index';
import { clearOauth2Cache } from 'utils/network';
import toast from 'react-hot-toast';

const OAuth2Implicit = ({ item, collection }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();

const oAuth = get(collection, 'root.request.auth.oauth2', {});

const handleRun = async () => {
dispatch(sendCollectionOauth2Request(collection.uid));
};

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

const { callbackUrl, authorizationUrl, clientId, scope } = oAuth;

const handleChange = (key, value) => {
dispatch(
updateCollectionAuth({
mode: 'oauth2',
collectionUid: collection.uid,
content: {
grantType: 'implicit',
callbackUrl,
authorizationUrl,
clientId,
scope,
[key]: value
}
})
);
};

const handleClearCache = (e) => {
clearOauth2Cache(collection?.uid)
.then(() => {
toast.success('cleared cache successfully');
})
.catch((err) => {
toast.error(err.message);
});
};

return (
<StyledWrapper className="mt-2 flex w-full gap-4 flex-col">
{inputsConfig.map((input) => {
const { key, label } = input;
return (
<div className="flex flex-col w-full gap-1" key={`input-${key}`}>
<label className="block font-medium">{label}</label>
<div className="single-line-editor-wrapper">
<SingleLineEditor
value={oAuth[key] || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleChange(key, val)}
onRun={handleRun}
collection={collection}
/>
</div>
</div>
);
})}
<div className="flex flex-row gap-4">
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
<button onClick={handleClearCache} className="submit btn btn-sm btn-secondary w-fit">
Clear Cache
</button>
</div>
</StyledWrapper>
);
};

export default OAuth2Implicit;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const inputsConfig = [
{
key: 'callbackUrl',
label: 'Callback URL'
},
{
key: 'authorizationUrl',
label: 'Authorization URL'
},
{
key: 'clientId',
label: 'Client ID'
},
{
key: 'scope',
label: 'Scope'
}
];

export { inputsConfig };
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import GrantTypeSelector from './GrantTypeSelector/index';
import OAuth2PasswordCredentials from './PasswordCredentials/index';
import OAuth2AuthorizationCode from './AuthorizationCode/index';
import OAuth2ClientCredentials from './ClientCredentials/index';
import OAuth2Implicit from './Implicit/index';

const grantTypeComponentMap = (grantType, collection) => {
switch (grantType) {
Expand All @@ -17,6 +18,9 @@ const grantTypeComponentMap = (grantType, collection) => {
case 'client_credentials':
return <OAuth2ClientCredentials collection={collection} />;
break;
case 'implicit':
return <OAuth2Implicit collection={collection} />;
break;
default:
return <div>TBD</div>;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ const GrantTypeSelector = ({ item, collection }) => {
>
Client Credentials
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onGrantTypeChange('implicit');
}}
>
Implicit
</div>
</Dropdown>
</div>
</StyledWrapper>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import styled from 'styled-components';

const Wrapper = styled.div`
label {
font-size: 0.8125rem;
}
.single-line-editor-wrapper {
max-width: 400px;
padding: 0.15rem 0.4rem;
border-radius: 3px;
border: solid 1px ${(props) => props.theme.input.border};
background-color: ${(props) => props.theme.input.bg};
}
`;

export default Wrapper;
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React from 'react';
import get from 'lodash/get';
import { useTheme } from 'providers/Theme';
import { useDispatch } from 'react-redux';
import SingleLineEditor from 'components/SingleLineEditor';
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 { clearOauth2Cache } from 'utils/network/index';
import toast from 'react-hot-toast';

const OAuth2Implicit = ({ item, collection }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();

const oAuth = item.draft ? get(item, 'draft.request.auth.oauth2', {}) : get(item, 'request.auth.oauth2', {});

const handleRun = async () => {
dispatch(sendRequest(item, collection.uid));
};

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

const { callbackUrl, authorizationUrl, clientId, scope } = oAuth;

const handleChange = (key, value) => {
dispatch(
updateAuth({
mode: 'oauth2',
collectionUid: collection.uid,
itemUid: item.uid,
content: {
grantType: 'implicit',
callbackUrl,
authorizationUrl,
clientId,
scope,
[key]: value
}
})
);
};

const handleClearCache = (e) => {
clearOauth2Cache(collection?.uid)
.then(() => {
toast.success('cleared cache successfully');
})
.catch((err) => {
toast.error(err.message);
});
};

return (
<StyledWrapper className="mt-2 flex w-full gap-4 flex-col">
{inputsConfig.map((input) => {
const { key, label } = input;
return (
<div className="flex flex-col w-full gap-1" key={`input-${key}`}>
<label className="block font-medium">{label}</label>
<div className="single-line-editor-wrapper">
<SingleLineEditor
value={oAuth[key] || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleChange(key, val)}
onRun={handleRun}
collection={collection}
/>
</div>
</div>
);
})}
<div className="flex flex-row gap-4">
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
<button onClick={handleClearCache} className="submit btn btn-sm btn-secondary w-fit">
Clear Cache
</button>
</div>
</StyledWrapper>
);
};

export default OAuth2Implicit;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const inputsConfig = [
{
key: 'callbackUrl',
label: 'Callback URL'
},
{
key: 'authorizationUrl',
label: 'Authorization URL'
},
{
key: 'clientId',
label: 'Client ID'
},
{
key: 'scope',
label: 'Scope'
}
];

export { inputsConfig };
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import GrantTypeSelector from './GrantTypeSelector/index';
import OAuth2PasswordCredentials from './PasswordCredentials/index';
import OAuth2AuthorizationCode from './AuthorizationCode/index';
import OAuth2ClientCredentials from './ClientCredentials/index';
import OAuth2Implicit from './Implicit/index';

const grantTypeComponentMap = (grantType, item, collection) => {
switch (grantType) {
Expand All @@ -17,6 +18,9 @@ const grantTypeComponentMap = (grantType, item, collection) => {
case 'client_credentials':
return <OAuth2ClientCredentials item={item} collection={collection} />;
break;
case 'implicit':
return <OAuth2Implicit item={item} collection={collection} />;
break;
default:
return <div>TBD</div>;
break;
Expand Down
4 changes: 4 additions & 0 deletions packages/bruno-app/src/utils/collections/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,10 @@ export const humanizeGrantType = (mode) => {
label = 'Client Credentials';
break;
}
case 'implicit': {
label = 'Implicit';
break;
}
}

return label;
Expand Down

0 comments on commit 406ca82

Please sign in to comment.