Reading browser cookies lambda proxy java - java

I know it is possible to get a cookie in lambda proxy. I can't find any sources on retrieving the cookies except in node.js (but it isn't in the same format). Can anyone point me in the right direction?

Cookie can be set up in the response headers. Return as a response something like this:
{
statusCode: 200,
headers: {'Set-Cookie': 'key=val'},
body: 'Some response'
}
To read cookies you need to check the request header. It's provided in the event from API Gateway. It's either event.headers.Cookie.

Related

"Refused to set unsafe header 'Cookie' " while sending cookies with GET request in angular 6

I am using spring security with angular 6. When i login using basic Auth server sends a cookie JessionID with response. I want to send this cookie with other request for authentication purpose but it gives me error Refused to set unsafe header 'Cookie' . When i hit the same endpoint from postman with same cookie in header it works.
Below is the method in angular:
Note: Currently i am manually adding it with headers.
private heroesUrl = 'http://localhost:8080/hi';
header = new HttpHeaders().set("Cookie", "JSESSIONID=A2A75EC9A3E1172D60060C6E708549B5");
getMessage() :Observable<Message>{
return this.http.get<Message>(this.heroesUrl,{headers:this.header});
}
Response which i get when i login using basic Auth
You can't do this, cause the browser doesn't allow you to do it. Let me describe the problem here:
Did you notice the Set-Cookie: JSESSIONID=......; Path=/; HttpOnly in your response headers? Well, The problem is the HttpOnly flag. Actually :) it's not a problem, it's a feature to prevent attacks that aim to steal your browser cookies:
HttpOnly is a flag added to cookies that tell the browser not to display the cookie through client-side scripts (document.cookie and others). ... When you set a cookie with the HttpOnly flag, it informs the browser that this special cookie should only be accessed by the server
So the browser doesn't allow any javascript code to access this variable. If you could change that value, then it's not a HttpOnly flagged cookie anymore:)
If you want to send this cookie via javascript, you should send it via the Authorization header for example and write middleware in Java server so that it captures these values from the Authorization header and think of them as JSESSIONID cookie. No more options for you :)
I also had this issue, and i just fixed it right now.
I realized that is you pass option {withCredentials: true} your browser will automatically send all available cookies along with your request. That way you don't have to add the cookies manually, so it's fluent and i thinks it also safer.
Change your code to this and see and check.
Cookies are available when the path is same as your front end.
private heroesUrl = 'http://localhost:8080/hi';
getMessage() :Observable<Message>{
return this.http.get<Message>(this.heroesUrl, {withCredentials: true});
}

HttpClientErrorException 406 null is thrown in rest template spring mvc [duplicate]

In my Ruby on Rails application I tried to upload an image through the POSTMAN REST client in Base64 format. When I POST the image I am getting a 406 Not Acceptable Response. When I checked my database, the image was there and was successfully saved.
What is the reason for this error, is there anything I need to specify in my header?
My request:
URL --- http://localhost:3000/exercises.json
Header:
Content-Type - application/json
Raw data:
{
"exercise": {
"subbodypart_ids": [
"1",
"2"
],
"name": "Exercise14"
},
"image_file_name": "Pressurebar Above.jpg",
"image":"******base64 Format*******"
}
Your operation did not fail.
Your backend service is saying that the response type it is returning is not provided in the Accept HTTP header in your Client request.
Ref: http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
Find out the response (content type) returned by Service.
Provide this (content type) in your request Accept header.
http://en.wikipedia.org/wiki/HTTP_status_code -> 406
406 Not Acceptable
The resource identified by the request is only capable of generating response entities which have content characteristics not
acceptable according to the accept headers sent in the request.
406 happens when the server cannot respond with the accept-header specified in the request.
In your case it seems application/json for the response may not be acceptable to the server.
You mentioned you're using Ruby on Rails as a backend. You didn't post the code for the relevant method, but my guess is that it looks something like this:
def create
post = Post.create params[:post]
respond_to do |format|
format.json { render :json => post }
end
end
Change it to:
def create
post = Post.create params[:post])
render :json => post
end
And it will solve your problem. It worked for me :)
"Sometimes" this can mean that the server had an internal error, and wanted to respond with an error message (ex: 500 with JSON payload) but since the request headers didn't say it accepted JSON, it returns a 406 instead. Go figure. (in this case: spring boot webapp).
In which case, your operation did fail. But the failure message was obscured by another.
You can also receive a 406 response when invalid cookies are stored or referenced in the browser - for example, when running a Rails server in Dev mode locally.
If you happened to run two different projects on the same port, the browser might reference a cookie from a different localhost session.
This has happened to me...tripped me up for a minute. Looking in browser > Developer Mode > Network showed it.
const request = require('request');
const headers = {
'Accept': '*/*',
'User-Agent': 'request',
};
const options = {
url: "https://example.com/users/6",
headers: headers
};
request.get(options, (error, response, body) => {
console.log(response.body);
});
Changing header to Accept: */* resolved my issue and make sure you don't have any other Accept Header
In my case, I added:
Content-Type: application/x-www-form-urlencoded
solved my problem completely.
If you are using 'request.js' you might use the following:
var options = {
url: 'localhost',
method: 'GET',
headers:{
Accept: '*/*'
}
}
request(options, function (error, response, body) {
...
})
In my case for a API in .NET-Core, the api is set to work with XML (by default is set to response with JSON), so I add this annotation in my Controller :
[Produces("application/xml")]
public class MyController : ControllerBase {...}
Thank you for putting me on the path !
It could also be due to a firewall blocking the request. In my case the request payload contained string properties - "like %abc%" and ampersand symbol "&" - which caused the firewall to think it is a security risk (eg. a sql injection attack) and it blocked the request. Note here the request does not actually go to the server but is returned at the firewall level itself.
In my case, there were no application server logs generated so I knew that the request did not actually reach the server and was blocked before that. The logs that helped me were Web application firewall (WAF) logs.

Google Drive : gsheets download through REST API

I am trying to download spreadhseets from a users google drive. I am encountering a CORS issue.
http://javascript.wekeepcoding.com/article/15417055/CORS+on+exportLinks+for+Google+Docs+spreadsheets+not+working
Reading this:
https://github.com/google/google-api-javascript-client/issues/47
I am trying to make a GET request on the server side. I tried using restTemplate.exchange but I am not sure what format my response should be in. Basically completely lost.
Is there a way to make the GET to pull the file and pass back to my front end?
I keep getting this error for whatever format I try:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [interface java.sql.Blob] and content type [application/vnd.openxmlformats-officedocument.spreadsheetml.sheet]
Any help greatly appreciated.
As far as CORS goes, this is the relevant guide I can find, How to use CORS to access Google APIs
Use XMLHttpRequest2 to make
CORS requests.
A CORS request to a Google API is similar to a REST request. The URL
for a CORS request follows this pattern:
https://www.googleapis.com +
REST path + URL Params
Example: here is a REST request:
var restRequest = gapi.client.request({
'path': 'https://people.googleapis.com/v1/people/me/connections',
'params': {'sortOrder': 'LAST_NAME_ASCENDING'}
});
And here is the equivalent CORS request:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://people.googleapis.com/v1/people/me/connections?sortOrder=LAST_NAME_ASCENDING');
Request headers are added to the request using
XMLHttpRequest.setRequestHeader.
The request body is sent using the XMLHttpRequest.send method.
You can register callbacks by adding event listeners on the load and
error events. Follow this link for information about XMLHttpRequest
events
Also make sure you have permission to download the spreadsheet file
from the other user.

Cross Origin Resource sharing issue even when all the CORS headers are present

even though i have appended my service response with following provided CORS Headers :
resp.setContentType("application/json");
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.addHeader("Access-Control-Allow-Credentials", "true");
resp.addHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
resp.addHeader("Access-Control-Allow-Headers", "Origin,accept,content-type");
resp.flushBuffer();
i am still getting below error in the console while trying to access some of the POST web methods in the service through my AngularJS frontend.
XMLHttpRequest cannot load http://192.***.*.***:8080/abc/def/search/vehicleManufacturer. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.***.*.***:8085' is therefore not allowed access.
However within the same class, some POST methods without any payloads are responding perfectly. Any suggestions ?
EDIT--------->
Below is my AngularJS client screen code for calling the web method:-
getVehicleModel : function(searchData,$scope){
$http({
method:'POST',
url:'http://192.169.*.***:8085/abc/def/search/vehicleModel',
dataType:'jsonp',
data:searchData
}).
success(function(data){
console.log("vehicle model")
$scope.vehicleModel = data.Response;
});
},
I think the problem here is Preflighted Requests in CORS.
From the Mozilla docs,
Unlike simple requests (discussed above), "preflighted" requests first
send an HTTP request by the OPTIONS method to the resource on the
other domain, in order to determine whether the actual request is safe
to send. Cross-site requests are preflighted like this since they may
have implications to user data. In particular, a request is
preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than
application/x-www-form-urlencoded,
multipart/form-data
text/plain
e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
As explained above, even though you're making a simple POST request, the Content-Type in your request is application/json which is different from the 3 types mentioned above, so it's considered as a Preflight request and an OPTIONS request is fired before your actual POST request.
You can solve this by implementing doOptions in your servlet, just add the headers there and it will work :)
The preflight (OPTIONS) is occurring due to the fact that you are sending a cross-origin ajax request AND specifying an Authorization header with this GET request.
Also (this is not causing an issue) I would suggest removing the contentType option. This doesn't make sense in the context of a GET request. A GET request should not have any content. All data should be included in the query string or, possibly, headers.
The Authorization header will not be sent with the OPTIONS. You must acknowledge it server-side, and then the browser will send the underlying GET. Read more about CORS at https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS .

How does cookies work, when calling cookie-setting REST services from java VM?

I'm in the process of learning how to use HP Quality Center's REST api to query and manipulate data. Unlike REST standard, this API is not completely stateless. It uses cookies to store authentication sessions.
I've tried to implement a very simple test, using the Jersey Client library. I can successfully authenticate my user, by sending my credentials. The API reference claims that this will set a cookie, and I am good to go with further calling the REST api. However, a simple "is-authenticated" call returns a 401, Authentication failed.
I have a feeling that the cookie writing or reading is not working properly, as everything else seems to work as it should. But I haven't been able to find out if or how cookies are set and read, when no browser is involved. So How does cookies work, when calling cookie-setting REST services from java VM? Does it work at all? Where are they stored?
I am using Eclipse Kepler as my IDE, if that matters at all, and a 32-bit java 1.6 JDK and JRE.
Code, and response strings below:
1. Logging in:
Client client = ClientBuilder.newClient();
Response response = client
.target("http://[host]:[port]").path("qcbin/authentication-
point/alm-authenticate")
.request().post(Entity.entity("<alm-authentication>
<user>username</user>
<password>secret</password></alm-authentication>",
MediaType.TEXT_XML_TYPE));
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=POST,
uri=http://[host]:[port]/qcbin/authentication-point/alm-authenticate,
status=200, reason=OK}}
API Return description:
One of:
HTTP code 200 and sets the LWSSO cookie (LWSSO_COOKIE_KEY).
HTTP code 401 for non-authenticated request. Sends header
WWW-Authenticate: ALMAUTH
2. Verifying Logged in:
response = client.target("http://[host]:[port]")
.path("qcbin/rest/is-authenticated")
.request().get();
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=GET,
uri=http://[host]:[port]/rest/is-authenticated, status=401,
reason=Authentication failed. Browser based integrations - to login append
'?login-form-required=y to the url you tried to access.}}
PS: adding the ?login-form-required=y to the URL, will bring up a log-in window when called in a browser, but not here. Appending the line to the URL actually still gives the same error message, and suggestion to append it again. Also, when called in a browser, the is-authenticated returns a 200, success, even without the login-form.
When you log in, you're getting a cookie which is a name plus a value.
The REST server expects you to pass this in the request header with every request you make.
Look into the object which you get for client.request(); there should be a way to specify additional headers to send to the server. The header name must be Cookie and the header value must be name=value.
So if the server responds with a cookie called sessionID with the value 1234, then you need something like:
client.request().header("Cookie", "sessionID=1234")
Related:
http://en.wikipedia.org/wiki/HTTP_cookie

Categories

Resources