Handling a clustered environment in an android application - android

I have an application where authentication happens through a passive client. Basically based on server information, a browser will be launched and it will show a login screen. Once the user enters login credentials, the further handling of cookies and session is done in shouldOverrideUrlLoading.
The issue is coming with authentication when I am connecting to web application servers in a clustered environment. When user connects to first server, it shows him login screen and user enters the details, server authenticates, but during session handling in shouldOverrideUrlLoading, my code connects to the same server with same url, but the response from the server comes that user has not been authenticated, while he has already done authentication.
So to differentiate between different servers, we use JSESSIONID to identify server.
I get the original JSESSIONID that was used on the first URL, but when the second URL is fired, my code use JSESSIONID and other cookies from the first URL in the request of second URL. To fire second URL, i use org.apache.http.impl.client.DefaultHttpClient.execute method.
I am not sure what I am missing to get the response from server that user is already authenticated.

I resolved this issue. There was an issue with cookie version, I was using while building a HTTP context for second request.
BasicClientCookie cookie = new BasicClientCookie(name,value);
// cookie.setVersion(1);
cookie.setDomain(host);
cookie.setPath("/");
cookie.setSecure(true);
cookieJar.addCookie(cookie);
I commented version for cookie and then it recognized request to send to same cluster member which was authenticated in first request.

Related

What is the best way to add and check authorization token?

I am implementing an android application which will validate user details against the server and stores the return token. For subsequent requests it should send the token along with each request. Here are some of the points I need to consider.
I am using Retrofit 2 library to send http requests to the server
The token will be generated by JWT library and sent back to the client
If the token is not present or invalid or expired, the server will throw 400/401 error
Design
The landing page of android app is not login protected so that user can see the app before using his credentials
Once he is on MainActivity, any requests to other screens require authentication. So all other activities will check for token and redirect to login activity.
In case any response received from server has 400/401 header, it should also redirect to login page.
Considering the above requirements, I tried to add an interceptor in Retrofit service generator class which which will be executed on every request/response.
Problem
The interceptor is executed for every request not just once per activity. i.e. it is opening n number of logic activities if there are n number of async calls in the main activity (because no token will be present for all those requests).
Can someone help me in identify:
If there is a better design that can avoid such problem or
Is there any way to suspend main activity until login is completed and then resume it.

Manage server-side authentication from Android client

I have set up third party OAuth authentication on my Node.js server using passport.js.
It works well from browser. The flow is the following:
Get request to myserver.com/auth/instagram
Passport redirects me to instagram website to login
I type my credentials
I am redirected to the callback url, which is my server.com/auth/instagram/callback
I do further processing and finally res.send(myAccessToken) to the client.
I am having troubles implementing this in Android. To type third-party credential, a browser page will be needed. But then how am I going to get the final result in my app?
Option 1
Start the browser.
Intent i = new Intent(ACTION_VIEW);
i.setData(Uri.parse("https://myserver.com/auth/instagram"));
startActivity(i);
Issues:
I cannot easily set proper headers needed for my server.
I cannot programmatically read the final response! The action is given to the browser app, which goes to the end and will never notify my app. The user is shown a blank page with myAccessToken printed.
Option 2
Connect using some http library.
final Request request = createRequest()
.url("https://myserver.com/auth/instagram")
.get()
.build();
Response response = client.newCall(request).execute();
Issues:
Does not work! Even if I set okhttp to follow redirects, I get a 200 response pointing to some instagram url. Of course the user is never prompted his instagram credentials, because no browser ever opened.
How to deal with this?
Notes:
I have used instagram as an example, the third party service is not relevant to the question. I am looking for a general solution to receive the result callback in my Android app.
I am not willing to implement client-side auth. I am willing to trigger steps 1.-5. from my Android app and receive the final result in a Java callback.

Login via Basic Authentication and open Browser afterwards

So I want to login to a webpage which uses Basic Authentication to login.
If I send HTTP Get with the Authorization Header, I get the successful response as HTML. But afterwards, it asks me again, to login, because it didn’t remember that I’m already logged in.
So my question is:
How can I save this information, that I have already been logged in?
I know, I already asked that question before, but since no one answered any more on the other thread my last hope was to open another.
The other thread: Android doesnt notice when i do an WWW-Authenticate
EDIT:
So what i wanna do is:
Intent browserIntent = new Intent(Intent.ACTION_VIEW,Uri.parse("The Website with the Authentication")); // Here, i want to add the request header
handler.startActivity(browserIntent);
But i have no idea how, because, the only thing you can send the intent is the Url (and no request headers).
Hope this makes things clearer.
Basic authentication doesn’t save state on the server end. Every request requires that you include the login information.
What happens normally is that:
The browser makes a request for a URL, lacking any authentication.
The server returns code 401, that this URL requires basic authentication.
The browser asks (either the user, or some database of its own) for the username and password. If it asked the user for the password, the browser then stores the username/password in an internal database, keying it against this URL.
For every further request for this URL, the browser includes that username and password in the HTTP GET request.
So the basic answer is, the server doesn’t remember that you have already logged in. The browser remembers that. Since you’re writing the browser, it’s up to you to have your application remember the username/password combination for that URL. Whatever you are doing now after you receive a 401 response, you simply always do for that URL. You don’t even need to wait for the 401 response.

Java Servlet, Cookies and Android

I am writing an Android app which submits a username and password to a Java Servlet hosted on Google App Engine. I am writing both the Android app. and Servlet.
The username and password are packaged into a POST request on the device and the servlet doPost() method checks the values. If the username and password are correct I request a session...creating it if it doesn't exist:
HttpSession session = request.getSession(true);
In this session I store a name value pair "logged" and "true".
Back on the android device a cookie is returned along with an HTTP status of 200 OK. This all seems fine, since the session on the server is implemented using cookies (transparent to me since I'm just using the session API).
All subsequent HTTP POSTs made by the android device package up the cookie into the HTTP POST so that it can request .jsp pages or use other servlets which inspect the session for the "logged and "true" value (i.e. protected pages).
The problem: A cookie is returned even if the following code is NOT run:
HttpSession session = request.getSession(true);
i.e. the username and password were false. This isn't such a security issue since the "logged" and "true" name value pair is never set so the application cannot use the .jsp or other servlets. However, I was using the fact that a cookie had been returned from the POST request to the device as a sign that authentication was successful.
Why am I getting a cookie even though I don't use or request the use of a session?
My current solution is to create an additional cookie in the servlet and check for this cookie on the device. HOWEVER, this cookie is not the one packaged into subsequent POSTS from the device since it is not the cookie associated with the session containing the "logged" "true" value. This seems hacky. Clearly I ave misunderstood something.
Most (or perhaps all) servlet containers will always assign a user a session cookie if they do not already have one, whether the webapp being served explicitly requests a session or not. Google App Engine is no different in this regard. You shouldn't assume anything based upon the mere existence or non-existence of a cookie other than that the device has made a request to the server and received some response back.
If you want to verify that the login was successful on the device, why not just send back a response to the login request that it can easily parse. For instance, a simple JSON-snippet like {"status": "success"} would do, or even just the literal text string "success".
Your second cookie approach definitely sounds a bit hacky. Presumably your authentication request is already sending some response back to the device (it has to be, if cookies are being sent). What do you feel that you gain from using a cookie that you don't get by just sending some status message back as part of the response?

Reaching server when request is redirected to form

I have an issue with wifi connectivity when a browser form must be completed before internet access is granted. The user (if using a browser) is redirected to a login form requiring them to login or sign up for wifi access.
The users are not using a browser but a request from my app to the server is redirected to a login form making the server unreachable. Is there a graceful way of detecting this behaviour and at least warning the user of the issue..
In many cases the mobile network is available and switching off wifi is all that is required.
An HTTP redirect has a specific response code (well, several specific response codes, from 300 to 307). You could read the responseCode before assuming that you have a connection and handle the failure from that point.
A redirect should also have a Location value in the response header, so you could conceiveably capture that value and launch a WebView, passing Location as the URL, giving the user access to the login form. This would get a little complex, though, depending on how the session is validated - if there's a cookie, for instance, you'd have to extract it from the form response and store it for future requests from your native code. Often these sessions employ the MAC address, in which case you wouldn't have to do anything else (apart from handle a successful login and try your request again).
I hope that's helpful.

Categories

Resources