diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/GrantTypeSelector/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/GrantTypeSelector/index.js
index 5d92893820..4cd8519b00 100644
--- a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/GrantTypeSelector/index.js
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/GrantTypeSelector/index.js
@@ -90,6 +90,15 @@ const GrantTypeSelector = ({ collection }) => {
>
Client Credentials
+
{
+ dropdownTippyRef.current.hide();
+ onGrantTypeChange('implicit');
+ }}
+ >
+ Implicit
+
diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/Implicit/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/Implicit/StyledWrapper.js
new file mode 100644
index 0000000000..856f35b9b9
--- /dev/null
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/Implicit/StyledWrapper.js
@@ -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;
diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/Implicit/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/Implicit/index.js
new file mode 100644
index 0000000000..1dee00f16a
--- /dev/null
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/Implicit/index.js
@@ -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 (
+
+ {inputsConfig.map((input) => {
+ const { key, label } = input;
+ return (
+
+
+
+ handleChange(key, val)}
+ onRun={handleRun}
+ collection={collection}
+ />
+
+
+ );
+ })}
+
+
+
+
+
+ );
+};
+
+export default OAuth2Implicit;
diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/Implicit/inputsConfig.js b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/Implicit/inputsConfig.js
new file mode 100644
index 0000000000..87e1fd42d5
--- /dev/null
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/Implicit/inputsConfig.js
@@ -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 };
diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/index.js
index 1aa674ab95..2075aa8ca9 100644
--- a/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/index.js
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/index.js
@@ -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) {
@@ -17,6 +18,9 @@ const grantTypeComponentMap = (grantType, collection) => {
case 'client_credentials':
return ;
break;
+ case 'implicit':
+ return ;
+ break;
default:
return TBD
;
break;
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/GrantTypeSelector/index.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/GrantTypeSelector/index.js
index 3fa12b9474..52425fc2ce 100644
--- a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/GrantTypeSelector/index.js
+++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/GrantTypeSelector/index.js
@@ -84,6 +84,15 @@ const GrantTypeSelector = ({ item, collection }) => {
>
Client Credentials
+ {
+ dropdownTippyRef.current.hide();
+ onGrantTypeChange('implicit');
+ }}
+ >
+ Implicit
+
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/Implicit/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/Implicit/StyledWrapper.js
new file mode 100644
index 0000000000..856f35b9b9
--- /dev/null
+++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/Implicit/StyledWrapper.js
@@ -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;
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/Implicit/index.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/Implicit/index.js
new file mode 100644
index 0000000000..690b821977
--- /dev/null
+++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/Implicit/index.js
@@ -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 (
+
+ {inputsConfig.map((input) => {
+ const { key, label } = input;
+ return (
+
+
+
+ handleChange(key, val)}
+ onRun={handleRun}
+ collection={collection}
+ />
+
+
+ );
+ })}
+
+
+
+
+
+ );
+};
+
+export default OAuth2Implicit;
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/Implicit/inputsConfig.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/Implicit/inputsConfig.js
new file mode 100644
index 0000000000..87e1fd42d5
--- /dev/null
+++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/Implicit/inputsConfig.js
@@ -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 };
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/index.js b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/index.js
index 3965c8d3e4..05a3fe79c1 100644
--- a/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/index.js
+++ b/packages/bruno-app/src/components/RequestPane/Auth/OAuth2/index.js
@@ -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) {
@@ -17,6 +18,9 @@ const grantTypeComponentMap = (grantType, item, collection) => {
case 'client_credentials':
return ;
break;
+ case 'implicit':
+ return ;
+ break;
default:
return TBD
;
break;
diff --git a/packages/bruno-app/src/utils/collections/index.js b/packages/bruno-app/src/utils/collections/index.js
index 26a1209916..d87bd5d81f 100644
--- a/packages/bruno-app/src/utils/collections/index.js
+++ b/packages/bruno-app/src/utils/collections/index.js
@@ -533,6 +533,10 @@ export const humanizeGrantType = (mode) => {
label = 'Client Credentials';
break;
}
+ case 'implicit': {
+ label = 'Implicit';
+ break;
+ }
}
return label;
diff --git a/packages/bruno-electron/src/ipc/network/authorize-user-in-window.js b/packages/bruno-electron/src/ipc/network/authorize-user-in-window.js
index 3ed05d45c6..b27110c6bd 100644
--- a/packages/bruno-electron/src/ipc/network/authorize-user-in-window.js
+++ b/packages/bruno-electron/src/ipc/network/authorize-user-in-window.js
@@ -1,33 +1,40 @@
const { BrowserWindow } = require('electron');
const { preferencesUtil } = require('../../store/preferences');
-const authorizeUserInWindow = ({ authorizeUrl, callbackUrl, session }) => {
- return new Promise(async (resolve, reject) => {
- let finalUrl = null;
+const openNewWindow = (session) => {
+ let allOpenWindows = BrowserWindow.getAllWindows();
- let allOpenWindows = BrowserWindow.getAllWindows();
+ // main window id is '1'
+ // get all other windows
+ let windowsExcludingMain = allOpenWindows.filter((w) => w.id != 1);
+ windowsExcludingMain.forEach((w) => {
+ w.close();
+ });
- // main window id is '1'
- // get all other windows
- let windowsExcludingMain = allOpenWindows.filter((w) => w.id != 1);
- windowsExcludingMain.forEach((w) => {
- w.close();
- });
+ const window = new BrowserWindow({
+ webPreferences: {
+ nodeIntegration: false,
+ partition: session
+ },
+ show: false
+ });
- const window = new BrowserWindow({
- webPreferences: {
- nodeIntegration: false,
- partition: session
- },
- show: false
- });
- window.on('ready-to-show', window.show.bind(window));
+ window.on('ready-to-show', window.show.bind(window));
- // We want browser window to comply with "SSL/TLS Certificate Verification" toggle in Preferences
- window.webContents.on('certificate-error', (event, url, error, certificate, callback) => {
- event.preventDefault();
- callback(!preferencesUtil.shouldVerifyTls());
- });
+ // We want browser window to comply with "SSL/TLS Certificate Verification" toggle in Preferences
+ window.webContents.on('certificate-error', (event, url, error, certificate, callback) => {
+ event.preventDefault();
+ callback(!preferencesUtil.shouldVerifyTls());
+ });
+
+ return window;
+};
+
+const authorizeUserInWindow = ({ authorizeUrl, callbackUrl, session }) => {
+ return new Promise(async (resolve, reject) => {
+ let finalUrl = null;
+
+ let window = openNewWindow(session);
function onWindowRedirect(url) {
// check if the url contains an authorization code
@@ -93,4 +100,68 @@ const authorizeUserInWindow = ({ authorizeUrl, callbackUrl, session }) => {
});
};
-module.exports = { authorizeUserInWindow };
+const authorizeUserInWindowImplicit = ({ authorizeUrl, session }) => {
+ return new Promise(async (resolve, reject) => {
+ let finalUrl = null;
+
+ let window = openNewWindow(session);
+
+ function onWindowRedirect(url) {
+ // check if the url contains an access token
+ if (new URLSearchParams(new URL(url).hash.slice(1)).has('access_token')) {
+ finalUrl = url;
+ window.close();
+ }
+ if (url.match(/(error=).*/) || url.match(/(error_description=).*/) || url.match(/(error_uri=).*/)) {
+ const _url = new URL(url);
+ const error = _url.searchParams.get('error');
+ const errorDescription = _url.searchParams.get('error_description');
+ const errorUri = _url.searchParams.get('error_uri');
+ let errorData = {
+ message: 'Authorization Failed!',
+ error,
+ errorDescription,
+ errorUri
+ };
+ reject(new Error(JSON.stringify(errorData)));
+ window.close();
+ }
+ }
+
+ window.on('close', () => {
+ if (finalUrl) {
+ try {
+ const uriFragmentWithToken = new URLSearchParams(new URL(finalUrl).hash.slice(1));
+ const accessToken = uriFragmentWithToken.get('access_token');
+ return resolve({ accessToken });
+ } catch (error) {
+ return reject(error);
+ }
+ } else {
+ return reject(new Error('Authorization window closed'));
+ }
+ });
+
+ // wait for the window to navigate to the callback url
+ const didNavigateListener = (_, url) => {
+ onWindowRedirect(url);
+ };
+ window.webContents.on('did-navigate', didNavigateListener);
+ const willRedirectListener = (_, authorizeUrl) => {
+ onWindowRedirect(authorizeUrl);
+ };
+ window.webContents.on('will-redirect', willRedirectListener);
+
+ try {
+ await window.loadURL(authorizeUrl);
+ } catch (error) {
+ reject(error);
+ window.close();
+ }
+ });
+};
+
+module.exports = {
+ authorizeUserInWindow,
+ authorizeUserInWindowImplicit
+};
diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js
index 73d8a59232..fd69220f20 100644
--- a/packages/bruno-electron/src/ipc/network/index.js
+++ b/packages/bruno-electron/src/ipc/network/index.js
@@ -34,7 +34,8 @@ const { getCookieStringForUrl, addCookieToJar, getDomainsWithCookies } = require
const {
resolveOAuth2AuthorizationCodeAccessToken,
transformClientCredentialsRequest,
- transformPasswordCredentialsRequest
+ transformPasswordCredentialsRequest,
+ getOAuth2ImplicitToken
} = require('./oauth2-helper');
const Oauth2Store = require('../../store/oauth2');
@@ -232,6 +233,11 @@ const configureRequest = async (
request.data = passwordData;
request.url = passwordAccessTokenUrl;
break;
+ case 'implicit':
+ interpolateVars(requestCopy, envVars, collectionVariables, processEnvVars);
+ const { accessToken } = await getOAuth2ImplicitToken(requestCopy, collectionUid);
+ request.headers['Authorization'] = `Bearer ${accessToken}`;
+ break;
}
}
diff --git a/packages/bruno-electron/src/ipc/network/interpolate-vars.js b/packages/bruno-electron/src/ipc/network/interpolate-vars.js
index 2139194a2a..c25af722c5 100644
--- a/packages/bruno-electron/src/ipc/network/interpolate-vars.js
+++ b/packages/bruno-electron/src/ipc/network/interpolate-vars.js
@@ -156,6 +156,12 @@ const interpolateVars = (request, envVars = {}, collectionVariables = {}, proces
scope
};
break;
+ case 'implicit':
+ request.oauth2.callbackUrl = _interpolate(request.oauth2.callbackUrl) || '';
+ request.oauth2.authorizationUrl = _interpolate(request.oauth2.authorizationUrl) || '';
+ request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
+ request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
+ break;
default:
break;
}
diff --git a/packages/bruno-electron/src/ipc/network/oauth2-helper.js b/packages/bruno-electron/src/ipc/network/oauth2-helper.js
index e254e8c746..4ab0ee1836 100644
--- a/packages/bruno-electron/src/ipc/network/oauth2-helper.js
+++ b/packages/bruno-electron/src/ipc/network/oauth2-helper.js
@@ -1,6 +1,6 @@
const { get, cloneDeep } = require('lodash');
const crypto = require('crypto');
-const { authorizeUserInWindow } = require('./authorize-user-in-window');
+const { authorizeUserInWindow, authorizeUserInWindowImplicit } = require('./authorize-user-in-window');
const Oauth2Store = require('../../store/oauth2');
const generateCodeVerifier = () => {
@@ -114,9 +114,38 @@ const transformPasswordCredentialsRequest = async (request) => {
};
};
+// IMPLICIT
+
+const getOAuth2ImplicitToken = async (request, collectionUid) => {
+ return new Promise(async (resolve, reject) => {
+ const { oauth2 } = request;
+ const { callbackUrl, authorizationUrl, clientId, scope } = oauth2;
+ let oauth2QueryParams =
+ (authorizationUrl.indexOf('?') > -1 ? '&' : '?') + `client_id=${clientId}&response_type=token`;
+ if (callbackUrl) {
+ oauth2QueryParams += `&redirect_uri=${callbackUrl}`;
+ }
+ if (scope) {
+ oauth2QueryParams += `&scope=${scope}`;
+ }
+ const authorizationUrlWithQueryParams = authorizationUrl + oauth2QueryParams;
+ try {
+ const oauth2Store = new Oauth2Store();
+ const { accessToken } = await authorizeUserInWindowImplicit({
+ authorizeUrl: authorizationUrlWithQueryParams,
+ session: oauth2Store.getSessionIdOfCollection(collectionUid)
+ });
+ resolve({ accessToken });
+ } catch (err) {
+ reject(err);
+ }
+ });
+};
+
module.exports = {
resolveOAuth2AuthorizationCodeAccessToken,
getOAuth2AuthorizationCode,
transformClientCredentialsRequest,
- transformPasswordCredentialsRequest
+ transformPasswordCredentialsRequest,
+ getOAuth2ImplicitToken
};
diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js
index 37196589ae..bc83cc3a6e 100644
--- a/packages/bruno-electron/src/ipc/network/prepare-request.js
+++ b/packages/bruno-electron/src/ipc/network/prepare-request.js
@@ -135,6 +135,15 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
scope: get(request, 'auth.oauth2.scope')
};
break;
+ case 'implicit':
+ axiosRequest.oauth2 = {
+ grantType: grantType,
+ callbackUrl: get(request, 'auth.oauth2.callbackUrl'),
+ authorizationUrl: get(request, 'auth.oauth2.authorizationUrl'),
+ clientId: get(request, 'auth.oauth2.clientId'),
+ scope: get(request, 'auth.oauth2.scope')
+ };
+ break;
}
break;
}
diff --git a/packages/bruno-lang/v2/src/bruToJson.js b/packages/bruno-lang/v2/src/bruToJson.js
index afb0a43e02..872e956f62 100644
--- a/packages/bruno-lang/v2/src/bruToJson.js
+++ b/packages/bruno-lang/v2/src/bruToJson.js
@@ -425,6 +425,14 @@ const sem = grammar.createSemantics().addAttribute('ast', {
clientSecret: clientSecretKey ? clientSecretKey.value : '',
scope: scopeKey ? scopeKey.value : ''
}
+ : grantTypeKey?.value && grantTypeKey?.value == 'implicit'
+ ? {
+ grantType: grantTypeKey ? grantTypeKey.value : '',
+ callbackUrl: callbackUrlKey ? callbackUrlKey.value : '',
+ authorizationUrl: authorizationUrlKey ? authorizationUrlKey.value : '',
+ clientId: clientIdKey ? clientIdKey.value : '',
+ scope: scopeKey ? scopeKey.value : ''
+ }
: {}
}
};
diff --git a/packages/bruno-lang/v2/src/collectionBruToJson.js b/packages/bruno-lang/v2/src/collectionBruToJson.js
index 355f2f9664..ae1a13ee3a 100644
--- a/packages/bruno-lang/v2/src/collectionBruToJson.js
+++ b/packages/bruno-lang/v2/src/collectionBruToJson.js
@@ -287,6 +287,14 @@ const sem = grammar.createSemantics().addAttribute('ast', {
clientSecret: clientSecretKey ? clientSecretKey.value : '',
scope: scopeKey ? scopeKey.value : ''
}
+ : grantTypeKey?.value && grantTypeKey?.value == 'implicit'
+ ? {
+ grantType: grantTypeKey ? grantTypeKey.value : '',
+ callbackUrl: callbackUrlKey ? callbackUrlKey.value : '',
+ authorizationUrl: authorizationUrlKey ? authorizationUrlKey.value : '',
+ clientId: clientIdKey ? clientIdKey.value : '',
+ scope: scopeKey ? scopeKey.value : ''
+ }
: {}
}
};
diff --git a/packages/bruno-lang/v2/src/jsonToBru.js b/packages/bruno-lang/v2/src/jsonToBru.js
index a59d7cd7c5..790dd3e9b9 100644
--- a/packages/bruno-lang/v2/src/jsonToBru.js
+++ b/packages/bruno-lang/v2/src/jsonToBru.js
@@ -164,6 +164,17 @@ ${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
}
+`;
+ break;
+ case 'implicit':
+ bru += `auth:oauth2 {
+${indentString(`grant_type: implicit`)}
+${indentString(`callback_url: ${auth?.oauth2?.callbackUrl || ''}`)}
+${indentString(`authorization_url: ${auth?.oauth2?.authorizationUrl || ''}`)}
+${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
+${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
+}
+
`;
break;
}
diff --git a/packages/bruno-lang/v2/src/jsonToCollectionBru.js b/packages/bruno-lang/v2/src/jsonToCollectionBru.js
index e4d6ab5fdb..b093323291 100644
--- a/packages/bruno-lang/v2/src/jsonToCollectionBru.js
+++ b/packages/bruno-lang/v2/src/jsonToCollectionBru.js
@@ -152,6 +152,17 @@ ${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
}
+`;
+ break;
+ case 'implicit':
+ bru += `auth:oauth2 {
+${indentString(`grant_type: implicit`)}
+${indentString(`callback_url: ${auth?.oauth2?.callbackUrl || ''}`)}
+${indentString(`authorization_url: ${auth?.oauth2?.authorizationUrl || ''}`)}
+${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
+${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
+}
+
`;
break;
}
diff --git a/packages/bruno-schema/src/collections/index.js b/packages/bruno-schema/src/collections/index.js
index 033e68277f..f9e120a2c2 100644
--- a/packages/bruno-schema/src/collections/index.js
+++ b/packages/bruno-schema/src/collections/index.js
@@ -121,7 +121,7 @@ const authDigestSchema = Yup.object({
const oauth2Schema = Yup.object({
grantType: Yup.string()
- .oneOf(['client_credentials', 'password', 'authorization_code'])
+ .oneOf(['client_credentials', 'password', 'authorization_code', 'implicit'])
.required('grantType is required'),
username: Yup.string().when('grantType', {
is: (val) => ['client_credentials', 'password'].includes(val),
@@ -134,12 +134,12 @@ const oauth2Schema = Yup.object({
otherwise: Yup.string().nullable().strip()
}),
callbackUrl: Yup.string().when('grantType', {
- is: (val) => ['authorization_code'].includes(val),
+ is: (val) => ['authorization_code', 'implicit'].includes(val),
then: Yup.string().nullable(),
otherwise: Yup.string().nullable().strip()
}),
authorizationUrl: Yup.string().when('grantType', {
- is: (val) => ['authorization_code'].includes(val),
+ is: (val) => ['authorization_code', 'implicit'].includes(val),
then: Yup.string().nullable(),
otherwise: Yup.string().nullable().strip()
}),
@@ -149,7 +149,7 @@ const oauth2Schema = Yup.object({
otherwise: Yup.string().nullable().strip()
}),
clientId: Yup.string().when('grantType', {
- is: (val) => ['client_credentials', 'password', 'authorization_code'].includes(val),
+ is: (val) => ['client_credentials', 'password', 'authorization_code', 'implicit'].includes(val),
then: Yup.string().nullable(),
otherwise: Yup.string().nullable().strip()
}),
@@ -159,7 +159,7 @@ const oauth2Schema = Yup.object({
otherwise: Yup.string().nullable().strip()
}),
scope: Yup.string().when('grantType', {
- is: (val) => ['client_credentials', 'password', 'authorization_code'].includes(val),
+ is: (val) => ['client_credentials', 'password', 'authorization_code', 'implicit'].includes(val),
then: Yup.string().nullable(),
otherwise: Yup.string().nullable().strip()
}),