Convert CookieStore to String: pb with encode/decode value - java

I have my cookies in a CookieStore Object, but to stream a video I need to convert my CookieStore to a String, but my API in NodeJS (using express, cookie-parser and passport-local) never recognizes the value of the cookie, whenever I try to encode/decode it before. I think it's a stupid problem just I'm not really good in HTTP Headers so I'm doing it wrong.
There is the code:
Method setVideoURIMethod = videovvw.getClass().getMethod("setVideoURI", Uri.class, Map.class);
Map<String, String> params = new HashMap<String, String>(1);
params.put("Cookie", ARequestAPI.getCookieString());
setVideoURIMethod.invoke(videovvw, uri[0], params);
I had the code from here so normally it should work perfectly: Authentication for Videoview in android
I think the problem comes from "ARequest.getCookieString()":
protected static CookieStore _cookies = null;
...
...
...
public static String getCookieString() {
String cookieString = "";
Log.v("Debug", _cookies.toString());
for (Cookie cookie : _cookies.getCookies()) {
try {
Log.v("Debug", "Decode: " + URLDecoder.decode(cookie.getValue(), "UTF-8"));
Log.v("Debug", "Encode: " + URLEncoder.encode(cookie.getValue(), "UTF-8"));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
cookieString += cookie.getName() + "=" + cookie.getValue()+ ";";
}
return cookieString;
}
The display in LogCat:
And the log on my API:
When I do a request using CookieStore:
{ 'connect.sid': 's:NUTf8t9o8cepR1yYItMexMxy.WFv/ZlktryfpVZHweVozabW1US4UBvGlWxQR7G7Aamc' }
When I do the request with my function which convert the CookieStore to a String:
{ 'connect.sid': 's:AZXpZmQGX7eJgej9hVA1qaAk.7vWP756Flwbte/qxBRcLOhl/CXMlVO3HVvmsvsEBpzA' }
I tried all the options, even encode(decode()), ... but it is never a good one on my API.
The weird thing is that I tried to decode 's%3ANUTf...' (so cookie.getValue()) with the javascript function "decodeURIComponent()" and I found exactly 's:NUTf8t9o8cepR1yYItMexMxy.WFv/ZlktryfpVZHweVozabW1US4UBvGlWxQR7G7Aamc', so my cookie is good, but I think I'm doing something wrong on the encode/decode part.
Thanks for your help.
Edit: After many tests, I saw that on the API the value for the cookie is always the same, whenever I use URLDecoder.decode(), URLDecoder.decode() or event directly cookie.getValue(), the only time I get the right value is when I "choose/write" the value myself like "totoauzoo" for example with this wring I get exactly the same value on the API. But it's not working with my old cookie value like "s:DMCBao7zeS9B2jwIfeQoDZtl.3XPIYIm7y2Bz9/o468v4wxvFZmjDrc6hKk4ty89sIX4".
Edit2: I probably found what is wrong, I get that on the API:
request with HttpGet and CookieStore:
headers { host: 'xxx',
connection: 'Keep-Alive',
'user-agent': 'Apache-HttpClient/UNAVAILABLE (java 1.4)',
cookie: 'connect.sid=s%3AGRGciNxOcR4BXHrUG8PikHMX.MyWa6vjW%2BBlcUaaCHHendqc7DEK4aoNFDzm5aabOkDM',
cookie2: '$Version=1' }
cookies { 'connect.sid': 's:GRGciNxOcR4BXHrUG8PikHMX.MyWa6vjW+BlcUaaCHHendqc7DEK4aoNFDzm5aabOkDM' }
request with setVideoURI:
headers { host: 'xxx',
connection: 'keep-alive',
cookie: 'connect.sid=s%3AKWKdcuXqUpzBIMv0sOGpPxqM.xb14kPsGKvn%2Fv%2BVcfUDzxWsye8QdJfuQgonNocsX3k8',
'user-agent': 'stagefright/1.2 (Linux;Android 4.1.2)',
'accept-encoding': 'gzip,deflate' }
cookies { 'connect.sid': 's:KWKdcuXqUpzBIMv0sOGpPxqM.xb14kPsGKvn/v+VcfUDzxWsye8QdJfuQgonNocsX3k8' }
How can I fix that?

I would suggest inspecting the network traffic itself.
Cookies are nothing else than HTTP headers ...
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: name=value
Set-Cookie: name2=value2; Expires=Wed, 09 Jun 2021 10:18:14 GMT
or
GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: name=value; name2=value2
Accept: */*
I'm not familiar with the classes you are using to set the cookies, but I would inspect two places:
1:
params.put("Cookie", ARequestAPI.getCookieString());
Is this call setting the headers or are you setting POST parameters? This should be visible in the network traffic. What are params? Headers, query string?
2:
ARequestAPI.getCookieString()
Is the output of this function in correct cookie value format, or what is it?
Most probably in one of those places lies the error.

Related

How to determine authentication requirements given 401 response?

I'm using the following code on the client side to take response of a protected website, which works pretty fine whenever there is no authentication request from server side:
final String targetURL = "http://************";
final String username = "********";
final String password = "******";
final int connectTimeout = 30000;
final String username_password = username + ":" + password;
final byte[] usernamepassword = (byte[])username_password.getBytes();
final String encoded_username_password = java.util.Base64.getEncoder().encodeToString(usernamepassword);
final URL url = new URL(targetURL);
final URLConnection connection = url.openConnection();
connection.setConnectTimeout(connectTimeout);
connection.setRequestProperty("Authorization", "Basic " + encoded_username_password);
connection.setRequestProperty("Accept", "text/html");
// response headers
final Map<String, List<String>> headerFields = connection.getHeaderFields();
for (final Map.Entry<String, List<String>> entry : headerFields.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
However, when I try to connect with a specific (protected) webserver, the connection is refused with the 401 http status code.
Key: null, Value: [HTTP/1.1 401 Unauthorized]
Key: WWW-Authenticate, Value: [Digest realm="Login to ********", qop="auth", nonce="*******", opaque=""]
Key: Connection, Value: [close] Key: Content-Length, Value: [0]
Is it possible to infer from the above logged response what I'm missing ?
I mean, the snippet above is a well known Java basic-authentication template, there are many examples everywhere with the same structure, so the issue seems likely related to the parameters issued as argument of the setRequestProperty() method.
This is what I took on request header by using Mozilla >> Web Developer >> Debug (where some fields are hidden by me):
Host: xxx.xxx.xxx.xxx
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache
Authorization: Digest username="", realm="Login to xxxxxxx", nonce="xxx-xxx-xxx-xxx-xxx", uri="xxxxxxx", response="xxxxx", qop=auth, nc=00000001, cnonce="b2b43c8d9631354d"
I am not sure to understand your question. My guess is you would like to filter the request based on the parameters and url so you can chhose to either serve content or reject and return 401.
In this case your question should be: How to filter which http requests requires authentication.
Depending on what framework your are using, in spring-boot, there is something called WebSecurityConfigurerAdapter. It basically helps you with your problem. You can filter all the requests coming to your server.
It Simply because you are not authenticated to their server,
you need the use that protected server authentication, if you want to enable yourself to access their resource,
maybe u can check their website, or docs to get some some api key or
some token (basic, bearer or whatever token)
then follow their guideline where to put that authentication in your request (usually if token will be in request payload, if api key or basic auth will be in request header)
hope this helps

HTTPPOST - Unsuccessful in code but successful via Postman

I am sending a JSON request via http post. Backend requires me to send two headers, namely - Authorization and Content-Type. Then a raw JSON request as body. I send the request via Post method via Postman tool and the message gets through successfully. But when I send the same request with same headers via code, I get a bad request - Error.
I minimized the scope of testing to check.
I have sent only the two headers via Postman and here's the response:
Headers
Authorization: "bearer " + token. The structure is "bearer" keyword + space + Okta token.
Content-Type: application/json
Response:
Headers
Content-Type →application/json; charset=utf-8
Strict-Transport-Security →max-age=31536000
X-Content-Type-Options →nosniff
Request-Context →appId=cid-v1:dc220dda-e515-4dd4-b324-c078a1b8fac4
Date →Sun, 26 May 2019 13:23:01 GMT
Content-Length →29
Body
{
"Message": "No Request Body"
}
But when I send the same thing via code, I get a Bad-Request Error. Please help :(
HttpClient httpclient1;
HttpPost httppost1;
//ArrayList<NameValuePair> postParameters1 = null;
httpclient1 = HttpClientBuilder.create().build
httppost1 = new HttpPost(Constants.URL);
// httppost1.setEntity(new UrlEncodedFormEntity(postParameters1,"UTF-8"));
// httppost1.setEntity(new StringEntity(request,"UTF-8"));
httppost1.setHeader("Authorization", token);
httppost1.setHeader("Content-Type", "application/json");
// httppost1.setHeader("Content-Length", strlength);
// httppost1.setHeader("Accept", "application/json");
// StringEntity entity = new StringEntity(request,ContentType.APPLICATION_JSON);
// httppost1.setEntity(entity);
HttpResponse response1 = httpclient1.execute(httppost1);
InputStream is = response1.getEntity().getContent();
HttpEntity entity1 = httppost1.getEntity();
Header[] headers = httppost1.getAllHeaders();
System.out.println(headers.length);
for(int i=0; i<headers.length;i++)
{
System.out.println(headers[i]);
}
String result = convertInputStreamToStringCommonIO(is);
System.out.println();
System.out.println(result);
int code1 = response1.getStatusLine().getStatusCode();
System.out.println("Code: "+code1+"");
String reason1 = response1.getStatusLine().getReasonPhrase();
System.out.println("Description: "+reason1 +"");
Temporary Request Headers from Postman:
UserAgent: PostmanRuntime/7.13.0
Accept: /
Cache-Contro: no-cache
Postman-Token: *****
Host: *****
accept-encoding: gzip,dflate
content-length:
Connection: keep-alive
Here's the error I am getting:
{"errorCode":"E0000021","errorSummary":"Bad request. Accept and/or Content-Type headers likely do not match supported values.","errorLink":"E0000021","errorId":"oae5BpTGp_5RjaFtGn_Zm_mhw","errorCauses":[]}
Code: 400
Description: Bad Request
Any idea why it's failing via code? Thanks.

Jetty POST Request returning error code 411

Here is my code to run the POST request
// Instantiate HttpClient
HttpClient httpClient = new HttpClient();
// Configure HttpClient, for example:
httpClient.setFollowRedirects(false);
// Start HttpClient
httpClient.start();
ContentResponse response = httpClient.POST("url")
.agent("Mozilla/5.0")
.method(HttpMethod.POST)
.param("do","login")
.param("url","")
.param("vb_login_md5password", this.password)
.param("vb_login_md5password_utf", this.password)
.param("s", "")
.param("vb_login_username", this.username)
.param("vb_login_password", "")
.send();
for(HttpField h : response.getHeaders())
System.out.println(h.getName() + " = " + h.getValue());
Here is the output
Date = Mon, 14 Dec 2015 08:17:08 GMT
Content-Type = text/html
Transfer-Encoding = chunked
Connection = keep-alive
Set-Cookie = __cfduid=dbb11c371945319b1d5943aad06c1977e1450081028; expires=Tue, 13-Dec-16 08:17:08 GMT; path=/; domain=.sythe.org; HttpOnly
Server = cloudflare-nginx
CF-RAY = 2548787ba9dc21b6-EWR
I look at the ContentResponse text of the post request by doing
response.getContentAsString()
However for some reason I keep getting a 411 error which tells me my Content-Length is zero or not specified. Is there a way to set the content length header of the post?
Thanks!
EDIT : Doing this makes no difference in my post request
.header(HttpHeader.CONTENT_LENGTH, "0")
With .param("do","login") you specify a query param to be added. For the POST to actually contain a body I'd think you need to set content() on the request. Maybe a FormContentProvider will work for you?

Java : How to handle POST request without form?

I'm sending a http post request from javascript, with some json data.
Javascript
var data = {text : "I neeed to store this string in database"}
var xhr= new XMLHttpRequest();
xhr.open("POST","http://localhost:9000/postJson" , true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.send(data);
xhr.setRequestHeader("Connection", "close");
//Also, I've tried a jquery POST
//$.post('postJson', {'data=' : JSON.stringify(data)});
//But this doesn't make a request at all. What am I messing up here?
Route
POST /postJson controllers.Application.postJson()
Controller
public static Result postJson(){
//What should I write here to get the data
//I've tried the below but values is showing null
RequestBody rb=request().body();
final Map<String,String[]> values=rb.asFormUrlEncoded();
}
What is the way to parse the POST request body?
Much thanks!
Retreive the request body directly as JSON... no need to complicate your life.
public static Result postJson() {
JsonNode rb = request().body().asJson();
//manipulate the result
String textForDBInsertion = rb.get("text").asText(); //retreives the value for the text key as String
Logger.debug("text for insertion: " + textForDBInsertion
+ "JSON from request: " + rb);
return ok(rb);
}
Also, I recommend you use the AdvancedRestClient Chrome plugin for testing. This way you can eliminate from the equation client-side code errors.
Cheers!

JAX-RS Cookies in response not showing in browser

I am using Rest response to set cookies on the client side. But I cannot see the cookie being set when I open up 'Resources' in Chrome. But interestingly, when I go to chrome settings and check all cookies, I find the cookies I am setting. Again, getCookie() javascript function from w3schools (or better version to handle all possibilities) fetch me nothing. I tried firefox, there same thing happens. When I see all cookies, I see my cookies, but JS function getCookie() does not return me anything. I think the cookies are not getting set properly.
Here is my JAX-RS response :
Cookie c1 = new Cookie(Constants.SESSION_TOKEN, response
.getSessionToken().getValue());
Cookie c2 = new Cookie(Constants.USER_IDENTIFIER,
response.getUserIdentifier());
NewCookie cookie1 = new NewCookie(c1);
NewCookie cookie2 = new NewCookie(c2);
return Response.ok(jsonResponse, MediaType.APPLICATION_JSON)
.cookie(cookie1,cookie2).build();
And this is my JS getCookie() function
function getCookies() {
var c = document.cookie, v = 0, cookies = {};
if (document.cookie.match(/^\s*\$Version=(?:"1"|1);\s*(.*)/)) {
c = RegExp.$1;
v = 1;
}
if (v === 0) {
c
.split(/[,;]/)
.map(
function(cookie) {
var parts = cookie.split(/=/, 2), name = decodeURIComponent(parts[0]
.trimLeft()), value = parts.length > 1 ? decodeURIComponent(parts[1]
.trimRight())
: null;
cookies[name] = value;
});
} else {
c
.match(
/(?:^|\s+)([!#$%&'*+\-.0-9A-Z^`a-z|~]+)=([!#$%&'*+\-.0-9A-Z^`a-z|~]*|"(?:[\x20-\x7E\x80\xFF]|\\[\x00-\x7F])*")(?=\s*[,;]|$)/g)
.map(
function($0, $1) {
var name = $0, value = $1.charAt(0) === '"' ? $1
.substr(1, -1).replace(/\\(.)/g, "$1")
: $1;
cookies[name] = value;
});
}
return cookies;
}
function getCookie(name) {
return getCookies()[name];
}
That's strange. I've tried to reproduce your problem, but everything worked fine:
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
#GET
#Path(value = "/test")
public Response test() {
NewCookie c = new NewCookie("name1", "value1");
Cookie cookie = new Cookie("name2", "value2");
NewCookie c2 = new NewCookie(cookie);
return Response.ok("response1").cookie(c, c2).build();
}
curl -i $URL gave me:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Server: Apache-Coyote/1.1
Set-Cookie: name1=value1; Version=1
Set-Cookie: name2=value2; Version=1
Date: Thu, 19 Sep 2013 13:52:43 GMT
Content-Type: application/json
Content-Length: 13
["a","b","c"]
The cookies also showed up in Chrome's Resources.
Not sure why your function doesn't get you your cookie information, but I might have an idea why it doesn't show up in your browser.
It helped me to remember that you need to visit the specific path that the cookie was set on for the browser to display the cookie in the console.
In the example above, make sure to visit the url displayed in the "Path:" section.
For somebody landing on this issue.
This problem occurs when the domain or the path values are not set properly
Use the below snippet to set the path and domain
NewCookie cookie = new NewCookie("cookie-name", "cookie-value,"/", "", "cookie description", 1000000, false);
For example, In your browser you should see these values after its set
Set-Cookie:x-auth-cookie=eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJtbTMiLCJhdWRpZW5jZSI6IkJST1dTRVIiLCJjcmVhdGVkIjoxNDg1MjU4MDcwMzQ2LCJyb2xlcyI6WyJBRE1JTiIsIlRFQUNIRVIiXSwiZXhwIjoxNDg2MjU4MDcwfQ.TM6oiCsOXh2zNou00H-5tkafAj40AngkbrCA62Vdyi5si_5hZFdmZFfitmK_bgRJexmFC49KlpAaRzGJF8bvMQ;Version=1;Comment="cookie description";Domain=;Path=/;Max-Age=1000000

Categories