Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuth 2.0 usage #2666

Open
2 tasks done
sosandumsft opened this issue Jul 19, 2024 · 8 comments
Open
2 tasks done

OAuth 2.0 usage #2666

sosandumsft opened this issue Jul 19, 2024 · 8 comments
Labels

Comments

@sosandumsft
Copy link

I have checked the following:

  • I use the newest version of bruno.
  • I've searched existing issues and found nothing related to my issue.

Describe the bug

Hi,
I am trying to use OAuth 2.0 for password credentials (Delegated token). After I set my details I use Get Access Token button and I get the token. But my request id for an REST API, so after I get that token and try to run the request, I get in response the token (like I've pressed Get Access Token button).
Is it normal to have this behavior ?

.bru file to reproduce the bug

No response

Screenshots/Live demo link

image

@sosandumsft sosandumsft added the bug Something isn't working label Jul 19, 2024
@sanjai0py
Copy link
Member

It seems like your request is undergoing a two-request workflow. Once the token is obtained by clicking on 'Get Access Token', it should be stored in a variable using a post-response script.

Consider using the following script:

bru.setVar(req.body.access_token)

Please note that the 'Get Access Token' step doesn't consider the URL in the URL bar and it can be blank. After setting the token variable, you can make a separate request to the URL that the user has in the URL bar with the token variable that was set. This should address the behavior you are experiencing.

@sosandumsft
Copy link
Author

Thanks for reply.
So that request for a token will be a separate request and the URL can be blank in this case.
I thought that the obtained token from Auth tab will be automatically used by request.

@pietrygamat
Copy link
Contributor

It is a known issue reported back in #1999. Seems like it is being presented as a "feature", but questions like this one pop up every few weeks, and I keep hoping it gets addressed some time for usability sake.

@sosandumsft
Copy link
Author

Looks like it was resolved by #2077 or not ?

@pietrygamat
Copy link
Contributor

Looks like it was resolved by #2077 or not ?

Yes. That PR resolves that and makes OAuth2 work (in my humble author's opion) a lot more intuitively. It is still pending review, though.

@hf-krechan
Copy link

This would be a game change for me.
At the moment I find the approach with two requests not really user friendly.

Thanks for your PR. Fingers crossed that it gets a review in the near future ^^

@hf-krechan
Copy link

I needed a solution and found this youtube video which got me at least a temporary solution.

In the collection you can add the following script in the pre-request section

const axios = require('axios')
const btoa = require('btoa')
const moment = require('moment')


const calculateTokenExpiryInMilliseconds = (tokenExpiryVarName) => {
  const currentTime = moment()
  const expiryTime = moment(bru.getVar(tokenExpiryVarName)) || currentTime
  return expiryTime.diff(currentTime, 'milliseconds')
}

const authenticateClient = async (config) => {

  const {
    tokenEndpointVarName,
    clientIdVarName,
    clientSecretVarName,
    bearerTokenVarName
  } = config

  if (!bearerTokenVarName) {
    throw new Error('Missing environment variable name for storing the bearer token')
  }

  const expiryDifferenceInMilliseconds = calculateTokenExpiryInMilliseconds(`expiryFor_${bearerTokenVarName}`)

  const oneMinuteInMilliseconds = 60000

  if (expiryDifferenceInMilliseconds >= oneMinuteInMilliseconds && bru.getVar('lastRequestedEnvironmentName') === bru.getEnvName()) {

    return
  }

  const envVariables = {

    [tokenEndpointVarName]: bru.getEnvVar(tokenEndpointVarName),
    [clientIdVarName]: bru.getEnvVar(clientIdVarName),
    [clientSecretVarName]: bru.getEnvVar(clientSecretVarName)
  }

  const missingVariables = Object.entries(envVariables).filter(([key, value]) => !value).map(([key]) => key)

  // Console log all entries of missingVariables
  missingVariables.forEach(key => console.log(key));

  console.log("checking required env vars.")
  if (missingVariables.length > 0) {
    console.log(`There is something missing: ${missingVariables} `)
    throw new Error(`Missing required environment variables: ${missingVariables.join(', ')}`)
  }


try {
  // Logging the endpoint and credentials being used (ensure not to log sensitive data in production)
  console.log('Token Endpoint:', envVariables[tokenEndpointVarName]);
  console.log('Client ID:', envVariables[clientIdVarName]);

  // Making the HTTP request
  const response = await axios.post(
    envVariables[tokenEndpointVarName], 
    { grant_type: "client_credentials" }, 
    { 
      headers: { 
        "Authorization": `Basic ${btoa(`${envVariables[clientIdVarName]}:${envVariables[clientSecretVarName]}`)}`, 
        "Content-Type": "application/x-www-form-urlencoded" 
      } 
    }
  );

  // Logging the full response to debug
  console.log('Response:', response);

  // Extracting token data
  const tokenData = response.data;
  console.log('Token Data:', tokenData);

  // Storing the token and expiry
  bru.setVar(bearerTokenVarName, tokenData.access_token);
  bru.setVar(`expiryFor_${bearerTokenVarName}`, moment().add(tokenData.expires_in, 'seconds').format());
  bru.setVar('lastRequestedEnvironmentName', bru.getEnvName());
} catch (error) {
  // Enhanced error logging
  console.error('Error occurred while fetching the token:', error);

  // Re-throwing the error after logging
  throw error;
}
}

await authenticateClient({
  tokenEndpointVarName: 'tokenUrl',
  clientIdVarName: 'clientId',
  clientSecretVarName: 'clientSecret',
  bearerTokenVarName: 'bearerToken'
})

Now go in the Collection section to the Auth tab, choose Bearer Token and add there the variable {{bearerToken}}.

In you request you open the Auth section and select there Inherit.

Now each request checks if the token is still valid.

If not it takes a new one and puts it into the bearerToken variable.

Still I would like to prefer the same workflow like in Insomnia.

@apischan
Copy link

apischan commented Aug 24, 2024

looking forward this issue to be fixed but currently cannot use bruno normally

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants