Skip to content

Commit

Permalink
fix: OAuth2 - auth is successful but token endpoint is returned inste…
Browse files Browse the repository at this point in the history
…ad of api endpoint (usebruno#1999)

Setting oauth2 authorization no longer equals overwriting user-specified data in a request. The pre-requests made to obtain oauth2 access_token are now separated from actual API request.
  • Loading branch information
pietrygamat committed Aug 27, 2024
1 parent 6009402 commit 6da0a5d
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 55 deletions.
43 changes: 15 additions & 28 deletions packages/bruno-electron/src/ipc/network/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ const { shouldUseProxy, PatchedHttpsProxyAgent } = require('../../utils/proxy-ut
const { chooseFileToSave, writeBinaryFile, writeFile } = require('../../utils/filesystem');
const { getCookieStringForUrl, addCookieToJar, getDomainsWithCookies } = require('../../utils/cookies');
const {
resolveOAuth2AuthorizationCodeAccessToken,
transformClientCredentialsRequest,
transformPasswordCredentialsRequest
oauth2AuthorizeWithAuthorizationCode,
oauth2AuthorizeWithClientCredentials,
oauth2AuthorizeWithPasswordCredentials
} = require('./oauth2-helper');
const Oauth2Store = require('../../store/oauth2');
const iconv = require('iconv-lite');
Expand Down Expand Up @@ -214,36 +214,23 @@ const configureRequest = async (

if (request.oauth2) {
let requestCopy = cloneDeep(request);
interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars);
let accessToken;
switch (request?.oauth2?.grantType) {
case 'authorization_code':
interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars);
const { data: authorizationCodeData, url: authorizationCodeAccessTokenUrl } =
await resolveOAuth2AuthorizationCodeAccessToken(requestCopy, collectionUid);
request.method = 'POST';
request.headers['content-type'] = 'application/x-www-form-urlencoded';
request.data = authorizationCodeData;
request.url = authorizationCodeAccessTokenUrl;
case 'authorization_code': {
({ accessToken } = await oauth2AuthorizeWithAuthorizationCode(requestCopy, collectionUid));
break;
case 'client_credentials':
interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars);
const { data: clientCredentialsData, url: clientCredentialsAccessTokenUrl } =
await transformClientCredentialsRequest(requestCopy);
request.method = 'POST';
request.headers['content-type'] = 'application/x-www-form-urlencoded';
request.data = clientCredentialsData;
request.url = clientCredentialsAccessTokenUrl;
}
case 'client_credentials': {
({ accessToken } = await oauth2AuthorizeWithClientCredentials(requestCopy, collectionUid));
break;
case 'password':
interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars);
const { data: passwordData, url: passwordAccessTokenUrl } = await transformPasswordCredentialsRequest(
requestCopy
);
request.method = 'POST';
request.headers['content-type'] = 'application/x-www-form-urlencoded';
request.data = passwordData;
request.url = passwordAccessTokenUrl;
}
case 'password': {
({ accessToken } = await oauth2AuthorizeWithPasswordCredentials(requestCopy, collectionUid));
break;
}
}
request.headers['Authorization'] = `Bearer ${accessToken}`;
}

if (request.awsv4config) {
Expand Down
68 changes: 41 additions & 27 deletions packages/bruno-electron/src/ipc/network/oauth2-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { get, cloneDeep } = require('lodash');
const crypto = require('crypto');
const { authorizeUserInWindow } = require('./authorize-user-in-window');
const Oauth2Store = require('../../store/oauth2');
const { makeAxiosInstance } = require('./axios-instance');

const generateCodeVerifier = () => {
return crypto.randomBytes(22).toString('hex');
Expand All @@ -16,31 +17,36 @@ const generateCodeChallenge = (codeVerifier) => {

// AUTHORIZATION CODE

const resolveOAuth2AuthorizationCodeAccessToken = async (request, collectionUid) => {
const oauth2AuthorizeWithAuthorizationCode = async (request, collectionUid) => {
let codeVerifier = generateCodeVerifier();
let codeChallenge = generateCodeChallenge(codeVerifier);

let requestCopy = cloneDeep(request);
const { authorizationCode } = await getOAuth2AuthorizationCode(requestCopy, codeChallenge, collectionUid);
const oAuth = get(requestCopy, 'oauth2', {});
const { clientId, clientSecret, callbackUrl, scope, state, pkce } = oAuth;
const { clientId, clientSecret, callbackUrl, pkce } = oAuth;
const data = {
grant_type: 'authorization_code',
code: authorizationCode,
redirect_uri: callbackUrl,
client_id: clientId,
client_secret: clientSecret,
state: state
client_secret: clientSecret
};
if (pkce) {
data['code_verifier'] = codeVerifier;
}

const url = requestCopy?.oauth2?.accessTokenUrl;
return {
data,
url
};

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

const axiosInstance = makeAxiosInstance();
let response = await axiosInstance(request);
let accessToken = JSON.parse(response.data).access_token;
return { accessToken };
};

const getOAuth2AuthorizationCode = (request, codeChallenge, collectionUid) => {
Expand Down Expand Up @@ -80,7 +86,7 @@ const getOAuth2AuthorizationCode = (request, codeChallenge, collectionUid) => {

// CLIENT CREDENTIALS

const transformClientCredentialsRequest = async (request) => {
const oauth2AuthorizeWithClientCredentials = async (request) => {
let requestCopy = cloneDeep(request);
const oAuth = get(requestCopy, 'oauth2', {});
const { clientId, clientSecret, scope } = oAuth;
Expand All @@ -92,18 +98,23 @@ const transformClientCredentialsRequest = async (request) => {
if (scope) {
data.scope = scope;
}
const url = requestCopy?.oauth2?.accessTokenUrl;
return {
data,
url
};

request.method = 'POST';
request.headers['content-type'] = 'application/x-www-form-urlencoded';
request.data = data;
request.url = requestCopy?.oauth2?.accessTokenUrl;

const axiosInstance = makeAxiosInstance();
let response = await axiosInstance(request);
let accessToken = JSON.parse(response.data).access_token;

return { accessToken };
};

// PASSWORD CREDENTIALS

const transformPasswordCredentialsRequest = async (request) => {
let requestCopy = cloneDeep(request);
const oAuth = get(requestCopy, 'oauth2', {});
const oauth2AuthorizeWithPasswordCredentials = async (request) => {
const oAuth = get(request, 'oauth2', {});
const { username, password, clientId, clientSecret, scope } = oAuth;
const data = {
grant_type: 'password',
Expand All @@ -115,16 +126,19 @@ const transformPasswordCredentialsRequest = async (request) => {
if (scope) {
data.scope = scope;
}
const url = requestCopy?.oauth2?.accessTokenUrl;
return {
data,
url
};
};

request.method = 'POST';
request.headers['content-type'] = 'application/x-www-form-urlencoded';
request.data = data;
request.url = request?.oauth2?.accessTokenUrl;

const axiosInstance = makeAxiosInstance();
let response = await axiosInstance(request);
let accessToken = JSON.parse(response.data).access_token;
return { accessToken };
};
module.exports = {
resolveOAuth2AuthorizationCodeAccessToken,
getOAuth2AuthorizationCode,
transformClientCredentialsRequest,
transformPasswordCredentialsRequest
oauth2AuthorizeWithAuthorizationCode,
oauth2AuthorizeWithClientCredentials,
oauth2AuthorizeWithPasswordCredentials
};

0 comments on commit 6da0a5d

Please sign in to comment.