Wrong credentials in REST fetch with multiple users per session - reactjs

I have a webapp (using react, redux) that fetchs data via REST. Everything works fine as long as I'm only logging in one user per session. If I'm logging in multiple users at once using the same browser, in the BE (java with spring) the wrong principal (always the principal for the latest logged in user) is received.
How I can send the correct credentials for each user?
FE:
public restPost(url: string, request: any): Rx.Observable<any> {
return Rx.Observable.create(
(observer: Rx.Observer<any>) => {
fetch(url, {
method: 'POST',
mode: 'cors',
credentials: 'include',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(request)
}).then((response: Response) => {
// handle response
})
.catch(error => observer.error(error));
}
);
}
BE:
#RequestMapping(value="/test", method = RequestMethod.POST)
#CrossOrigin(origins = "*")
public ResponseEntity<Test> test(#RequestBody TestRequest testReq, HttpServletResponse response, #AuthenticationPrincipal Principal principal) {
// at this point the principal.getName() has the name of the latest logged in user
// return the response
}

My solution (only working because I have also have a websocket connection):
added a bearer token to the REST headers in the FE:
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: header ? ('Bearer ' + header.token) : ''
}
In the BE I saved a map with token to principals which I could then access for REST messages

Related

How do I make a post request from react.js front end to flask backend that sends data but also grabs data?

I am posting a user id to the backend route /stat. In /stat I want to perform a query that takes in user id as a parameter. Then I also want to get the result of the query in the front end so I can display the value. I understand how to make a post request that successfully sends the data, but how do I program it to also grab data?
my post request on the front end looks like this:
const postData = (username) => {
try {
let result = fetch('http://127.0.0.1:5000/stat', {
credentials: 'include',
method: 'POST',
mode: 'no-cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
user: username
})
});
} catch(e) {
console.log(e)
}
}
and my backend route /stat looks like this:
#app.route('/stat', methods=['GET', 'POST'])
def stats():
request_data = request.get_json()
user = request_data['user']
def get_total_percent_correct(user):
correct = d.db_query('SELECT COUNT(*) FROM cards.responses WHERE guess = answer AND user_id = %s' % user)
total = d.db_query('SELECT COUNT(*) FROM cards.responses WHERE user_id = %s' % user)
return float(correct[0][0])/float(total[0][0])
response_body = {
"totalAccuracy": get_total_percent_correct(user),
"user" : user
}
return response_body
You need to get the response from the fetch call. If you send JSON from the backend this is how it would look:
fetch('http://127.0.0.1:5000/stat', {
credentials: 'include',
method: 'POST',
mode: 'no-cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
user: username
})
})
.then(function(response) {
console.log(response.json())
})

Cannot generate embed token using access token in power bi

I'm trying to be understand authorization mechanism in power bi API
I would embed a report in my web app.
I have done the steps as mentioned in docs
Actually I would get report embedded url then use power bi JS API to embed the report.
Getting access_token is successful
var options = {
'method': 'POST',
'url': `https://login.microsoftonline.com/${process.env.TENANT_ID}/oauth2/token`,
'headers': {
'Content-Type': 'multipart/form-data'
},
formData: {
'grant_type': process.env.GRANT_TYPE,
'client_id': process.env.CLIENT_ID,
'client_secret': process.env.CLIENT_SECRET,
'resource': "https://analysis.windows.net/powerbi/api",
'Scope': "https://analysis.windows.net/powerbi/api/.default"
}
};
Now I try to get embedded token for report in group
var data = { accessLevel: "View", datasetId: "5b11d62a-803e-46c9-83f3-*****" };
var config = {
method: 'post',
url: `https://api.powerbi.com/v1.0/myorg/groups/${process.env.GROUP_ID}/reports/${process.env.Report_ID}/GenerateToken`,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${JSON.parse(response).access_token}`
},
data: data
};
let embedtoken
try {
embedtoken = await axios(config)
}
catch (e) {
console.log(e)
}
context.res = {
// status: 200, /* Defaults to 200 */
body: JSON.parse(response).access_token
};
I get error 400 response
But When I generate an embed token for dashboard I get a valid token. But of course that's not working with get report API
My goal is to get report infos. For information I get get that using the access token but it's not safe
For POST API requests, data should be passed in string format. This can be done by using for example, JSON.stringify(data).
Refer below code snippet which should resolve the error.
var config = {
method: 'post',
url: `https://api.powerbi.com/v1.0/myorg/groups/${process.env.GROUP_ID}/reports/${process.env.Report_ID}/GenerateToken`,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${JSON.parse(response).access_token}`
},
data: JSON.stringify(data) };

React native - FETCH - Authorization header not working

I made a server query via an app developed using react-native. I used fetch API and it turns out any query with authorization header not working. POST and GET method REQUESTS that don't expect Authorization headers at the server side works well. Some Queries at the server side are protected with authorization and when I make such queries including authorization header, I always get '401:unauthorized' error.
But such queries works well with POSTMAN. Any suggestions here would be of great help.
getThingsApi() {
let uri = "https://example.com/things/";
let req = {
method: "GET",
credentials: "include",
//mode: "no-cors",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
//'Access-Control-Request-Method': 'GET',
//'Access-Control-Request-Headers': 'origin, x-requested-with',
'Origin': '',
'Host':'example.com',
'authorization': 'Basic '+Base64.btoa('aaa:bbb'),
'Cache-Control': 'no-cache'
}
};
fetch(uri, req)
.then(response => response.json())
.then(responseJson => {
console.log("ResponseAxis::" + JSON.stringify(responseJson));
console.log("ResponseAxis::" + JSON.stringify(responseJson));
alert("ResponseAxis::" +JSON.stringify(responseJson));
})
.catch(error => {
console.log("Error::" + JSON.stringify(error));
});
}
Issue is fixed. We used Fetch API and fetch Api converts all headers into lower-case(eg: authorization) and the server side expects upper-case starting letter(eg: Authorization). After changing the server side code to be case-insensitive, everything works fine.

What is the best way to enable CORS in React Application?

There are different ways to make a REST call in react-
e.g
axios.post('link', JSON.stringify(data1),
{
headers: {"content-type" : "application/json", "Access-Control-Allow-Origin" : "*"}})
.then(response => {
console.log("res:", response)
})
.catch(err =>{
console.log(err)
})
}
OR
fetch('http://localhost:8080/feedbacks/addfeedback', {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin' : '*'
},
body:body
What is the most effiecient way to enable CORS.
Is there any other way that I can do this either in frontend or backend?
It depends on what HTTP library you are using.
See What is difference between Axios and Fetch?.
I usually use Axios, next what i do is creating a global instance and configuring Axios once.
export const api = axios.create({
baseURL: '_URL_',
timeout: 1000,
withCredentials: false,
responseType: 'json',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*' // whatever you want
}
});
// You can add common headers later
api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
Also i'm enabling CORS on my server side application.
Thanks to #henrik123 for good explanation:
The browser is going to see that some Javascript request has tried to initiate a request to a different domain, subdomain or port than what the browsers is currently at. If any of these things are different, the CORS kicks in. Doesn't matter if you use Axios, Fetch or any other other library

Http request in angular send undefine values

** It turns out that the problem was at the server **
I'm trying to excute HTTP post request (from my angular client) to my server (node express). The server recive the request but the data is undefined.
Already tried to make this req by postman and it worked perfect there.
var req = {
method: 'POST',
url: _url +'/login',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: { user: 'someUser', password :'somePass' }
}
$http(req)
.then(function success(res){
...
}, function error(res){
...
});
You are sending JSON data and sending the header of x-www-form-urlencoded.
Change the content type to "application/json"
Like:
headers: {
'Content-Type': 'application/json'
}

Resources