Does Google Script have an equivalent to python's Session object? - session

I have this python script and I want to get Google Script equivalent but I do not know how to "pass" whatever needs to be passed between next get or post request once I log in.
import requests
import json
# login
session = requests.session()
data = {
'LoginName': 'name',
'Password': 'password'
}
session.post('https://www.web.com/en-CA/Login/Login', data=data)
session.get('https://www.web.com//en-CA/Redirect/?page=Dashboard')
# get customer table
data = {
'page': '1',
'pageSize': '100'
}
response = session.post('https://www.web.com/en-CA/Reporting', data=data)
print(response.json())
I wonder if there is an equivalent to .session() object from python's requests module. I did search google but could not find any working example. I am not a coder so I dot exactly know that that .session() object does. Would it be enough to pass headers from response when making new request?
UPDATE
I read in some other question that Google might be using for every single UrlFetchApp.fetch different IP so login and cookies might not work, I guess.

I believe your goal as follows.
You want to achieve your python script with Google Apps Script.
Issue and workaround:
If my understanding is correct, when session() of python is used, the multiple requests can be achieved by keeping the cookie. In order to achieve this situation using Google Apps Script, for example, I thought that the cookie is retrieved at 1st request and the retrieved cookie is included in the request header for 2nd request. Because, in the current stage, UrlFetchApp has no method for directly keeping cookie and using it to the next request.
From above situation, when your script is converted to Google Apps Script, it becomes as follows.
Sample script:
function myFunction() {
const url1 = "https://www.web.com/en-CA/Login/Login";
const url2 = "https://www.web.com//en-CA/Redirect/?page=Dashboard";
const url3 = "https://www.web.com/en-CA/Reporting";
// 1st request
const params1 = {
method: "post",
payload: {LoginName: "name", Password: "password"},
followRedirects: false
}
const res1 = UrlFetchApp.fetch(url1, params1);
const headers1 = res1.getAllHeaders();
if (!headers1["Set-Cookie"]) throw new Error("No cookie");
// 2nd request
const params2 = {
headers: {Cookie: JSON.stringify(headers1["Set-Cookie"])},
followRedirects: false
};
const res2 = UrlFetchApp.fetch(url2, params2);
const headers2 = res2.getAllHeaders();
// 3rd request
const params3 = {
method: "post",
payload: {page: "1", pageSize: "100"},
headers: {Cookie: JSON.stringify(headers2["Set-Cookie"] ? headers2["Set-Cookie"] : headers1["Set-Cookie"])},
followRedirects: false
}
const res3 = UrlFetchApp.fetch(url3, params3);
console.log(res3.getContentText())
}
By this sample script, the cookie can be retrieved from 1st request and the retrieved cookie can be used for next request.
Unfortunately, I have no information of your actual server and I cannot test for your actual URLs. So I'm not sure whether this sample script directly works for your server.
And, I'm not sure whether followRedirects: false in each request is required to be included. So when an error occurs, please remove it and test it again.
About the method for including the cookie to the request header, JSON.stringify might not be required to be used. But, I'm not sure about this for your server.
Reference:
Class UrlFetchApp

You might want to try this:
var nl = getNewLine()
function getNewLine() {
var agent = navigator.userAgent
if (agent.indexOf("Win") >= 0)
return "\r\n"
else
if (agent.indexOf("Mac") >= 0)
return "\r"
return "\r"
}
pagecode = 'import requests
import json
# login
session = requests.session()
data = {
\'LoginName\': \'name\',
\'Password\': \'password\'
}
session.post(\'https://www.web.com/en-CA/Login/Login\', data=data)
session.get(\'https://www.web.com//en-CA/Redirect/?page=Dashboard\')
# get customer table
data = {
\'page\': \'1\',
\'pageSize\': \'100\'
}
response = session.post(\'https://www.web.com/en-CA/Reporting\', data=data)
print(response.json())'
document.write(pagecode);
I used this program

Related

Get OAuth 2.0 token for google service accounts

Short explanation
I want to get a Auth2.0 token for access to some APIs in my Google Cloud Platform proyect.
Context
At the current time i have a Wordpress page that has to make the connection. Temporarily i will make a javascript connection with the client via Ajax (when all work successfully i will make this in another way, for example with a PHP server in the middle).
The process that has to execute in our GCP don't need the user to log in with his google account, for that reason we will make a google service account for server to server connections. All the threads executed by the API will be log like be executed by this service account that isn't owned by any real person.
When i generate the Ajax connection for get the token, this will be send to the following URL:
https://oauth2.googleapis.com/token
I send it on JWT coding.
The coded message is generated in this Javascript code:
`
var unixHour = Math.round((new Date()).getTime() / 1000);
var header = {
"alg":"RS256",
"typ":"JWT"
}
var data = {
"iss":"nombreoculto#swift-firmament-348509.iam.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/devstorage.read_only",
"aud":"https://oauth2.googleapis.com/token",
"exp":(unixHour+3600),
"iat":unixHour
}
var secret = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCkhZH7TuaNO4XBVVVcE2P/hvHSsGXNu1D/FcCaMrW56BF/nbOlxAtbp07TCIOyrR1FEcJb+to66olSFnUVUWhWUB9zLbzKpULQoFmYECSWppUbCZd+bp271AFYZpxXFduziWuaG9BNxV2cmWTjLLlZI7FoIYFwLgPZHPWndY0E99lGEjmnH";
function base64url(source) {
// Encode in classical base64
encodedSource = CryptoJS.enc.Base64.stringify(source);
// Remove padding equal characters
encodedSource = encodedSource.replace(/=+$/, '');
// Replace characters according to base64url specifications
encodedSource = encodedSource.replace(/\+/g, '-');
encodedSource = encodedSource.replace(/\//g, '_');
return encodedSource;
}
var stringifiedHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
var encodedHeader = base64url(stringifiedHeader);
//document.getElementById("header").innerText = encodedHeader;
console.log(encodedHeader);
var stringifiedData = CryptoJS.enc.Utf8.parse(JSON.stringify(data));
var encodedData = base64url(stringifiedData);
//document.getElementById("payload").innerText = encodedData;
console.log(encodedData);
var signature = encodedHeader + "." + encodedData;
signature = CryptoJS.HmacSHA256(signature, secret);
signature = base64url(signature);
console.log(signature);
//document.getElementById("signature").innerText = signature;
var jwt = encodedHeader + "." + encodedData + "." + signature;
console.log(jwt);
$.ajax({
url: 'https://oauth2.googleapis.com/token',
type: 'POST',
data: { "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion" : jwt} ,
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
success: function (response) {
alert(response.status);
},
error: function () {
alert("error");
}
});
`
Console:
Console output
The problem
The Ajax message generated in the script return "Invalid JWT signature".
send message API
ajax response API
Following the google documentation, this problem is for a bad coding of the message or a incorrect secret key.
You can see the code for generate the coding message in the previous script.
About the secret key, maybe i am not selecting the correct key for this task, here you have the steps i follow:
cred GCP
Inside the service account, i create a key in the "keys" section:
Keys GCP
As result this download this file:
File keys
I tried to use like secret key the "private_key" content of this file and additionally i tried to delete the line breaks (\n) of this and try again.
¿Is that correct?¿Or i dont use the corret key?
¿Maybe i make an incorrect coding?
*There aren't problems with share the key and account id because the key was disabled at the moment of share this thread and the project is only for testing purposes.

Sapper/svelte3 session not synchronizing without page reload

I'm having trouble getting Sapper to synchronize session changes made in my server-side routes without a pageload. My example scenario is that I load my app with no user in the session, my server-side login route sets the user to the session, and I use goto to got to the dashboard.
The problem is that the session argument in the dashboard's preload function isn't populated. If I use window.location.href = '/dashboard', it is, because it's running through Sapper's page_handler. But if I do a client-only redirect, Sapper isn't sending the updated session to the client.
Any way around this? Am I using my tools wrong?
Note: I'm using connect-pg-simple and express-session, setting up sapper like this: sapper.middleware({session: (req, res) => req.session.public}).
I found my answer in the Sapper docs
session contains whatever data was seeded on the server. It is a writable store, meaning you can update it with new data (for example, after the user logs in) and your app will be refreshed.
Reading between the lines, this indicates that your app has to manually synchronize your session data.
The solution here is to manually sync the session data to the client, either with a webhook connection, a response header, or a key in the response data.
I've got a decorator I use to create a server route handler, in which I add the session data to the response. Here's a simplified version:
const createHandler = getData => (req, res) => {
res.status(200).json({data: getData(req.body), session: req.session.public})
}
Obviously there's more to it than that, e.g. error handling, but you get the idea. On the client, I wrap fetch in a helper function that I always use anyway to get my json, set the correct headers, etc. In it, I look at the response, and if there's a session property, I set that to the session store so that it's available in my preloads.
import {stores} from "#sapper/app"
const myFetch = (...args) => fetch(...args).then(r => r.json()).then(body => {
if (body.session) stores().session.set(body.session)
return body.data
})
To put it simply, after your session status changes from the front end (user just logged in, or you just invalidated his login), you should update the session store on the front end.
<script>
import { goto, stores } from '#sapper/app';
const { session } = stores();
const loginBtnHandler = () => {
const req = await fetch('/api/login', {
method: 'POST',
credentials: 'same-origin', // (im using cookies in this example)
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ ........ })
});
if (req.ok) {
// here is where you refresh the session on the client right after you log in
$session.loggedIn = true; // or your token or whatever
// next page will properly read the session
goto('/');
return;
}
...
}
</script>

Issues sending requests using fetch

I am using FETCH to make GET requests. I am also using NGROK for HTTP tunneling. My problem is here when I use var url = 'http://localhost:9090/test-message', I get a response but when I use
https://c2f2493e.ngrok.io/test-message I don't get a response. I don't know what the problem might be here.
Here is the full code:
fetch(url).then(function(response) {
console.log(response)
})
This url var url = 'http://localhost:9090/test-message ' does not have any Get Method request.
You May try Like this
function myFunction() {
var str = "http://localhost:9090/test-message";
var res = str.split("/");
res = res.reverse();
alert(res[0]); //text-message
}

Angular HttpClientModule Body Syntax Issue

I am trying to make an HTTP request like this:
login(username, password) {
let body = {
userid: username,
password: password
}
let options = {
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded'),
withCredentials: true
};
let request = this.http.post(this.baseUrl, body, options);
request.subscribe();
}
which is returning a 500 internal server error. However, if I modify the body variable to look like this:
login(username, password) {
let body = 'userid=' + username + '&password=' + password;
let options = {
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded'),
withCredentials: true
};
let request = this.http.post(this.baseUrl, body, options);
request.subscribe();
}
it works fine. I have seen the first version used in the documentation, but for some reason it doesn't work this way for me. I'm wondering:
A) Are these statements supposed to be equivalent? Is there a syntax issue? -or-
B) Is there a problem on the backend? In our server log, we're getting something like 'parameter #userIdentifier is expected but not supplied.'
I have to go with the one that works, but I'd like to use the syntax of the first statement if possible. Thanks!
Without more information on the backend or on the specific 500 error message you are receiving, the only suggestion I have is to verify that your back-end schema matches the front-end model. Judging by the limited error message provided, it looks as though you may have mislabeled userid as userIdentifier in the backend.

Dart Language: Authentication and session control (shelf_auth)

I'm developing a Dart application that will need authentication and session control. I'm trying shelf_auth to do that, but the examples doesn't seem to work or, more likely, I'm not implementing them the right way.
In short, this is what I want to happen:
An user opens the application on the browser.
The user enters the login information (login and password), which are POSTED to the server.
If the provided information is valid, the application generates a session code that is passed to the client and stored on the DB (server-side). This code will be sent with every transaction to the server-side.
The package shelf_auth has some examples, but I don't know which one to follow. So my question is: how could I do that with shelf_auth? I'm not asking for anyone to code this for me, but just to point me to the right direction.
EDIT: The example that I was trying out was this: example_with_login_and_jwt_session.dart. Seems that it's lacking CORS headers (this question helped me fixing it) and, even providing valid information, it responds "Unauthorized".
This is how I'm POSTING the information:
import "dart:html";
void main() {
Map _queryParameters = {
"username": "fred",
"password": "blah"
};
var _button = querySelector("#login_button");
_button.onClick.listen((MouseEvent e) {
e.preventDefault();
var requisition = new HttpRequest();
Uri uri = new Uri(path: "http://localhost:8080/login", queryParameters: _queryParameters);
requisition.open("POST", uri.toString());
requisition.setRequestHeader("content-type", "application/x-www-form-urlencoded");
requisition.onLoadEnd.listen((_) {
print(requisition.response.toString());
});
requisition.send();
});
}
I got it working with this client code
import "dart:html";
void main() {
Map _queryParameters = {"username": "fred", "password": "blah"};
var _button = querySelector("#login_button");
_button.onClick.listen((MouseEvent e) async {
e.preventDefault();
var requisition = new HttpRequest();
Uri uri = new Uri(
path: "http://localhost:8080/login/");
requisition.onLoadEnd.listen((_) {
print(requisition.response.toString());
});
HttpRequest request = await HttpRequest.postFormData(
"http://localhost:8080/login/", _queryParameters
//,withCredentials: true
);
print(request.response);
});
}
The example server expects the credentials in the body instead of query parameters and I set withCredentials: true so authentication cookies are sent with the request. Worked without withCredentials.

Resources