Skip to content

Commit

Permalink
feat: OAuth2 - display token request and response details on the time…
Browse files Browse the repository at this point in the history
…line
  • Loading branch information
pietrygamat committed Sep 23, 2024
1 parent bbbcb78 commit e8e5da1
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 21 deletions.
46 changes: 44 additions & 2 deletions packages/bruno-app/src/components/ResponsePane/Timeline/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ import StyledWrapper from './StyledWrapper';
const Timeline = ({ request, response }) => {
const requestHeaders = [];
const responseHeaders = typeof response.headers === 'object' ? Object.entries(response.headers) : [];
const requestData = typeof request?.data === "string" ? request?.data : safeStringifyJSON(request?.data, true);

const authRequest = request.authRequest;
const authResponse = request.authResponse;
const authRequestHeaders = typeof authRequest?.headers === 'object' ? Object.entries(authRequest.headers) : [];
const authResponseHeaders = typeof authResponse?.headers === 'object' ? Object.entries(authResponse?.headers) : [];
const authRequestData = authRequest?.data === "string" ? authRequest?.data : safeStringifyJSON(authRequest?.data, true);

request = request || {};
response = response || {};
Expand All @@ -17,10 +24,45 @@ const Timeline = ({ request, response }) => {
});
});

let requestData = typeof request?.data === "string" ? request?.data : safeStringifyJSON(request?.data, true);

return (
<StyledWrapper className="pb-4 w-full">
{authRequest ? (
<>
<div>
<pre className="line request font-bold">
<span className="arrow">{'>'}</span> {authRequest.method} {authRequest.url}
</pre>
{authRequestHeaders.map((h) => {
return (
<pre className="line request" key={h[0]}>
<span className="arrow">{'>'}</span> {h[0]}: {h[1]}
</pre>
);
})}
{authRequestData ? (
<pre className="line request">
<span className="arrow">{'>'}</span> data {authRequestData}
</pre>
) : null}
</div>
{authResponse ? (
<div className="mt-4">
<pre className="line response font-bold">
<span className="arrow">{'<'}</span> {authResponse.status} {authResponse.statusText}
</pre>
{authResponseHeaders.map((h) => {
return (
<pre className="line response" key={h[0]}>
<span className="arrow">{'<'}</span> {h[0]}: {h[1]}
</pre>
);
})}
</div>
) : null}
<div className="mt-4" />
</>
) : null}

<div>
<pre className="line request font-bold">
<span className="arrow">{'>'}</span> {request.method} {request.url}
Expand Down
42 changes: 35 additions & 7 deletions packages/bruno-electron/src/ipc/network/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,23 +267,33 @@ const configureRequest = async (
if (request.oauth2) {
let requestCopy = cloneDeep(request);
interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars);
let credentials, response;
let credentials, authResponse, authRequest;
switch (request?.oauth2?.grantType) {
case 'authorization_code': {
({ credentials, response } = await oauth2AuthorizeWithAuthorizationCode(requestCopy, collectionUid));
({ credentials, authRequest, authResponse } = await oauth2AuthorizeWithAuthorizationCode(
requestCopy,
collectionUid
));
break;
}
case 'client_credentials': {
({ credentials, response } = await oauth2AuthorizeWithClientCredentials(requestCopy, collectionUid));
({ credentials, authRequest, authResponse } = await oauth2AuthorizeWithClientCredentials(
requestCopy,
collectionUid
));
break;
}
case 'password': {
({ credentials, response } = await oauth2AuthorizeWithPasswordCredentials(requestCopy, collectionUid));
({ credentials, authRequest, authResponse } = await oauth2AuthorizeWithPasswordCredentials(
requestCopy,
collectionUid
));
break;
}
}
request.credentials = credentials;
request.authRequestResponse = response;
request.authRequest = authRequest;
request.authResponse = authResponse;

// Bruno can handle bearer token type automatically.
// Other - more exotic token types are not touched
Expand Down Expand Up @@ -558,6 +568,24 @@ const registerNetworkIpc = (mainWindow) => {
method: request.method,
headers: request.headers,
data: safeParseJSON(safeStringifyJSON(request.data)),
authRequest: request.authRequest
? {
url: request.authRequest.url,
method: request.authRequest.method,
headers: request.authRequest.headers,
data: request.authRequest.data,
timestamp: request.authRequest.timestamp
}
: null,
authResponse: request.authResponse
? {
headers: request.authResponse ? request.authResponse.headers : [],
data: request.authResponse.data ? parseDataFromResponse(request.authResponse).data : {},
status: request.authResponse.status,
statusText: request.authResponse.statusText,
timestamp: request.authResponse.timestamp
}
: null,
timestamp: Date.now()
},
collectionUid,
Expand Down Expand Up @@ -743,8 +771,8 @@ const registerNetworkIpc = (mainWindow) => {
collectionPath
);

const response = request.authRequestResponse;
// When credentials are loaded from cache, authRequestResponse has no data
const response = request.authResponse;
// When credentials are loaded from cache, authResponse has no data
if (response.data) {
const { data } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
response.data = data;
Expand Down
25 changes: 13 additions & 12 deletions packages/bruno-electron/src/ipc/network/oauth2-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const oauth2AuthorizeWithAuthorizationCode = async (request, collectionUid) => {
const { cachedCredentials } = getPersistedOauth2Credentials(collectionUid);
if (cachedCredentials?.access_token) {
console.log('Reusing Stored access token');
return { credentials: cachedCredentials, response: {} };
return { credentials: cachedCredentials, authRequest: null, authResponse: null };
}

let codeVerifier = generateCodeVerifier();
Expand Down Expand Up @@ -79,10 +79,11 @@ const oauth2AuthorizeWithAuthorizationCode = async (request, collectionUid) => {
setClientCredentials(clientId, clientSecret, clientSecretMethod, request);

const axiosInstance = makeAxiosInstance();
const response = await axiosInstance(request);
const credentials = JSON.parse(response.data);
const authResponse = await axiosInstance(request);
const credentials = JSON.parse(authResponse.data);
persistOauth2Credentials(credentials, collectionUid);
return { credentials, response };

return { credentials, authRequest: request, authResponse };
};

const getOAuth2AuthorizationCode = (request, codeChallenge, collectionUid) => {
Expand Down Expand Up @@ -125,7 +126,7 @@ const oauth2AuthorizeWithClientCredentials = async (request, collectionUid) => {
const { cachedCredentials } = getPersistedOauth2Credentials(collectionUid);
if (cachedCredentials?.access_token) {
console.log('Reusing Stored access token');
return { credentials: cachedCredentials, response: {} };
return { credentials: cachedCredentials, authRequest: null, authResponse: null };
}

let requestCopy = cloneDeep(request);
Expand All @@ -146,10 +147,10 @@ const oauth2AuthorizeWithClientCredentials = async (request, collectionUid) => {
setClientCredentials(clientId, clientSecret, clientSecretMethod, request);

const axiosInstance = makeAxiosInstance();
let response = await axiosInstance(request);
let credentials = JSON.parse(response.data);
let authResponse = await axiosInstance(request);
let credentials = JSON.parse(authResponse.data);
persistOauth2Credentials(credentials, collectionUid);
return { credentials, response };
return { credentials, authRequest: request, authResponse };
};

// PASSWORD CREDENTIALS
Expand All @@ -158,7 +159,7 @@ const oauth2AuthorizeWithPasswordCredentials = async (request, collectionUid) =>
const { cachedCredentials } = getPersistedOauth2Credentials(collectionUid);
if (cachedCredentials?.access_token) {
console.log('Reusing Stored access token');
return { credentials: cachedCredentials, response: {} };
return { credentials: cachedCredentials, authRequest: null, authResponse: null };
}

const oAuth = get(request, 'oauth2', {});
Expand All @@ -180,10 +181,10 @@ const oauth2AuthorizeWithPasswordCredentials = async (request, collectionUid) =>
setClientCredentials(clientId, clientSecret, clientSecretMethod, request);

const axiosInstance = makeAxiosInstance();
let response = await axiosInstance(request);
let credentials = JSON.parse(response.data);
let authResponse = await axiosInstance(request);
let credentials = JSON.parse(authResponse.data);
persistOauth2Credentials(credentials, collectionUid);
return { credentials, response };
return { credentials, authRequest: request, authResponse };
};
module.exports = {
oauth2AuthorizeWithAuthorizationCode,
Expand Down

0 comments on commit e8e5da1

Please sign in to comment.