feat: enhance OAuth2 support in snippet generation (#6592)

* feat: enhance OAuth2 support in snippet generation

* Updated getAuthHeaders function to handle OAuth2 authentication, including token retrieval and placement.
* Added tests for OAuth2 scenarios, ensuring correct Authorization header generation and handling of edge cases.
* Improved error handling for access token retrieval from stored credentials.

* refactor: standardize comparison operators in getAuthHeaders function

* Updated comparison operators in the getAuthHeaders function to use strict equality (===) for improved consistency and reliability in credential checks.

* fix: correct block structure in OAuth2 case of getAuthHeaders function

* Added missing block structure for the 'oauth2' case in the getAuthHeaders function to ensure proper execution flow and maintain code clarity.

* feat: enhance OAuth2 credential retrieval in getAuthHeaders function

* Updated getAuthHeaders function to support retrieval of stored OAuth2 credentials based on collection and item context.
* Improved access token handling by checking for existing credentials before falling back to default values.
* Enhanced test coverage for OAuth2 scenarios to ensure accurate token management and error handling.

* fix: preserve tokenHeaderPrefix value in OAuth2 configuration

* Updated snippet-generator.spec.js to ensure that the tokenHeaderPrefix from OAuth2 configuration is preserved, allowing for empty string scenarios.
* Default to 'Bearer' only if the tokenHeaderPrefix is undefined, enhancing flexibility in token management.

* fix: ensure consistent formatting of authorization header in OAuth2 handling

* Updated getAuthHeaders function to always trim the final result of the authorization header for consistent formatting.
* Adjusted snippet-generator.spec.js to reflect the same trimming logic for the access token, enhancing test reliability.

* fix: clarify token placement handling in getAuthHeaders function

* Updated comments in the getAuthHeaders function to specify that when tokenPlacement is 'url', no auth headers are added, and that token placement in the URL/query params must be managed separately.

* fix: ensure safe handling of OAuth2 credentials in getAuthHeaders function

* Updated getAuthHeaders function to default to an empty array when accessing oauth2Credentials, preventing potential errors when no credentials are available.
This commit is contained in:
Yash
2026-01-21 12:23:05 +05:30
committed by GitHub
parent 967b073ded
commit 0bf169562b
3 changed files with 291 additions and 2 deletions

View File

@@ -1,6 +1,9 @@
import get from 'lodash/get';
import { find } from 'lodash';
import { interpolate } from '@usebruno/common';
import { getAllVariables } from 'utils/collections/index';
export const getAuthHeaders = (collectionRootAuth, requestAuth) => {
export const getAuthHeaders = (collectionRootAuth, requestAuth, collection = null, item = null) => {
// Discovered edge case where code generation fails when you create a collection which has not been saved yet:
// Collection auth therefore null, and request inherits from collection, therefore it is also null
// TypeError: Cannot read properties of undefined (reading 'mode')
@@ -48,6 +51,72 @@ export const getAuthHeaders = (collectionRootAuth, requestAuth) => {
];
}
return [];
case 'oauth2': {
const oauth2Config = get(auth, 'oauth2', {});
const tokenPlacement = get(oauth2Config, 'tokenPlacement', 'header');
const tokenHeaderPrefix = get(oauth2Config, 'tokenHeaderPrefix', 'Bearer');
// Only add header if token placement is 'header'
if (tokenPlacement === 'header') {
// Try to get access token from persisted credentials
let accessToken = '<access_token>';
if (collection && item) {
try {
const grantType = get(oauth2Config, 'grantType', '');
// For implicit grant type, use authorizationUrl; for others, use accessTokenUrl
const urlToLookup = grantType === 'implicit'
? get(oauth2Config, 'authorizationUrl', '')
: get(oauth2Config, 'accessTokenUrl', '');
const credentialsId = get(oauth2Config, 'credentialsId', 'credentials');
const collectionUid = get(collection, 'uid');
if (urlToLookup && collectionUid) {
// Interpolate the URL with variables
const variables = getAllVariables(collection, item);
const interpolatedUrl = interpolate(urlToLookup, variables);
// Look up stored credentials
const credentialsData = find(
collection?.oauth2Credentials || [],
(creds) =>
creds?.url === interpolatedUrl
&& creds?.collectionUid === collectionUid
&& creds?.credentialsId === credentialsId
);
if (credentialsData?.credentials?.access_token) {
accessToken = credentialsData.credentials.access_token;
}
}
} catch (error) {
console.error('Error retrieving OAuth2 access token:', error);
// Fall back to placeholder if lookup fails
}
}
// Build the authorization header value
// If tokenHeaderPrefix is empty, just use the token
// Otherwise, use the format: "prefix token"
// Always trim the final result for consistent formatting
const headerValue = (
tokenHeaderPrefix
? `${tokenHeaderPrefix} ${accessToken}`
: accessToken
).trim();
return [
{
enabled: true,
name: 'Authorization',
value: headerValue
}
];
}
// If tokenPlacement is 'url', this function does not add any auth headers;
// token placement in the URL/query params must be handled elsewhere.
return [];
}
default:
return [];
}