fix: OAuth2 - auth is successful but token endpoint is returned instead of api endpoint (#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.
This commit is contained in:
Mateusz Pietryga
2024-04-11 08:12:46 +02:00
parent 4ef5534d41
commit 22a9502976
2 changed files with 56 additions and 54 deletions

View File

@@ -31,9 +31,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');
@@ -267,36 +267,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) {

View File

@@ -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');
@@ -16,14 +17,14 @@ 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, pkce } = oAuth;
const { clientId, clientSecret, callbackUrl, pkce } = oAuth;
const data = {
grant_type: 'authorization_code',
code: authorizationCode,
@@ -36,10 +37,16 @@ const resolveOAuth2AuthorizationCodeAccessToken = async (request, collectionUid)
}
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) => {
@@ -79,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;
@@ -91,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',
@@ -114,16 +126,19 @@ const transformPasswordCredentialsRequest = async (request) => {
if (scope) {
data.scope = scope;
}
const url = requestCopy?.oauth2?.accessTokenUrl;
return {
data,
url
};
};
module.exports = {
resolveOAuth2AuthorizationCodeAccessToken,
getOAuth2AuthorizationCode,
transformClientCredentialsRequest,
transformPasswordCredentialsRequest
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 = {
oauth2AuthorizeWithAuthorizationCode,
oauth2AuthorizeWithClientCredentials,
oauth2AuthorizeWithPasswordCredentials
};