mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-09 06:55:03 +00:00
@@ -67,6 +67,44 @@ const getOAuth2TokenUsingAuthorizationCode = async ({ request, collectionUid, fo
|
||||
autoFetchToken,
|
||||
} = oAuth;
|
||||
const url = requestCopy?.oauth2?.accessTokenUrl;
|
||||
|
||||
// Validate required fields
|
||||
if (!authorizationUrl) {
|
||||
return {
|
||||
error: 'Authorization URL is required for OAuth2 authorization code flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
return {
|
||||
error: 'Access Token URL is required for OAuth2 authorization code flow',
|
||||
credentials: null,
|
||||
url: authorizationUrl,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!callbackUrl) {
|
||||
return {
|
||||
error: 'Callback URL is required for OAuth2 authorization code flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!clientId) {
|
||||
return {
|
||||
error: 'Client ID is required for OAuth2 authorization code flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!forceFetch) {
|
||||
const storedCredentials = getStoredOauth2Credentials({ collectionUid, url, credentialsId });
|
||||
|
||||
@@ -279,6 +317,34 @@ const getOAuth2TokenUsingClientCredentials = async ({ request, collectionUid, fo
|
||||
|
||||
const url = requestCopy?.oauth2?.accessTokenUrl;
|
||||
|
||||
// Validate required fields
|
||||
if (!url) {
|
||||
return {
|
||||
error: 'Access Token URL is required for OAuth2 client credentials flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!clientId) {
|
||||
return {
|
||||
error: 'Client ID is required for OAuth2 client credentials flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!clientSecret) {
|
||||
return {
|
||||
error: 'Client Secret is required for OAuth2 client credentials flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!forceFetch) {
|
||||
const storedCredentials = getStoredOauth2Credentials({ collectionUid, url, credentialsId });
|
||||
|
||||
@@ -447,6 +513,43 @@ const getOAuth2TokenUsingPasswordCredentials = async ({ request, collectionUid,
|
||||
} = oAuth;
|
||||
const url = requestCopy?.oauth2?.accessTokenUrl;
|
||||
|
||||
// Validate required fields
|
||||
if (!url) {
|
||||
return {
|
||||
error: 'Access Token URL is required for OAuth2 password credentials flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!username) {
|
||||
return {
|
||||
error: 'Username is required for OAuth2 password credentials flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
return {
|
||||
error: 'Password is required for OAuth2 password credentials flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!clientId) {
|
||||
return {
|
||||
error: 'Client ID is required for OAuth2 password credentials flow',
|
||||
credentials: null,
|
||||
url,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!forceFetch) {
|
||||
const storedCredentials = getStoredOauth2Credentials({ collectionUid, url, credentialsId });
|
||||
|
||||
@@ -726,10 +829,167 @@ const generateCodeChallenge = (codeVerifier) => {
|
||||
return base64Hash;
|
||||
};
|
||||
|
||||
const getOAuth2TokenUsingImplicitGrant = async ({ request, collectionUid, forceFetch = false }) => {
|
||||
const { oauth2 = {} } = request;
|
||||
const {
|
||||
authorizationUrl,
|
||||
clientId,
|
||||
scope,
|
||||
state = '',
|
||||
callbackUrl,
|
||||
credentialsId = 'credentials',
|
||||
autoFetchToken = true
|
||||
} = oauth2;
|
||||
|
||||
// Validate required fields
|
||||
if (!authorizationUrl) {
|
||||
return {
|
||||
error: 'Authorization URL is required for OAuth2 implicit flow',
|
||||
credentials: null,
|
||||
url: authorizationUrl,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
if (!callbackUrl) {
|
||||
return {
|
||||
error: 'Callback URL is required for OAuth2 implicit flow',
|
||||
credentials: null,
|
||||
url: authorizationUrl,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
|
||||
// Check if we already have valid credentials
|
||||
if (!forceFetch) {
|
||||
try {
|
||||
const storedCredentials = getStoredOauth2Credentials({
|
||||
collectionUid,
|
||||
url: authorizationUrl,
|
||||
credentialsId
|
||||
});
|
||||
|
||||
if (storedCredentials) {
|
||||
// Token exists
|
||||
if (!isTokenExpired(storedCredentials)) {
|
||||
// Token is valid, use it
|
||||
return {
|
||||
collectionUid,
|
||||
credentials: storedCredentials,
|
||||
url: authorizationUrl,
|
||||
credentialsId
|
||||
};
|
||||
} else {
|
||||
// Token is expired - unlike other grant types, implicit flow doesn't support refresh tokens
|
||||
if (autoFetchToken) {
|
||||
// Proceed to fetch new token
|
||||
clearOauth2Credentials({ collectionUid, url: authorizationUrl, credentialsId });
|
||||
} else {
|
||||
// Proceed with expired token
|
||||
return {
|
||||
collectionUid,
|
||||
credentials: storedCredentials,
|
||||
url: authorizationUrl,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No stored credentials
|
||||
if (!autoFetchToken) {
|
||||
// Don't fetch token if autoFetchToken is disabled
|
||||
return {
|
||||
collectionUid,
|
||||
credentials: null,
|
||||
url: authorizationUrl,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
// Otherwise proceed to fetch new token
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error retrieving oauth2 credentials from cache', error);
|
||||
clearOauth2Credentials({ collectionUid, url: authorizationUrl, credentialsId });
|
||||
}
|
||||
}
|
||||
|
||||
const authorizationUrlWithQueryParams = new URL(authorizationUrl);
|
||||
authorizationUrlWithQueryParams.searchParams.append('response_type', 'token');
|
||||
authorizationUrlWithQueryParams.searchParams.append('client_id', clientId);
|
||||
authorizationUrlWithQueryParams.searchParams.append('redirect_uri', callbackUrl);
|
||||
if (scope) {
|
||||
authorizationUrlWithQueryParams.searchParams.append('scope', scope);
|
||||
}
|
||||
if (state) {
|
||||
authorizationUrlWithQueryParams.searchParams.append('state', state);
|
||||
}
|
||||
|
||||
const authorizeUrl = authorizationUrlWithQueryParams.toString();
|
||||
|
||||
try {
|
||||
const { implicitTokens, debugInfo } = await authorizeUserInWindow({
|
||||
authorizeUrl,
|
||||
callbackUrl,
|
||||
session: oauth2Store.getSessionIdOfCollection({ collectionUid, url: authorizationUrl }),
|
||||
grantType: 'implicit'
|
||||
});
|
||||
|
||||
if (!implicitTokens || !implicitTokens.access_token) {
|
||||
return {
|
||||
error: 'No access token received from authorization server',
|
||||
credentials: null,
|
||||
url: authorizationUrl,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
};
|
||||
}
|
||||
|
||||
const credentials = {
|
||||
access_token: implicitTokens.access_token,
|
||||
token_type: implicitTokens.token_type || 'Bearer',
|
||||
state: implicitTokens.state || '',
|
||||
...(implicitTokens.expires_in ? { expires_in: parseInt(implicitTokens.expires_in) } : {}),
|
||||
created_at: Date.now()
|
||||
};
|
||||
|
||||
if (implicitTokens.scope) {
|
||||
credentials.scope = implicitTokens.scope;
|
||||
}
|
||||
|
||||
// Store the credentials
|
||||
persistOauth2Credentials({
|
||||
collectionUid,
|
||||
url: authorizationUrl,
|
||||
credentials,
|
||||
credentialsId
|
||||
});
|
||||
|
||||
return {
|
||||
collectionUid,
|
||||
credentials,
|
||||
url: authorizationUrl,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
error: error.message || 'Failed to obtain token',
|
||||
credentials: null,
|
||||
url: authorizationUrl,
|
||||
credentialsId
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
persistOauth2Credentials,
|
||||
clearOauth2Credentials,
|
||||
getStoredOauth2Credentials,
|
||||
getOAuth2TokenUsingAuthorizationCode,
|
||||
getOAuth2AuthorizationCode,
|
||||
getOAuth2TokenUsingClientCredentials,
|
||||
getOAuth2TokenUsingPasswordCredentials,
|
||||
refreshOauth2Token
|
||||
getOAuth2TokenUsingImplicitGrant,
|
||||
refreshOauth2Token,
|
||||
generateCodeVerifier,
|
||||
generateCodeChallenge
|
||||
};
|
||||
Reference in New Issue
Block a user