How to share cookie for all request for an user in locust? - locust

I'd like to share the _profiler cookie for all request for an user, anyway to do this in locust?
self.client.post(
"/customer/account/loginPost/bind/no/",
headers = headers,
data = {
'login[username]': email,
'login[password]': password,
'form_key': form_key
},
cookies={
'_profiler': True
}
)
//Another request in another task, I hope the `_profiler` cookies exists here.
self.client.get('/customer/section/load?sections=cart&force_new_section_timestamp=false',headers=headers)

I think that it's related to this:
How to configure or set cookie as json before making a post request in locust load test tool for FastHTTPUser
You could use the same approach

Related

How to store JWT's in cookies with FastApi?

I am creating a basic Login system with FastApi, React and MongoDb.
I want to store the JWT's in cookies, but nothing worked for me and i really don't want to store them in LocalStorage...
Can someone please tell me what's wrong with my code?
#app.post("/login")
async def login(response:Response,data: OAuth2PasswordRequestForm=Depends()):
username = data.username
password = data.password
user = await query_user(username)
if not user:
raise InvalidCredentialsException
if not verify_password(password,user["password"]):
raise InvalidCredentialsException
access_token = accessToken.create(user)
refresh_token = refreshToken.create(user)
response.set_cookie(key="access_token",value=f"Bearer {access_token}", httponly=True)
response.set_cookie(key="refresh_token",value=f"Bearer {access_token}", httponly=True)
return response
This is pretty easy. In my case, once the user logs in successfully, I redirect to dashboard and then set the token in the cookies.
#app.post('/token', tags=["authenticate"])
async def login_for_access_token(response:Response, request_form: OAuth2PasswordRequestForm = Depends()):
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
token = await token_generator(request_form.username, request_form.password,
expires_delta=access_token_expires)
response = RedirectResponse(url='/api/v1/dashboard', status_code=status.HTTP_303_SEE_OTHER)
response.set_cookie(key="access_token", value=f"Bearer {token[0]}", httponly=True)
return response
My token consists of both the access_token and user_id keys, hence the token[0]. As you will notice, the 'httponly' flag is set to True. This is a security feature as there is no way to access anything about the HttpOnly cookies from "non-HTTP" APIs, e.g. JavaScript. By design, neither reading nor writing such cookies is possible. HttpOnly header flag became a standard, defined in section 5.2.6 of RFC6265, with the storage semantics described in the same document (look for "http-only-flag" throughout the RFC text). Hope this helps, good luck!

Salesforce Rest API call from typescript using axios

I am trying to fetch records from a scratch org using the tooling API provided by salesforce and user access token. Lets say
accesstoken = "abcd"
url = "https://example.my.salesforce.com/services/data/v49.0/tooling/query?q=SELECT+Id,Name+FROM+Account"
I have used axios node module to make the API call as given below
const options = {
headers: {
"Authorization": "Bearer " + accessToken,
"Content-Type": "application/json"
}
};
axios.get(url, options).then(response => {
console.log(response.status);
if(response.status == 200){
console.log(response.data);
} else {
//do something else
}
});
The call responds with a status 200 i.e the request provided a response. But instead of correct records from Account object, I get the login html page
' Login | Salesforcehtml{visibility:
hidden;}a{color:#0070d2;}body{background-color:#F4F6F9;}#content,.container{background-color:#ffffff;}#header{color:#16325c;}body{display:
table;
width:100%;}#content{margin-bottom:24px;}#wrap{height:100%;} html { visibility: hidden; } if (self == top)
{document.documentElement.style.visibility = 'visible';} else
{document.write = ''; top.location = self.location;
setTimeout(function(){document.body.innerHTML='';},
1);window.self.onload=function(evt){document.body.innerHTML='';};}var
SFDCSessionVars={"server":"https://test.salesforce.com/login/sessionserver212.html","im":true,"ah":"active","save":"Save","saveOne":"Save
1 Change","sum":"#p# Saved Usernames","iaac":false,"hac":"Choose a
Username","suo":"1 Saved Username","title":" |
Salesforce","saveMany":"Save #p#
Changes","lpt":"Login","lllbl":"Lightning
Login","host":"test.salesforce.com","le":false,"heu":"Edit Username
List","ic":false,"lh":false,"ur":"https://business-data-8148-dev-ed.cs79.my.salesforce.com","hidp":"Log
In Using","ih":"inactive","dc":"Username removed. Click Save to Commit
Changes."};LoginHint.hideLoginForm();Edit ListSaveCancel
UsernamePassword Caps Lock is on.Remember
meForgot Your
Password?To go to your company's login
page, enter the custom domain name.Custom Domainhttps://domain.my.salesforce.comContinueBackLog In with a Different
Username© 2020
salesforce.com, inc. All rights reserved.<iframe frameborder="0" src="/s.gif" id="marketing"
name="marketing" scrolling="no" title="Marketing"
tabindex="-1"sandbox="allow-forms allow-pointer-lock allow-popups
allow-same-origin allow-scripts" >LoginLoginHint.getSavedIdentities(false);function
handleLogin(){document.login.un.value=document.login.username.value;document.login.width.value=screen.width;document.login.height.value=screen.height;document.getElementById("Login").disabled=true;document.getElementById("login_form").submit();}function
lazyload(){document.getElementById("pwcapsicon").src="/img/icon/capslock_blue.png";document.getElementById("marketing").src="https://c.salesforce.com/login-messages/promos.html";}loader();
'
Does anyone know what am I missing in here? According to salesforce documentation
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_query.htm
the accessToken in the header should be enough to make the API call.
Note: I gained the access token by running
sfdx force:user:display -u <username>
Your query is wrong. You selected Tooling API service which is for metadata (info about classes, triggers, objects, fields, deployments, running unit tests...). If you want to query Accounts - that's normal data. Try just /services/data/v49.0/query?q=SELECT+Id,Name+FROM+Account
I don't think you need Content-Type header in there. You don't POST anything. At best you can send Accept (application/json, application/xml)
Are you sure the session id was valid? As in you could go to the org, Setup -> Session management, see it there? Or in the user's login history?
It might be that your SF admin did something nasty like locking sessions down to IP from which they originated or maybe the user doesn't have API access... See if you can create your call in Workbench -> Utilities -> REST Explorer first, then go back to Axios?

Not able to set generated access_token in request object

I am authenticating user with the help of JWT token and #nestjs/passport library. I am able to successfully generate and return the access token but stuck at how to set it in the req object. So that I can validate other api routes until user logs out
Below code shows how I generated the access_token and returned to the calling point
let payload = { username: user.email, sub: user.id }
const accessToken = this.jwtService.sign(payload);
return {
expires_in: 3600,
access_token: accessToken,
status: 200
}
I am getting the access_token correctly. I verified generated access_token using https://jwt.io/ debugger and results were correct.
Can someone help me in setting up the req object with access_token?
There is multiple way you could send JWT token in your requests. If you have followed this tutorial: https://docs.nestjs.com/techniques/authentication, you are using passport-jwt library for JWT. One way is through header if you don't set auth schema it will be this one:
Authorization: JWT <-HERE YOU SHOULD INSERT TOKEN->
If you set authSchema to be bearer, then you could use this header like this:
Authorization: BEARER <-HERE YOU SHOULD INSERT TOKEN->
Except for that you can put your JWT into URL like this:
https://example.com/me?auth_token=<-HERE YOU SHOULD INSERT TOKEN->
Or in object body that you are sending with property named auth_token:
https://example.com/me
Body:
{
auth_token: <-HERE YOU SHOULD INSERT TOKEN->
}
You can find this in the source code of passport-jwt in this file.

Gatling-tool Extracting cookie data

I'm currently writing a test simulation with gatling and I've hit a brick wall. One of my post requests has an odd requirement. the request is:
.post("/checkout/cart/add/product/form_key/")
This post request wont complete with appending the form key on the end of the URL, the form key is stored in a cookie called: CACHED_FRONT_FORM_KEY
I need a way to grab the value in that cookie from the gatling cookiejar and to be used in the post request as follows:
.post("/checkout/cart/add/product/form_key/${FORM_KEY}")
I have done some googling and found a similar request:
https://groups.google.com/forum/#!topic/gatling/gXosGVnUuZA
But I'm unsure of how to implement this into a simulation file, I'm currently using gatling 1.4.3. Any assistance would be most appreciated.
Using the Gatling 2 API, you can access cookies as follows:
.exec( session => {
import io.gatling.http.cookie._
import org.asynchttpclient.uri._
import io.netty.handler.codec.http.cookie.ClientCookieDecoder.LAX.decode
val cookies = session("gatling.http.cookies").as[CookieJar].get(Uri.create("https://www.someSite.com"))
// for (ck <- cookies ) {
// val cc = decode(ck.toString())
// println(s"${cc.name} === ${cc.value}");
// }
val ck = cookies.filter( cookie => decode(cookie.toString()).name == "CookieName")
println(decode(ck.toString()).value)
session
})
Uncomment the iterator to view all the cookies in the current session
You can use a regexHeader check on the Set-Cookie reponse header in order to capture the cookie value.
Don't have enough rep to comment, so I'll add another answer.
For this Magento scenario I needed the form key, but using headerRegex("Set-Cookie","CACHED_FRONT_FORM_KEY=(.*)").saveAs("formkey") would return a value like
1Nt86VNYoPP5WUtt; path=/; domain=example.com
By using the following regex, I was able to extract just the 1Nt86VNYoPP5WUtt value
headerRegex("Set-Cookie","CACHED_FRONT_FORM_KEY=([^;]+)").saveAs("formkey")
I then used it in my HTTP Post like
http("add_to_cart")
.post("/checkout/cart/add/product/12345")
.formParam("form_key", "${formkey}")
Using the HTTP Helper getCookieValue is another way to grab cookie data:
// add cookie to the session as CACHED_FRONT_FORM_KEY
.exec(getCookieValue(CookieKey("CACHED_FRONT_FORM_KEY")))
.exec { session =>
println(session("CACHED_FRONT_FORM_KEY").as[String]) // `.as[]` unwraps the value from the session object
session
}
.post("/checkout/cart/add/product/form_key/${CACHED_FRONT_FORM_KEY}")
Sources
Gatling HTTP Helpers
Gatling Debugging

Google OAuth 2.0 redirect_uri with several parameters

How to add a parameters to the Google OAuth 2.0 redirect_uri?
Just like this:
redirect_uri=http://www.example.com/redirect.html?a=b
The b of a=b is random.
Anyone can help ?
You cannot add anything to the redirect uri, redirect uri is constant as set
in the app settings of Oauth.
eg :http://www.example.com/redirect.html
To pass several parameters to your redirect uri, have them stored in state
parameter before calling Oauth url, the url after authorization will send the same parameters to your redirect uri as
state=THE_STATE_PARAMETERS
So for your case,do this:
/1. create a json string of your parameters ->
{ "a" : "b" , "c" : 1 }
/2. do a base64UrlEncode , to make it URL safe ->
stateString = base64UrlEncode('{ "a" : "b" , "c" : 1 }');
This is a PHP example of base64UrlEncoding & decoding (http://en.wikipedia.org/wiki/Base64#URL_applications) :
function base64UrlEncode($inputStr)
{
return strtr(base64_encode($inputStr), '+/=', '-_,');
}
function base64UrlDecode($inputStr)
{
return base64_decode(strtr($inputStr, '-_,', '+/='));
}
So now state would be something like: stateString -> asawerwerwfgsg,
Pass this state in OAuth authorization URL:
https://accounts.google.com/o/oauth2/auth?
client_id=21302922996.apps.googleusercontent.com&
redirect_uri=https://www.example.com/back&
scope=https://www.google.com/m8/feeds/&
response_type=token&
state=asdafwswdwefwsdg,
For server side flow it will come along with token :
http://www.example.com/redirect.html?token=sdfwerwqerqwer&state=asdafwswdwefwsdg,
For client side flow it will come in the hash along with access token:
http://www.example.com/redirect.html#access_token=portyefghsdfgdfgsdgd&state=asdafwswdwefwsdg,
Retrieve the state, base64UrlDecode it, json_decode it, and you have your data.
See more about google OAuth 2 here:
http://code.google.com/apis/accounts/docs/OAuth2.html
Since the accepted answer does expose the actual data and misuses the state parameter instead of sticking to a nonce to protect against CSRF, I'll try to show a proper method. Rather than passing (read exposing) data it should be kept local. Hydrate it before the request and re-hydrate it after a validated request. "Validated" here means that the state-nonce of request and response match.
You need some kind of temporary client side storage. E.g. for SPA or general websites keep it in state or use the browser's localStorage, a session (or a signed cookie). For mobile apps they should use memory or any other local storage.
Before sending the request generate a nonce (see below) that will be used as state parameter for the request. Store the nonce together with the custom state (e.g. a json) in local storage.
For example, the nonce could be ih4f984hf and the custom state {"role": "customer"}. Then you could store data for re-hydration for that request like this:
"ih4f984hf": {
"role": "customer"
}
Then use only the nonce as value for the state parameter of the request. (If you absolutely want to combine the nonce and data into the state value be sure to encrypt it and be aware that the length of the value is limited!)
When receiving a response you get the value of the state parameter back. Look it up and if it matches the value in the local storage you may process the data using the stored state. If the nonces do not match the request is potentially from an attacker and should not be processed.
Generating the nonce
Remember that the nature of a nonce is that it is used once only and must be unpredictable! Unpredictable here means ideally random, but practically pseudo-random is ok if the entropry is high enough - in web apps you might want to check Web API Crypto which is supported pretty well.
For further readings this might be helpful:
http://www.thread-safe.com/2014/05/the-correct-use-of-state-parameter-in.html
https://datatracker.ietf.org/doc/html/draft-bradley-oauth-jwt-encoded-state-00
https://auth0.com/docs/protocols/state-parameters#set-and-compare-state-parameter-values
If you are in .NET you could save the parameters in the Session
HttpContext.Current.Session[{varname}]
and redirect to the authorization page without parameters
Response.Redirect(your_uri_approved_with_no_querystring_parameters);
In Javascript (Node), you could set the state property to an object of key value pairs.
const oAuth2Client = await new google.auth.OAuth2(
clientId: <clientId>,
clientSecret: <clientSecret>,
redirectUrl: <redirectUrl>,
);
return await oAuth2Client.generateAuthUrl({
access_type: "offline",
scope: <scopes>,
state: JSON.stringify({ a: "y", b: "z" }),
});
On google authorization complete, it returns of the state, code etc from ulr,
const params = JSON.parse(state); // { a: "y", b: "z" }
You can redirect parameter with url as below,
When you get response from google than you can pass parameter with url,
See below php code for same,
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL) . '?r=page/view');
}
In above example r=page/view is parameter on which i want the response with parameter