Skip to content

Commit

Permalink
feat: OAuth2 - Client Credentials as Basic Auth Header - request logic
Browse files Browse the repository at this point in the history
Update OAuth2 request logic to make use of client_secret_method option
  • Loading branch information
pietrygamat committed Jan 23, 2025
1 parent e2d5fc7 commit 38253e3
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 19 deletions.
6 changes: 4 additions & 2 deletions packages/bruno-electron/src/ipc/network/interpolate-vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,14 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
}

if (request?.oauth2?.grantType) {
let username, password, scope, clientId, clientSecret;
switch (request.oauth2.grantType) {
case 'password':
request.oauth2.accessTokenUrl = _interpolate(request.oauth2.accessTokenUrl) || '';
request.oauth2.username = _interpolate(request.oauth2.username) || '';
request.oauth2.password = _interpolate(request.oauth2.password) || '';
request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
request.oauth2.clientSecretMethod = _interpolate(request.oauth2.clientSecretMethod) || '';
request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
request.oauth2.credentialsId = _interpolate(request.oauth2.credentialsId) || '';
request.oauth2.tokenPlacement = _interpolate(request.oauth2.tokenPlacement) || '';
Expand All @@ -179,6 +179,7 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
request.oauth2.accessTokenUrl = _interpolate(request.oauth2.accessTokenUrl) || '';
request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
request.oauth2.clientSecretMethod = _interpolate(request.oauth2.clientSecretMethod) || '';
request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
request.oauth2.state = _interpolate(request.oauth2.state) || '';
request.oauth2.pkce = _interpolate(request.oauth2.pkce) || false;
Expand All @@ -192,6 +193,7 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
request.oauth2.accessTokenUrl = _interpolate(request.oauth2.accessTokenUrl) || '';
request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
request.oauth2.clientSecretMethod = _interpolate(request.oauth2.clientSecretMethod) || '';
request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
request.oauth2.credentialsId = _interpolate(request.oauth2.credentialsId) || '';
request.oauth2.tokenPlacement = _interpolate(request.oauth2.tokenPlacement) || '';
Expand Down Expand Up @@ -231,7 +233,7 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc
if (request.ntlmConfig) {
request.ntlmConfig.username = _interpolate(request.ntlmConfig.username) || '';
request.ntlmConfig.password = _interpolate(request.ntlmConfig.password) || '';
request.ntlmConfig.domain = _interpolate(request.ntlmConfig.domain) || '';
request.ntlmConfig.domain = _interpolate(request.ntlmConfig.domain) || '';
}

return request;
Expand Down
52 changes: 35 additions & 17 deletions packages/bruno-electron/src/utils/oauth2.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ 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, clientSecretMethod, callbackUrl, scope, pkce, authorizationUrl, credentialsId, reuseToken } = oAuth;
const url = requestCopy?.oauth2?.accessTokenUrl;

if ((reuseToken || ALWAYS_REUSE_ACCESS_TOKEN____UNLESS_FETCHED_MANUALLY) && !forceFetch) {
Expand All @@ -43,20 +43,20 @@ const getOAuth2TokenUsingAuthorizationCode = async ({ request, collectionUid, fo
const data = {
grant_type: 'authorization_code',
code: authorizationCode,
redirect_uri: callbackUrl,
client_id: clientId,
client_secret: clientSecret
redirect_uri: callbackUrl
};
if (pkce) {
data['code_verifier'] = codeVerifier;
}

requestCopy.method = 'POST';
requestCopy.headers['content-type'] = 'application/x-www-form-urlencoded';
requestCopy.headers['Accept'] = 'application/json';
requestCopy.headers['accept'] = 'application/json';
requestCopy.data = data;
requestCopy.url = url;

setClientCredentials(clientId, clientSecret, clientSecretMethod, requestCopy);

const axiosInstance = makeAxiosInstance();
const response = await axiosInstance(requestCopy);
const responseData = Buffer.isBuffer(response.data) ? response.data?.toString() : response.data;
Expand Down Expand Up @@ -105,11 +105,9 @@ 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 { clientId, clientSecret, clientSecretMethod, scope, credentialsId, reuseToken } = oAuth;
const data = {
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret
grant_type: 'client_credentials'
};
if (scope) {
data.scope = scope;
Expand All @@ -124,10 +122,12 @@ const getOAuth2TokenUsingClientCredentials = async ({ request, collectionUid, fo

requestCopy.method = 'POST';
requestCopy.headers['content-type'] = 'application/x-www-form-urlencoded';
requestCopy.headers['Accept'] = 'application/json';
requestCopy.headers['accept'] = 'application/json';
requestCopy.data = data;
requestCopy.url = url;

setClientCredentials(clientId, clientSecret, clientSecretMethod, requestCopy);

const axiosInstance = makeAxiosInstance();

const response = await axiosInstance(requestCopy);
Expand All @@ -142,13 +142,11 @@ 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 { username, password, clientId, clientSecret, clientSecretMethod, scope, credentialsId, reuseToken } = oAuth;
const data = {
grant_type: 'password',
username,
password,
client_id: clientId,
client_secret: clientSecret
password
};
if (scope) {
data.scope = scope;
Expand All @@ -162,10 +160,12 @@ const getOAuth2TokenUsingPasswordCredentials = async ({ request, collectionUid,

requestCopy.method = 'POST';
requestCopy.headers['content-type'] = 'application/x-www-form-urlencoded';
requestCopy.headers['Accept'] = 'application/json';
requestCopy.headers['accept'] = 'application/json';
requestCopy.data = data;
requestCopy.url = url;

setClientCredentials(clientId, clientSecret, clientSecretMethod, requestCopy);

const axiosInstance = makeAxiosInstance();
const response = await axiosInstance(requestCopy);
const responseData = Buffer.isBuffer(response.data) ? response.data?.toString() : response.data;
Expand All @@ -177,7 +177,7 @@ const getOAuth2TokenUsingPasswordCredentials = async ({ request, collectionUid,
const refreshOauth2Token = async (request, collectionUid) => {
let requestCopy = cloneDeep(request);
const oAuth = get(requestCopy, 'oauth2', {});
const { clientId, clientSecret, credentialsId } = oAuth;
const { clientId, clientSecret, clientSecretMethod, credentialsId } = oAuth;
const url = requestCopy?.oauth2?.accessTokenUrl;

const credentials = getStoredOauth2Credentials({ collectionUid, url, credentialsId });
Expand All @@ -195,10 +195,12 @@ const refreshOauth2Token = async (request, collectionUid) => {
};
requestCopy.method = 'POST';
requestCopy.headers['content-type'] = 'application/x-www-form-urlencoded';
requestCopy.headers['Accept'] = 'application/json';
requestCopy.headers['accept'] = 'application/json';
requestCopy.data = data;
requestCopy.url = url;

setClientCredentials(clientId, clientSecret, clientSecretMethod, requestCopy);

const axiosInstance = makeAxiosInstance();
try {
const response = await axiosInstance(requestCopy);
Expand Down Expand Up @@ -228,6 +230,22 @@ const generateCodeChallenge = (codeVerifier) => {
return base64Hash.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
};

const setClientCredentials = (clientId, clientSecret, clientSecretMethod, request) => {
if (clientSecret) {
switch (clientSecretMethod) {
case 'client_credentials_post': {
request.data["client_id"] = clientId;
request.data["client_secret"] = clientSecret;
break;
}
case 'client_credentials_basic': {
request.headers["authorization"] = 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64');
break;
}
}
}
};

module.exports = {
getOAuth2TokenUsingAuthorizationCode,
getOAuth2AuthorizationCode,
Expand Down
5 changes: 5 additions & 0 deletions packages/bruno-electron/src/utils/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
password: get(collectionAuth, 'oauth2.password'),
clientId: get(collectionAuth, 'oauth2.clientId'),
clientSecret: get(collectionAuth, 'oauth2.clientSecret'),
clientSecretMethod: get(collectionAuth, 'oauth2.clientSecretMethod'),
scope: get(collectionAuth, 'oauth2.scope'),
credentialsId: get(collectionAuth, 'oauth2.credentialsId'),
tokenPlacement: get(collectionAuth, 'oauth2.tokenPlacement'),
Expand All @@ -112,6 +113,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
accessTokenUrl: get(collectionAuth, 'oauth2.accessTokenUrl'),
clientId: get(collectionAuth, 'oauth2.clientId'),
clientSecret: get(collectionAuth, 'oauth2.clientSecret'),
clientSecretMethod: get(collectionAuth, 'oauth2.clientSecretMethod'),
scope: get(collectionAuth, 'oauth2.scope'),
state: get(collectionAuth, 'oauth2.state'),
pkce: get(collectionAuth, 'oauth2.pkce'),
Expand All @@ -128,6 +130,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
accessTokenUrl: get(collectionAuth, 'oauth2.accessTokenUrl'),
clientId: get(collectionAuth, 'oauth2.clientId'),
clientSecret: get(collectionAuth, 'oauth2.clientSecret'),
clientSecretMethod: get(collectionAuth, 'oauth2.clientSecretMethod'),
scope: get(collectionAuth, 'oauth2.scope'),
credentialsId: get(collectionAuth, 'oauth2.credentialsId'),
tokenPlacement: get(collectionAuth, 'oauth2.tokenPlacement'),
Expand Down Expand Up @@ -201,6 +204,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
accessTokenUrl: get(request, 'auth.oauth2.accessTokenUrl'),
clientId: get(request, 'auth.oauth2.clientId'),
clientSecret: get(request, 'auth.oauth2.clientSecret'),
clientSecretMethod: get(request, 'auth.oauth2.clientSecretMethod'),
scope: get(request, 'auth.oauth2.scope'),
state: get(request, 'auth.oauth2.state'),
pkce: get(request, 'auth.oauth2.pkce'),
Expand All @@ -217,6 +221,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
accessTokenUrl: get(request, 'auth.oauth2.accessTokenUrl'),
clientId: get(request, 'auth.oauth2.clientId'),
clientSecret: get(request, 'auth.oauth2.clientSecret'),
clientSecretMethod: get(request, 'auth.oauth2.clientSecretMethod'),
scope: get(request, 'auth.oauth2.scope'),
credentialsId: get(request, 'auth.oauth2.credentialsId'),
tokenPlacement: get(request, 'auth.oauth2.tokenPlacement'),
Expand Down

0 comments on commit 38253e3

Please sign in to comment.