usebruno / bruno

Opensource IDE For Exploring and Testing Api's (lightweight alternative to postman/insomnia)
https://www.usebruno.com/
MIT License
27.86k stars 1.29k forks source link

Unable to set either env or collection variables via collection level Pre Request script #2266

Open XDIJK opened 6 months ago

XDIJK commented 6 months ago

I have checked the following:

Describe the bug

OS & Version

OS: Ubuntu 22.04.4 LTS Bruno version: V1.17.0 deb pkg

I've been attempting to set any form of variable via a collection level Pre Request script and am seemingly unable to do so. unsure if I am missing something obvious or it is simply not working.

The variable neither can be interpolated in any request nor is it visibly set in the Bruno variables tab. This was tested both on 1.16.x & on 1.17.0

Similar issue can be found here however none of the work arounds seemed to have worked for me: https://github.com/usebruno/bruno/issues/1019

Likewise I found some odd behaviour where the request level Post Request script finishes before the Pre Request script does most likely related to some odd async axios behaviour.

Furthermore I have also tried to write the script without async functions and simply awaiting the response of the POST request which simply does not execute the POST not sure what is going on there.

I've also tried creating or removing the variables and letting the script instantiate them but no combination of any of it seems to work.

Pre Request script

const axios = require('axios');

var url = "https://cognito-idp.eu-central-1.amazonaws.com/";
var clientId = bru.getEnvVar("cognitoClientId");
var username = bru.getEnvVar("cognitoUserName");
var password = bru.getEnvVar("cognitoUserPassword");

async function getBearer() {
    const response = await axios.post(url, {
        "AuthParameters": {
            "USERNAME": username,
            "PASSWORD": password
        },
        "AuthFlow": "USER_PASSWORD_AUTH",
        "ClientId": clientId
    }, {
        headers: {
            'X-Amz-Target': 'AWSCognitoIdentityProviderService.InitiateAuth',
            'Content-Type': 'application/x-amz-json-1.1'
        },
    })
    return response.data
}

async function main() {
   const bearerRes = await getBearer()
    bru.setVar("cognitoAccessToken", bearerRes.AuthenticationResult.AccessToken);

    bru.setVar("cognitoIdToken", bearerRes.AuthenticationResult.IdToken);

  console.log(bru.getVar("cognitoAccessToken")) //Logs successfully using either using .getEnvVar or .getVar
}

main()

Pre Request script without functions as in documentation:

const axios = require('axios');

var url = "https://cognito-idp.eu-central-1.amazonaws.com/";
var clientId = bru.getEnvVar("cognitoClientId");
var username = bru.getEnvVar("cognitoUserName");
var password = bru.getEnvVar("cognitoUserPassword");

console.log("Start") //executes
    const response = await axios.post(url, {
        "AuthParameters": {
            "USERNAME": username,
            "PASSWORD": password
        },
        "AuthFlow": "USER_PASSWORD_AUTH",
        "ClientId": clientId
    }, {
        headers: {
            'X-Amz-Target': 'AWSCognitoIdentityProviderService.InitiateAuth',
            'Content-Type': 'application/x-amz-json-1.1'
        },
    });

console.log("Does not exec", response) //Doesn't execute

bru.setVar("cognitoAccessToken", response.data.bearerRes.AuthenticationResult.AccessToken);

    bru.setVar("cognitoIdToken", response.data.AuthenticationResult.IdToken);

  console.log(bru.getVar("cognitoAccessToken"))

.bru file to reproduce the bug

No response

Screenshots/Live demo link

brun-env-tab bruno-collection-pre-request bruno-pre-request bruno-request-timeline

jwsloan commented 6 months ago

I just got Cognito auth working myself. I ran into some strange issues for a while, and then it worked. I'm not sure what I did that finally made it successful.

The setup below also works for the schema introspection call if your API is in AppSync and authenticated via Cognito. Initially I was setting the header directly on the req object in the script, but that only worked for the actual API call. It did not work for the introspection call.

Here is the Pre-Request script I'm using:

 const axios = require('axios');

  const url = 'https://cognito-idp.us-east-1.amazonaws.com/';
  const headers = {
    'Content-Type': 'application/x-amz-json-1.1',
    'X-Amz-Target': 'AWSCognitoIdentityProviderService.InitiateAuth'
  };
  const data = {
    "AuthFlow": "USER_PASSWORD_AUTH",
    "AuthParameters": {
      "USERNAME": bru.getEnvVar("username"),
      "PASSWORD": bru.getEnvVar("password")
    },
    "ClientId": bru.getEnvVar("userPoolClientId")
  };

  response = await axios.post(url, data, { headers })

  bru.setVar("authorizationToken",response.data.AuthenticationResult.IdToken)

I think set the Collection level headers:

image
jwsloan commented 6 months ago

@XDIJK if this works for you, I'll see about making a contribution updating some docs about authenticating with Cognito.

XDIJK commented 6 months ago

@jwsloan Thanks for the response, the actual cognito call is working just fine and as far as I can see/understand the you posted snippet above doesn't really differ from the scripts I posted.

Other than on my end await directly on the call vs via function not working at all.

However on the first script in the parent post the I am getting a valid authToken back from cognito it is the variable assignment which is failing/not happening.

KevUp commented 6 months ago

I am experiencing the same issue as @jwsloan. Running a collection Pre Request script. the script is getting an auth token, all working fine apart from when I try to set a variable with either:

bru.setEnvVar("access_token", ${access_token}); bru.setVar("access_token", access_token);

neither work!

jwsloan commented 6 months ago

A couple of questions to consider, @KevUp @XDIJK

  1. How are you accessing the variable after setting it?
  2. Have you tried setting a header on the request directly instead?
    • This worked for me for the actual API request, but it did not work for the introspection call.
KevUp commented 6 months ago

Bruno v1.17.0 This is part of the code it getting a authentication JWT to use on API calls:

const axiosInstance = axios.create({
  baseURL: tokenUrl,
  headers: {
    "content-type": "application/json",
    "api_key": api_key,
  },
 });

const body = { 
  userName: user,
  password: password
};

axiosInstance.post('', body).then(response => {
  const access_token = response.data['id-token'];
  console.log('Authentication successful!');
  console.log('Access token:', access_token);

  // Use the access token for subsequent API requests
  bru.setEnvVar("access_token", access_token);

})
.catch(error => {
console.error('Authentication failed:', error);
});

and this is the response, so I know the call is good:

image

and this is how I am accessing the collection var in my subsequent calls :

image
XDIJK commented 6 months ago

@jwsloan Rather odd update it just started working without any changes made nor an update of Bruno. Scripts are the exact same as in the original post.

So on my end it is inexplicably working right now.

To answer your question above however: As in how I access the var the same as @KevUp above but using setVar() instead of setEnvVar() I did not try setting it directly on the request.

technodrome commented 5 months ago

I have the same issue. Tokens are printed correctly in the dev console but I cannot use the variable in the Auth tab in {{token}} format at all. https://github.com/usebruno/bruno/issues/2358#issuecomment-2147874883

Env vars seem to me broken in 1.18.1.

carlosgarciasilac commented 5 months ago

I think there's a race condition between the setting of the variable and the use of the variable in the execution of the request. I switched from using the promise().then().catch() syntax to await and then synchronously set the var and now it works for me in version 1.18.0.

eyalyoli commented 4 months ago

using async and wait worked for me on v1.21 on Mac

guplem commented 4 months ago

Awaiting seems to work for me. This is my code in case it helps:

const axios = require('axios')

const baseUrl = bru.getEnvVar("baseUrl")
const axiosInstance = axios.create({
  baseURL: baseUrl + "auth/",
  headers: {
  'Content-Type': 'application/x-www-form-urlencoded',
  },
});

const data = {
  "phone": bru.getEnvVar("authPhone"),
  "phonePrefix": "+34",
  "language": "es"
}

axiosInstance.post('requestPhoneValidation', data)
.catch(error => {
console.error('Authentication failed:', error);
});

const loginData = {
  "token": bru.getEnvVar("smsCode"),
  "id": bru.getEnvVar("authPhone"),
  "data": "+34",
  "type": "phone",
}

const response = await axiosInstance.post('login', loginData).catch(error => {
console.error('Authentication failed when login:', error);
});

const accessToken = response.data.tokens.token;
console.log(accessToken)
await bru.setVar("token", accessToken)

console.log("Token variable set")
gowriter commented 1 month ago

In my case it didn't work because i did't selected the fitting environment :)