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.
Related
At the time of login we get a authorization token and a refresh token,authorization token is attached with all API in header ,but after some time authorization token will expire and we will get 401,to refresh we need to call a API with refresh token that we get at the time of login in response we will get a new authorization token and refresh token,problem is where to catch 401 and write at one point to call refresh token API and resend the previous failed API ,we cant call API in interceptor.
Check this Refresh Access Token globally (Separate logic as a module) using RxJava 2, RxAndroid 2 and Retrofit 2 post.
Maybe it will help you
Okhttp (which acts as the http layer of retrofit) has a mechanism for doing just this. Have a look at https://square.github.io/okhttp/4.x/okhttp/okhttp3/-authenticator/
You provide the Authenticator to your Okhttp builder during setup and this then responds to 401 error responses to fetch a refresh token.
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.
I have an android app which uses the spring android library to communicate with my restful api. I'm not sure how to handle the scenario when the token for my client expires. What I'd like to to is to capture any 401 error and simply fetch a new token and retry the request.
I've created a ResponseErrorHandler and wired that up to my rest template:
public class UnauthorizedErrorHandler implements ResponseErrorHandler {
....
public void handleError(ClientHttpResponse response) throws IOException {
if (response.getStatusCode().value() == HttpStatus.SC_UNAUTHORIZED) { // 401 error
// fetch a new token
// Retry request now that we have a new token????
}
}
}
My problem is that I have no access to the originating request in the Response error handler. Unless I'm missing something, this strategy seems reasonable, but I'm not sure how to make it work. This also seems like a typical scenario for any client that is working with OAuth tokens, so hopefully someone out there can point me in the right direction.
If the token has expired then you should ask the user to login again.
Think about a user removing your OAuth app access, your app will received an expired token or similar error, and you should have the user login and give your app access again.
If you are not referring to an OAuth token, but your own API, then your should create some sort of mechanism to update the token to be used by the client. For example, you can send a header with the new token on your response asking the user to start using the new value from that point onwards, or as part of the response body or a push notification requesting a token exchange, etc.
If you're trying to request data from an API/Web Service how do you design the login process?
If it is sensitive data, do you send a login request to the server /w username+password, and receive a session-token or similar, or do you send username+password every request?
Assume you do get back a session-token. How do you get a fresh token, without asking the user to reenter their credentials. Do you save username+password on the device?
It is best to use client credentials flow of auth2:
show web page with login page
user enters username + password
page reloads and you get parameters from new page (auth code)
issue token request with auth code retrieved from previous step
save token with refresh token
use refresh token to obtain new token but remember that refresh tokens will have 'refresh_token'
value set to null so you will have to save refresh token retrieved
at the beginning to issue new tokens after they got too old (usually
3600s)
This: http://bshaffer.github.io/oauth2-server-php-docs/grant-types/client-credentials/ and this http://brentertainment.com/oauth2/ will make it easier to understand and implement
I am new to the volley library and try to figure out what is the best way to do the following.
My REST Api uses Basic Authentication first and if succeed they return a Access Token to use from that point. Because my Acces Token can expire, this is a requirement.
I want to call my api method http://myserver/test
I get back a 401 (Unauthorized).
I want to call http://myserver/auth using basic authentication
I get back a Access Token
Set the header to "Authentication: Session " + AccessToken
I want to "retry" the request to http://myserver/test.
Update
So basically what i want to do is. If a request failed with a given status code, i want to do a other request and after that retry the first one.
Thanks in advance!
I am using a similar approach using Volley.
Have listener from where the request is sent., Everytime when you get response check for session, if session is expired, save existing listeners temporarily.
Create new listeners & get Token, if success, resend request with oldTemp Listeners, so the request is sent back to original request.
Working app in PlayStore with similar approach.