this is my jersey server, REST api using java
#POST
#Produces({MediaType.APPLICATION_JSON})
#Path("registration")
public User register(#FormParam("username") String userName, #FormParam("password") String password) {
boolean isOk = true;
User newUser =null;
List<User> userList = em.createNamedQuery("User.findAll").getResultList();
for(User user: userList){
if(user.getUsername().equals(userName)){
isOk = false;
}
}
if(isOk == true){
newUser = new User();
newUser.setUsername(userName);
newUser.setPassword(password);
super.create(newUser);
}
return newUser;
}
I use javascript to POST new user to the server via formdata
buttonLogin.addEventListener('click', (evt) => {
evt.preventDefault();
console.log('login');
const imgData = new FormData();
imgData.append('username', 'newuser');
imgData.append('password', '123');
for (var p of imgData) {
console.log(p);
}
//
let url = endPointUrl + `webresources/users/registration`;
const myHeader = new Headers({'Content-Type':"application/x-www-form-urlencoded"});
fetch(url, {
method: 'POST',
headers: myHeader,
data: imgData
})
.then(json)
.then((data) => {
console.log(data);
});
});
My server did receive formparam but it is null object. I expect that the server will receive username: "newuser" and password "123" but server receive null object
I test server with postman and everything is ok. So I assume that the problem is javascript code.
Could you show me what is wrong with my code. Thank
Related
I'm trying to figure out how to delete information submitted to the firebase database.
I am trying to delete information under the requests. Example
Here are my actions used to fetch the data:
export default {
async contactArtist(context, payload) {
const newRequest = {
userEmail: payload.email,
message: payload.message
};
const response = await fetch(`https://find-artist-d3495-default-rtdb.firebaseio.com/requests/${payload.artistId}.json`, {
method: 'POST',
body: JSON.stringify(newRequest)
});
const responseData = await response.json();
if (!response.ok) {
const error = new Error(responseData.message || 'Failed to send request.');
throw error;
}
newRequest.id = responseData.name;
newRequest.artistId = payload.artistId;
context.commit('addRequest', newRequest);
},
async fetchRequests(context) {
const artistId = context.rootGetters.userId;
const token = context.rootGetters.token;
const response = await fetch(`https://find-artist-d3495-default-rtdb.firebaseio.com/requests/${artistId}.json?auth=` + token);
const responseData = await response.json();
if (!response.ok) {
const error = new Error(responseData.message || 'Failed to fetch requests.');
throw error;
}
const requests = [];
for (const key in responseData) {
const request = {
id: key,
artistId: artistId,
userEmail: responseData[key].userEmail,
message: responseData[key].message
};
requests.push(request);
}
context.commit('setRequests', requests);
},
};
I'm trying to set up a button that will delete the selected request object.
Your code is sending a POST request, which tells Firebase to generate a unique key. From the documentation on saving data:
POST: Add to a list of data in our Firebase database. Every time we send a POST request, the Firebase client generates a unique key, like fireblog/users/<unique-id>/<data>
The delete a node, send the DELETE verb/method to that path:
const response = await fetch(`https://find-artist-d3495-default-rtdb.firebaseio.com/requests/${payload.artistId}.json`, {
method: 'DELETE'
});
I am trying to use data from the client, which they would type into an input box. The idea is to use this for finding in my database to pull the data with the same username. on my Mongo DB:Atlas collection.
So its to use it like this to get the names from the database, .find({"username": request.body})
However, I keep getting the error "CastError: Cast to string failed for value "{ username: '' }" (type Object) at path "username" for model "Db1" on my terminal.
But when I try to hard code it onto the .find({"username": "name"), it works fine. Does anyone have any ideas?
**Javascript app**
async function pullData () {
let clientQ = document.querySelector('#userDB').value;
let entry = {
'username':clientQ
};
const options = {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(entry)
};
const getData = await fetch('/database', options);
const request = await getData.json();
console.log(request);
};
```
-----------------------------------------------------
**Node Server**
app.post('/database', (request,response) => {
const info = request.body;
postModel.find({"username": info}, (error,data) => {
if(error){
console.log(error);
} else {
response.json(data);
}
});
});
----------------------------------------------
***client side DB***
async function pullData () {
let clientQ = document.querySelector('#userDB').value;
let entry = {
'username':clientQ
};
const options = {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(entry)
};
const getData = await fetch('/database', options);
const request = await getData.json();
console.log(request);
Actually, you're passing the object {username : "value"} to the find method. You need to pass the string.
app.post('/database', (request,response) => {
const info = request.body; // object {username : "value"}
const username = info.username; // the string to search by username
postModel.find({"username": username}, (error,data) => {
if(error){
console.log(error);
} else {
response.json(data);
}
});
});
I am writing a javascript program (for a github action) right now but ran into a problem.
I was trying to log into www.overleaf.com and access the page https://www.overleaf.com/project after generating a session cookie by sending a POST request to https://www.overleaf.com/login with my credentials and the csrf token.
The response contained the requested token in the set-cookie header as expected, however, when I tried to access https://www.overleaf.com/project via GET, I get redirected back to https://www.overleaf.com/login
When copying a session cookie saved in my browser, the request works just fine as expected.
I tried doing the same thing in the command line with cURL and it worked there.
I am fairly certain my authentication request is accepted by Overleaf's server, because I have tried intentionally incorrectly sending the password or the csrf token and in both cases, the response does not give me a new session cookie but sends the old one.
If anyone has any clue what is going wrong, I'd be very thankful for your input.
This is what worked in the terminal, which I'm trying to replicate in javascript with node-fetch:
curl -v --header "Content-Type: application/json" --cookie "GCLB=someothercookie;overleaf_session2=firstsessioncookie" --data '{"_csrf":"the_csrf_token", "email": "MYEMAIL", "password":"MYPASSWORD"}' https://www.overleaf.com/login
to get the cookie and csrf token and
curl -v https://www.overleaf.com/project --cookie "overleaf_session2=returnedsessioncookie; GCLB=someothercookie" as the request that returns the html page of my projects.
This is my javascript code, I have double, triple, quadruple checked it but I think I'm missing something.
const fetch = require("node-fetch");
const parser = require("node-html-parser");
const scparser = require("set-cookie-parser");
async function run() {
const email = process.env.EMAIL;
const password = process.env.PASSWORD;
var cookies = await login(email, password);
console.log(await all_projects(cookies));
}
async function login(email, password) {
const login_get = await fetch("https://www.overleaf.com/login");
const get_cookies = login_get.headers.raw()["set-cookie"];
const parsed_get_cookies = scparser.parse(get_cookies, {
decodeValues: false
});
const overleaf_session2_get = parsed_get_cookies.find(
(element) => element.name == "overleaf_session2"
).value;
const gclb = parsed_get_cookies.find(
(element) => element.name == "GCLB"
).value;
console.log("overleaf_session2_get:", overleaf_session2_get, "gclb:", gclb);
const get_responsetext = await login_get.text();
const _csrf = parser
.parse(get_responsetext)
.querySelector("input[name=_csrf]")
.getAttribute("value");
login_json = { _csrf: _csrf, email: email, password: password };
console.log(login_json);
const login_post = await fetch("https://www.overleaf.com/login", {
method: "post",
body: JSON.stringify(login_json),
headers: {
"Content-Type": "application/json",
"Cookie": "GCLB=" + gclb + ";overleaf_session2=" + overleaf_session2_get
}
});
const post_cookies = login_post.headers.raw()["set-cookie"];
const parsed_post_cookies = scparser.parse(post_cookies, {
decodeValues: false
});
const overleaf_session2_post = parsed_post_cookies.find(
(element) => element.name == "overleaf_session2"
).value;
console.log(
"successful:",
overleaf_session2_get != overleaf_session2_post ? "true" : "false"
);
console.log(await fetch("https://www.overleaf.com/project", {
headers: {
"Cookie": "overleaf_session2=" + overleaf_session2_post
}
}))
return "overleaf_session2=" + overleaf_session2_post;
}
async function all_projects(cookies) {
const res = await fetch("https://www.overleaf.com/project", {
headers: {
Cookie: cookies
}
});
return res;
}
run();
Yes your authentication request is probably valid however this is likely to be a security issue which browsers do not allow you to do such thing and freely access another website's cookie.
Browsers do not allow you to access other domain's cookies, If they did then web would be an unsafe place because for example Stackoverflow could access my Facebook account cookie and extract my personal information.
I fixed my issue by not using node-fetch and switching to https.
Here is what worked:
async function login(email, password) {
//GET login page
const get = await get_login();
//get necessary info from response
const csrf = parser
.parse(get.html)
.querySelector(`meta[name="ol-csrfToken"]`)
.getAttribute("content");
const session1 = scparser
.parse(get.headers["set-cookie"], { decodeValues: false })
.find((cookie) => cookie.name == "overleaf_session2").value;
const gclb = scparser
.parse(get.headers["set-cookie"], { decodeValues: false })
.find((cookie) => cookie.name == "GCLB").value;
//POST login data
const post = await post_login(csrf, email, password, session1, gclb);
//get necessary data from response
const session2 = scparser
.parse(post["set-cookie"], { decodeValues: false })
.find((cookie) => cookie.name == "overleaf_session2").value;
//GET new csrf token from project page
const projects = await get_projects(session2, gclb);
const csrf2 = parser
.parse(projects.html)
.querySelector(`meta[name="ol-csrfToken"]`)
.getAttribute("content");
//return data
return {
session: session2,
gclb: gclb,
csrf: csrf2,
projects: projects.html
};
}
async function get_login() {
const url = "https://www.overleaf.com/login";
return new Promise((resolve) => {
https.get(url, (res) => {
var data;
res.on("data", (chunk) => {
data += chunk;
});
res.on("end", () => {
resolve({ html: data, headers: res.headers });
});
});
});
}
async function get_projects(session2, gclb) {
const url = "https://www.overleaf.com/project";
return new Promise((resolve) => {
https.get(
url,
{ headers: { Cookie: `GCLB=${gclb};overleaf_session2=${session2}` } },
(res) => {
var data;
res.on("data", (chunk) => {
data += chunk;
});
res.on("end", () => {
resolve({ html: data, headers: res.headers });
});
}
);
});
}
async function post_login(_csrf, email, password, session1, gclb) {
const url = "https://www.overleaf.com/login";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Cookie: `GCLB=${gclb};overleaf_session2=${session1}`
}
};
const postData = {
_csrf: _csrf,
email: email,
password: password
};
return new Promise((resolve) => {
var req = https.request(url, options, (res) => {
resolve(res.headers);
});
req.on("error", (e) => {
console.error(e);
});
req.write(JSON.stringify(postData));
req.end();
});
}
I have this code that sends a username and password to a local API (it's http at the moment since I'm developing it still and it's not on a server yet). However the data returned is just the response code, instead of the body of the response which is meant to contain an auth-token.
This is the Client-code (my app in SwiftUI):
func login(username:String, password:String){
guard let url = URL(string: "http://localhost:3000/users/login") else { print("URL error"); return }
var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10)
let headers = [
//"auth-token": "auth-token goes here",
"accept": "string",
"content-type": "application/json"]
let body = [
"username": username,
"password": password]
do{
let dataToSend = try JSONSerialization.data(withJSONObject: body, options: .fragmentsAllowed)
request.httpBody = dataToSend
}catch{
print("Error creating data object")
return
}
request.allHTTPHeaderFields = headers
request.httpMethod = "POST"
let session = URLSession.shared
let dataTask = session.dataTask(with: request) { (data, response, error) in
// Check for erros
if error == nil && data != nil{
// Try parse out data
print(data)
do {
let dictionary = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String:Any]
print(dictionary)
}
catch{
print("Error parsing response data")
}
}
}
dataTask.resume()
}
When I print out the data response before I try and put it in a dictionary I get this:
Optional(200 bytes)
I get the response code instead of the body of the response (which is json), why?
This is my server-side code:
router.post('/login', async (req,res) => {
// Validate before we login user
const { error } = loginValidation(req.body);
if (error) return res.status(400).send(error.details[0].message);
// Checking if the user exists
const user = await User.findOne({username: req.body.username});
if(!user) return res.status(400).send("Invalid username")
// Check if password is correct
const validPass = await bcrypt.compare(req.body.password, user.password);
if(!validPass) return res.status(400).send("Invalid password")
console.log(req.body);
// User is logged in provide them with a token
const token = jwt.sign({
_id: user._id,
_username: user.username
}, "SECRET_KEY", { expiresIn: '1h' });
res.status(200).header('auth-token', token).send(token);
});
The data doesn't seem to contain a valid JSON, it's the reason your code doesn't print out the dictionary that you tried to parse out. Here's how you find the response data:
if let data = data {
do {
let dictionary = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:Any]
print(dictionary)
} catch {
print("Error parsing response data: \(String(decoding: data, as: UTF8.self))")
}
}
I'm trying to authenticate to an API via fetch. For that, I'm using an encrypted username and password. The problem is that no matter what I do, the response I get from the API is that my password is invalid. I know the password works because it was provided by my admins.
This is the code I'm using:
import CryptoJS from 'crypto-js';
import CryptoJSAesJson from './helpers/helpers';
var username = 'myusername';
var pass = 'mypassword';
var hash = CryptoJS.SHA1(username).toString();
var password = CryptoJS.AES.encrypt(JSON.stringify(pass), 'mypassphrase', {format: CryptoJSAesJson}).toString();
var credentials = {
user: hash,
password: password
}
fetch("https://demo.mediainfo.com/api/user/login", {
body: JSON.stringify(credentials),
headers: {
"Content-Type": "application/json"
},
method: "POST"
}).then(response => {
// do something with the response
});
On helpers.js I have this code:
var CryptoJSAesJson = {
stringify: function (cipherParams) {
var j = {ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)};
if (cipherParams.iv) j.iv = cipherParams.iv.toString();
if (cipherParams.salt) j.s = cipherParams.salt.toString();
return JSON.stringify(j).replace(/\s/g, '');
},
parse: function (jsonStr) {
var j = JSON.parse(jsonStr);
var cipherParams = CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Base64.parse(j.ct)});
if (j.iv) cipherParams.iv = CryptoJS.enc.Hex.parse(j.iv);
if (j.s) cipherParams.salt = CryptoJS.enc.Hex.parse(j.s);
return cipherParams;
}
}
export default CryptoJSAesJson;
Unfortunately the API documentation is null so I'm not sure what could be the problem, the only message I get when fetching is: "Wrong password exchange. Please contact administrator."
Thanks!