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

Oauth2: Supported at the request level, but not at the collection level #1704

Open
clocklear opened this issue Mar 1, 2024 · 14 comments · May be fixed by #2077
Open

Oauth2: Supported at the request level, but not at the collection level #1704

clocklear opened this issue Mar 1, 2024 · 14 comments · May be fixed by #2077

Comments

@clocklear
Copy link

When configuring OAuth 2.0, it would be helpful to configure once per collection instead of requiring configuration on individual requests:

Auth configuration at the request level:
image

Auth configuration at the collection level:
image

(This is for Bruno v1.10.0)

@jackj93
Copy link

jackj93 commented Mar 18, 2024

For people that found this page via searching the issue, this is now possible with a little workaround in v1.11.0.
Set the collection level auth as OAuth 2.0 (like Insomnia/Postman)
Navigate to the "Script" pane of the collection and set the access token as a variable in the "Post response" section

  var token = res.body.access_token;
  if (token) {
    bru.setVar('oauth2_token', token)
  }

Then navigate to the "Headers" pane still in the collection settings and set the "Authorization" header as needed.
i.e.
image

Once you do this, you only need to "Get the token" once and then all requests in the collection will use this access token.

Full collection.bru for anything that just wants to copy that.

headers {
  Authorization: Bearer {{oauth2_token}}
}

auth {
  mode: oauth2
}

auth:oauth2 {
  grant_type: authorization_code
  callback_url: {{RedirectUrl}}
  authorization_url: {{AuthorizationUrl}}
  access_token_url: {{AccessTokenUrl}}
  client_id: {{ClientId}}
  client_secret: 
  scope: {{GatewayScope}}
  pkce: false
}

script:post-response {
  var token = res.body.access_token;
  if (token) {
    bru.setVar('oauth2_token', token)
  }
}

DO NOT change the request level settings (auth or script), leave the request level Auth settings on "No Auth"

After setting this up, you would just need to navigate to the "Auth" pane in collection settings, press "Get New Token" and you should be good to go to call the protected endpoints in the collection.

@dougbreaux
Copy link

@jackj93 this isn't working for me either (v 1.12.1 now). Var isn't being set by the script either when hitting "Get Access Token" button on the Collection Authorization or in making a call that uses inherit authorization.

@EirikHaughom
Copy link

@jackj93 did you have to install an external module for this to work?
When putting the code you mention in the pre request script location on the collection, I just get this error:

Error invoking remote method 'send-http-request': ReferenceError: res is not defined

Any idea?

@jackj93
Copy link

jackj93 commented Mar 22, 2024

@jackj93 this isn't working for me either (v 1.12.1 now). Var isn't being set by the script either when hitting "Get Access Token" button on the Collection Authorization or in making a call that uses inherit authorization.

In the request themselves you have to set the "No Auth"

@jackj93 did you have to install an external module for this to work? When putting the code you mention in the pre request script location on the collection, I just get this error:

Error invoking remote method 'send-http-request': ReferenceError: res is not defined

Any idea?

All the configuration I listed go in the configuration for the collection. do NOT put anything in the request settings
The script is meant to be put in the "Post Response", sorry if that part wasn't clear

@EirikHaughom
Copy link

Thank you @jackj93, it works now! Retrospectively I should've seen in the code that it was going in the post response part.

@clocklear
Copy link
Author

Update: As of v1.11.0 I see that OAuth2 is supported at the collection level, but setting auth to 'inherit' at the request level isn't supported:

image

Using @jackj93 's scripting provides a workaround: we can save the collection token as a variable and use that in requests in the appropriate place (for me, I set an Authorization header with the value Bearer {{oauth2_token}}). Is inherit going to be supported natively in the future without scripting hacks?

pietrygamat added a commit to pietrygamat/bruno that referenced this issue Apr 14, 2024
@pietrygamat pietrygamat linked a pull request Apr 14, 2024 that will close this issue
5 tasks
pietrygamat added a commit to pietrygamat/bruno that referenced this issue Apr 14, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue Apr 15, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue Apr 15, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue Apr 15, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue Apr 16, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue May 5, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue May 5, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue May 5, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue May 5, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue May 5, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue May 6, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue May 7, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue May 7, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue May 7, 2024
@baldursson
Copy link

In addition to the Post Request script by @jackj93, I'm using this Pre Request script on Collection level, then you don't need to add the header manually on each request:

var token = bru.getVar('oauth2_token')
if (token) {
  req.setHeader('Authorization', `Bearer ${token}`)
}

pietrygamat added a commit to pietrygamat/bruno that referenced this issue Jun 21, 2024
@devsales
Copy link

Is there a way to reuse a token across multiple collections?

I have many collections but they use the same OAuth provider. So now I have to get a token for each collection individually, instead of doing it once and reusing it in all collections.

I guess a workaround would be to have only one collection per OAuth provider and group the requests in folders and subfolders.

@danielloader
Copy link

Workarounds aside (which work, thanks for that) is there intention to work on this formally? Debating the pros and cons of waiting on this to be solved upstream and permit inheritance on the collection requests when using Oauth2 instead of injecting a pre-script one every single request.

Thanks

pietrygamat added a commit to pietrygamat/bruno that referenced this issue Jul 26, 2024
@hardiksethi22
Copy link

hardiksethi22 commented Jul 31, 2024

I am taking approach the insomnia way for this

created a request responsible for just fetching the token
and storing the variable in post response

Screenshot 2024-08-01 at 00 12 19

then using the variable in header.

Screenshot 2024-08-01 at 00 12 39

Only friction with this approach is we have to fetch token manually once before using any of the api in our collection.

insomnia saves a little time in this by allowing us to directly use the attribute from some other response. Also it can auto refresh, hoping to see similar feature in bruno as well :)

image

@johnnyggalt
Copy link

Just a suggestion: until such time that the header can be added automatically for OAuth, perhaps this message could point people to this thread:

image

It took me 20 mins to track this down.

pietrygamat added a commit to pietrygamat/bruno that referenced this issue Aug 22, 2024
pietrygamat added a commit to pietrygamat/bruno that referenced this issue Aug 28, 2024
@espada-edalex
Copy link

After applying @jackj93's workaround (thanks for that) requests are fine, however, when attempting to get a new token I'm getting invalid_client errors. I tracked this down to the Authorization header being added, and disabling it allows a new token to be generated. Has anyone had this issue, and possibly got a better way to handle it than manually toggling the header value?

pietrygamat added a commit to pietrygamat/bruno that referenced this issue Sep 23, 2024
@jplutarch
Copy link

The work arounds suggested still seem to require manually clicking the "Get Access Token" on the collection every time the token expires. This isn't great for api's that use short lived tokens. Luckily the client credential flow can be automated fairly simply by adding the following Pre Request script on the collection:

const axios = require('axios');

let token = bru.getEnvVar('access_token_set_by_collection_script');
let tokenExpiration = bru.getEnvVar('access_token_expiration');
let currentTime = (new Date()).getTime();

if (!token || !tokenExpiration || tokenExpiration < currentTime) {
  try {
    console.log("requesting new token");
    const tokenData = (await axios.post(
      bru.getEnvVar('AccessTokenUrl'),
      {
        client_id: bru.getEnvVar('ClientId'),
        client_secret: bru.getEnvVar('ClientSecret'),
        grant_type: 'client_credentials'
      },
      {
        headers: {
          "Content-Type": "application/x-www-form-urlencoded"
        }
      }
    )).data;
    let now = new Date();
    let expiration = (now.setSeconds(now.getSeconds() + tokenData.expires_in - 60)); //Add a minute buffer to expiration time.
    bru.setEnvVar('access_token_set_by_collection_script', tokenData.access_token);
    bru.setEnvVar('access_token_expiration', expiration);
  } catch (error) {
    console.log(error);
  }
} else {
  console.log("using existing token");
}

req.setHeader('Authorization', `Bearer ${bru.getEnvVar('access_token_set_by_collection_script')}`)

This stores the access token and token expiration time in environment variables and checks each request to see if a new token needs to be retrieved. It would be really helpful if the bruno Oauth2 documentation for client credentials provided an example like this to simplify the authentication process.

@clocklear
Copy link
Author

Since the majority of use-cases use the same scripts at this point, is there a reason why this functionality isn't baked into the client?

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

Successfully merging a pull request may close this issue.