Android: How to set cookie data in Custom Tabs - android

I need to open a web page in the custom tab. However, the page would obviously require users to log in. We don't want our users to be asked to log in, instead, we want to set cookies with token to CustomTab so that they will be automatically logged.
I have read an answer here that says it is not possible. Do I understand it correctly? Is there a way to achieve the goal?
EDIT: I've tried this after #Aris Panayiotou's answer but it did not work. What did I do wrong here?
private void openWebView() {
if (getActivity() != null) {
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager );
String cookieStringTakenFromWeb = "some cookie string with correct token";
CookieStore cookieStore = cookieManager.getCookieStore();
HttpCookie cookie = new HttpCookie("Cookie", cookieStringTakenFromWeb);
cookieStore.add(URI.create(Util.getString(R.string.myUrl)), cookie);
final CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder(mCustomTabsSession)
.setToolbarColor(ContextCompat.getColor(getActivity(), R.color.red))
.setShowTitle(true)
.build();
customTabsIntent.launchUrl(getActivity(), Uri.parse(Util.getString(R.string.myUrl)));
}
}

If you can update the website's code to read a header, you could pass the token in the request header.
val customTabsIntent = CustomTabsIntent.Builder(session).build()
val headersBundle = Bundle().apply {
putString("X-Session-Token", "token")
}
customTabsIntent.intent.putExtra(android.provider.Browser.EXTRA_HEADERS, headersBundle)

as of what i understand from your question, you can try CookieHandler. A CookieHandler object provides a callback mechanism to hook up a HTTP state management policy implementation into the HTTP protocol handler. The HTTP state management mechanism specifies a way to create a stateful session with HTTP requests and responses.
Read More on this link : CookieHandler
and CookieManager read more : CookieManager

Related

How to access cookie and check if it has expired using okhttp3 and PersistentCookieStore?

I am working on an Android app in which a log in post request is made to a webservice. The request returns a cookie which expires in 20 minutes.
Using okhttp3 and this PersistentCookieStore library, I got the cookie to be stored and subsequently added it as request header to access authentication-required get requests (e.g. personal information that are non-public).
The code goes this way,
CookieJar myCookieJar = new PersistentCookieJar(new SetCookieCache(),
new SharedPrefsCookiePersistor(this));
OkHttpClient client = new OkHttpClient.Builder().cookieJar(HttpRequests.cookieJar).build();
I then call a method like this inside an (after I have gone through another log in Async task to get the cookie) Async task to perform a get request that requires authentication,
public static String PostReq(String url, String json) {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.addHeader("Cookie", "key=value")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
catch(Exception e){
}
}
The .addHeader("Cookie", "key=value") adds the cookie to the header to tell the webservice that I am authenticated.
Here comes my difficulty. Since the cookie expires after 20 minutes, I would like to be able to access the cookie itself to check for the expiration time and possibly redirect the user to the log in activity by calling the method,
myCookie.expiresAt()
and comparing it to
System.currentTimeMillis()
I tried to look at the PersistentCookieStore codes and found that it uses a SharedPreference with the key "CookiePersistence". I looked inside this file while my emulator was running the app and found it to be empty however.
How would I be able to access this cookie that I have obtained? Much thanks for any advice to be given.
OK, this is old, but I was facing the same problem, and here is how I fixed it.
Hold a reference to your SetCookieCache used to instantiate your CookieJar:
SetCookieCache cookieCache = new SetCookieCache();
CookieJar myCookieJar = new PersistentCookieJar(
cookieCache,
new SharedPrefsCookiePersistor(this)
);
Then use this to find your cookie and check it:
for (Cookie cookie : cookieCache) {
if (cookie.name().equals("cookie_name") && cookie.persistent()) {
//cookie is still good
break;
}
}
Or use cookie.expiresAt() to do your thing.

Android Intercept a WebView request properly

My current code for intercepting a request in webview is
#Override
public WebResourceResponse shouldInterceptRequest(WebView view,
String url) {
String ext = MimeTypeMap.getFileExtensionFromUrl(url);
String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);
if (mime == null) {
return super.shouldInterceptRequest(view, url);
} else {
HttpURLConnection conn = (HttpURLConnection) new URL(
url).openConnection();
conn.setRequestProperty("User-Agent", userAgent);
return new WebResourceResponse(mime, "UTF-8",
conn.getInputStream());
}
}
I got this code from
The best way to intercept a WebView request in Android.
However, whenever I try to perform authentication, let's say I am loading facebook in my webview.
mWebView.loadUrl("https://www.facebook.com/");
Nothing is happening, what I noticed is that, the request headers are incomplete and also the response. Also, there are no cookies in the Sources. (I saw this when I remotely debugged the webview through Chrome).
Please correct me if I'm wrong, but I think that the incomplete headers and missing cookies is what causing the login request to fail.
Is there a way where I can modify the request and set its headers? Also for the response, should I do it too? And finally, how will I be able to have the cookies.
This question hasn't been answered for 6 months, so I don't know whether you will still need this, but maybe someone else has a similar question.
request headers are incomplete
When using HttpURLConnection you will be responsible to set any request headers, you might need, but it is as simple as setting the User-Agent, which you already did: conn.setRequestHeader(header, value) or if you want to add and not overwrite a header value: conn.addRequestHeader(header, value)
Alternatively, you could use okhttp, a HTTP client, which should add default values for headers, that are commonly expected.
there are no cookies in the Sources
When intercepting the request, you will also be in charge for handling cookies. You could store the cookie manually, by parsing the headers from the response e.g.
public WebResourceResponse shouldInterceptRequest(WebView view,
String url) {
// do your stuff
conn.connect(); // required to tell that the connection should be established
String cookie = getCookieFromConnection(conn);
// do more stuff and return WebResourceResponse
}
/**
* iterates all headers, and finds "cookie" headers
* (there could be more than one)
* #return cookie (concatenated value of all the found cookies)
* or null if no cookie has been found
*/
private String getCookieFromConnection(HttpURLConnection connection) {
String cookie = "";
Map<String, List<String>> header = connection.getHeaderFields();
List<String> cookies = header.get(COOKIE_HEADER);
if (cookies != null) {
for (String c : cookies) {
if (c != null) cookie += c + ";";
}
}
if (cookie.isEmpty()) return null;
return cookie;
}
or you could use a CookieManager, which would handle everything for you:
cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
You could will also need to handle your cookies, when using okhttp, but again you could use the CookieManager as stated above. See this docu for more details, or this stackoverflow question.
Please correct me if I'm wrong, but I think that the incomplete headers and missing cookies is what causing the login request to fail.
There is another problem, when intercepting requests in a WebView: it somehow stops loading and evaluating javascript. I found this blog by Artem Zinnatullin online, who describes this behavior, and I experienced the same behavior.
If anyone would has a solution for this, I would be very happy.

Get Session from Android Webview

I have created an Android application, in that I want to get Session from webview.
How to make it possible ?
Thanks.
I use this method for getting session cookies from a webview:
public static String getCookieFromAppCookieManager(String url) throws MalformedURLException {
CookieManager cookieManager = CookieManager.getInstance();
if (cookieManager == null)
return null;
String rawCookieHeader = null;
URL parsedURL = new URL(url);
rawCookieHeader = cookieManager.getCookie(parsedURL.getHost());
if (rawCookieHeader == null)
return null;
return rawCookieHeader;
}
There are two ways:
If a developer has made a httpclient, and makes an api auth call and store the cookie. Then you sync the httpclient's cookie with webview and maintain a session natively.
If user has used a webview to make an auth call and the cookie resides in the webview.
First one is your code and simply making a getter will return instance of DefaultHTTPClient. The instance will have access to cookies too. you can make async calls to auth api to get correct cookie in the instance. Make sure to keep HttpClient and Webview in sync.
For retrieving cookie in second method, you would use CookieManager object and the url which user is logged into and you need cookie for, example twitter.com See the second post here for implementation details.

Sharing cookies/session from WebView to HttpClient doesn't work

I know this question has been asked a hundred times, and I've read and tried for 2 hours now, but I can't find my error :-(
I am trying to create a simple webbrowser and therefore have a webview, where I login on a site and get access to a picture area. With help of a DefaultHttpClient, I want to make it possible to download pictures in the secured area.
Therefore I am trying to share the cookies from the webview and pass them on to the HttpClient, so that it is authenticated and able to download. But whatever I try and do, I always get a 403 response back...
Basically the steps are the following:
1) Enter URL, webview loads website
2) Enter login details in a form
3) Navigate to picture and long hold for context menu
4) Retrieve the image URL and pass it on to AsynTask for downloading
Here's the code of the AsyncTask with the Cookie stuff:
protected String doInBackground(String... params) {
//params[0] is the URL of the image
try
{
CookieManager cookieManager = CookieManager.getInstance();
String c = cookieManager.getCookie(new URL(params[0]).getHost());
BasicCookieStore cookieStore = new BasicCookieStore();
BasicHttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
String[] cookieParts = null;
String cookies[] = null;
cookies = c.split(";");
for(int i=0;i<cookies.length;i++)
{
cookieParts = cookies[i].split("=");
BasicClientCookie sessionCookie = new BasicClientCookie(cookieParts[0].trim(), cookieParts[1].trim());
sessionCookie.setDomain(new URL(params[0]).getHost());
cookieStore.addCookie(sessionCookie);
}
DefaultHttpClient httpClient = new DefaultHttpClient();
httpClient.setCookieStore(cookieStore);
HttpGet pageGet = new HttpGet(new URL(params[0]).toURI());
HttpResponse response = httpClient.execute(pageGet, localContext);
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
--> NEVER Happens, always get 403
.) One of the problems is that the webview saves some cookies for the host *www.*example.com, but the image-URL to download (params[0]) is *static.*example.com. The line
cookieManager.getCookie(new URL(params[0]).getHost());
returns null, because there is no cookie for static.example.com, but only for www.example.com.
.) When I manually say cookieManager.getCookie("www.example.com"); I get some cookies back, which I add to the HttpClient cookie store:
There are 5 cookies added
- testcookie = 0
- PHPSESSID = 320947238someGibberishSessionId
- email = my#email.net
- pass = 32423te32someEncodedPassGibberish
- user = 345542
So although these cookies, a session ID and other stuff, get added to the HttpClient, it never get's through to download an image. Im totally lost... though I guess that it either has something to do with the cookies domains, or that Im still missing other cookies.
But from where the heck should I know which cookies exist in the webview, when I have to specify a specific URL to get a cookie back?? :-(
Any advice?
I guess we have made it too complicated in above snippet.
Use these easy steps -
1)Retrieve the cookie from webView -wherever your webview is, use this code to re
String cookie = CookieManager.getInstance().getCookie(
url.toString());
Log.d("mytcs", "cookie downloadlistner " + cookie);
2) Pass this in your downloading asyncTask using params -
downloadImageTask = new DownloadImage();
downloadPDFTask.execute(url, cookie);
(I assume you know to retrieve this cookie in asyncTask, you will use params[1],
3) set this cookie in your http request using -
if (cookie != null)
con.setRequestProperty("cookie", cookie);
where con is HttpURLConnection con;
so you can set it to your need, in HttpGet.
You probably figured out the answer already coz it is a pretty late answer. But, just in case...
Try this. When you retrieve the cookie from WebView just use example.com in the domain name. When you set the cookie in BasicClientCookie and set the domain, set the domain name to .example.com. Note the "." in the beginning. Now, i think the session should work across all subdomains in your application.

AndroidHttpClient and Cookies

Using the AndroidHttpClient with cookies gives me intermixed 200 ok and 403 forbidden responses. I'm not sure what I am doing wrong.
I'm using the AndroidHttpClient in the following manner:
I have several background thread classes, and each one does the following:
HttpGet get...
HttpClient client = AndroidHttpClient.newInstance("Android");
HttpContext http_context = HttpSupport.getHttpContextInstance();
CookieStore cookie_store = HttpSupport.getCookieStoreInstance();
http_context.setAttribute(ClientContext.COOKIE_STORE, cookie_store);
client.execute(
HttpSupport is a class with two static fields; a CookieStore and a HttpContext:
public class HttpSupport {
private static HttpContext _context;
private static CookieStore _cookieStore;
public static synchronized HttpContext getHttpContextInstance() {
if (_context == null) {
_context = new BasicHttpContext();
}
return _context;
}
public static synchronized CookieStore getCookieStoreInstance() {
if (_cookieStore == null) {
_cookieStore = new BasicCookieStore();
}
return _cookieStore;
}
}
Is it ok to have multiple instances of the AndroidHttpClient in the application? Am I storing the cookies correctly?
I would recommend using the Android Asynchronous HTTP Client
It implements its own persistent cookie store (PersistentCookieStore) which is really easy to use. In fact, if you don't want to use the library for its asynchronous abilities you could just use it for the Persistent Cookie Store that it provides.. However the asynchronous abilities of it are highly worth while.
So to use it with your current class you could simply make a change in your HttpSupport class that has
public static synchronized CookieStore getCookieStoreInstance(Context context) {
if (_cookieStore == null) {
_cookieStore = new PersistentCookieStore(context);
}
return _cookieStore;
}
Note that you will have to add the context to the method as it is required for the PersistentCookieStore to work.
HttpClient automattically stores the cookies I have found, you should really be doing all this in an async task (as to Android 3.0> requirments).
The 200 response is when everything has been sent through right and the file you want is avaliable to you, this isn't a problem.
The 403 error is pretty obvious, does this server require some type of log in to get the file or webpage? This is what you should investigate, a way to work out how to log in is to use something like google chrome, right click on the webpage, go inspect element, then watch the network files going through, log in, watch for a post request. Find out how the website works.
Have a look here for a async task: HTTP POST request ANDROID 4 (working in 2.3)?
I believe you can have multiple instances of HttpClient, but to be using the same cookies you should be using one for everything that is connected
For eg:
You should have one HttpClient to log in, then request a page using get, do what ever you need to do etc.
Sorry I relised you were using AndriodHttpClient not HttpClient, AndroidHttpClient does not store cookies by default so yeah, Any reason why you are using AndroidHttpClient over HttpClient?

Categories

Resources