Can we put authentication token in session object?
For example:
session.setAttribute("authToken",authTokne);
In my case I have to use authToken in every request call.
In service layer i am using third party services. In each request i need to pass authentication token. Getting authentication token is also a one request. I need to do many request calls step by step. At first request i am getting token and holding it in object level. After some time i need to make another request from different location(another class/object), now token is not available here. For this one more request i need to send for token. So avoiding this every time new call for a token, Can i put this token in servlet session varaible?
In term of security reasons is it good approach?
The all session data is kept on the server, so you can put anything you want there. The browser user is associated to the session via sessionId in a cookie (looked up by container upon request). When a user connects to server, a cookie is dropped on the browser with sessionId. Upon return the browser sends this sessionId back so you can lookup the session (usually a Map) to track data associated with the user and their current session. Session cookies can be set to persist through browser closing or expire when browser closes or after a certain time.
Storing the auth token in session is fine, but you will not be able to find a session based on auth token stored in it if the browser doesn't support or doesn't store cookies. If a user has no cookies (maybe a custom app that calls URLs), you would add an auth-token to the URL so that the user only logs in once per session. In this case you would create a data store which contains session data and associate both sessionId from browser and auth token to the same data. This is how I have done mobile/web/api session data management in the past.
What problem are you trying to solve?
Related
I am writing a REST client in Java using the HttpCLient , the REST API that I access needs an auth token for every REST action. This token is valid for 24 hours.
The way I am handling this now is calling a "getAuth()" method everytime I need to make a REST call which seems like an overhead on the auth server.
How can I conveniently store this auth token and manage its life cycle?
Are there any documented best practices?
I thought of the following solution
public class MySession {
String user;
String pass;
public MySession(String user, String pass) {
this.user = user;
this.pass = pass;
}
public getAuth() {
//user user, pass to get auth token
}
}
and then pass the sessions object to any class that nees the token. If the token is expired, just call this method again
For brevity I'll assuming you're calling an endpoint that you can't change. How you should implement will heavily depend on whether the token is app or user based (one token for all users on a shared app instance or one token per user).
If it's one auth token for the entire app:
Store it in memory along with a time-to-live timestamp (or alternatively catch the token expired error, request a new token and retry the original request), refresh it if it doesn't exist/is expired
If you're concerned about re-requesting API tokens after an application restart also store it in the database and load it at startup if it exists
If it's one token per user:
Store it in your user session, it's exactly what sessions are used for, if you're authing users then they'll have a session and the overhead is already there
If you don't want to re-request a token everytime they login store their current token in the DB and and load it into their session when they login
I'm assuming you are using OAuth for authorization. Whether you are using JWT or other tokens is irrelevant to this situation.
When performing authorization you will be issued an access_token with an expiration and, depending on the grant type you are requesting (Client credentials, Authorization code, Implicit, Resource owner), a refresh_token.
The client should keep the access_token and the expiration. The refresh_token, if issued, must be kept secret (beware of using the correct grant for your use case).
In subsequent calls, your client should not request new tokens on each call, it should use the stored access_token.
Once the API starts returning 401 Unauthorized, the access_token has probably expired. Your client should try to refresh the access_token using the refresh_token if you got one.
If you have no refresh_token or the refresh request also failed, because the refresh_token is no longer valid, you can perform a new authorization flow.
You can use the expiration time as a clue to know when to get a new access_token either through refresh or through a new full authorization flow. This will avoid the 401 Unauthorized. In any case, your client should have a fall back policy when this response is received after having used a valid access_token for some calls.
You can create a manager and store the auth-cookie during login in thread local like the code below. You can get the cookie from getAuth() as long as the thread lives.
public class Manager {
private static final ThreadLocal<String> SECURITY_CONTEXT = new ThreadLocal<>();
public static void setAuth(String auth) {
SECURITY_CONTEXT.set(auth);
}
public static String getAuth() {
return SECURITY_CONTEXT.get();
}
public static void clear(){
SECURITY_CONTEXT.remove();
}
}
I suggest you to use the following scenario:
1) First, call auth(username, password) rest api to get the auth token.
If the given credentials are okay then just send back the auth cookie to the client with HTTP 200 response code.
2) Then, you can call protected rest apis. You need to send auth cookie with your request each time.
3) Servlet filter (or something similar) checks each incoming request and validates the token. If the token is valid then the request goes forward to the rest method, if not you need to generate an http 401/403 response.
I suggest you not to write your own authentication layer. Instead of install and use an existing one. I suggest you OpenAM. It is a superb open source access management system.
I also suggest you not to open session on the server side for authentication purpose. If you have 10 clients then 10 sessions needs to be managed by server. It is not a big issue. But if you have 100 or 1000 or millions different clients than you need more memory to store sessions on the server.
If you are worried about too many hits to the database, then i'm assuming there is a lot of web activity.
I would not recommend using Session in your case, but rather store the token in a cookie on the client.
In a high traffic environment(which i'm assuming yours is), the use of Session can consume a lot of server memory, and scalability can be a concern as well, having to keep sessions in sync within a cluster.
As #Cássio Mazzochi Molin also mentioned, you can use an in-memory cache to store any user specific data and tokens. This will reduce the hits to the database, and also allow you to scale the application easier, when the need arises.
The de-facto standard is not implementing your own solution (basic rule in security: don't implement your own stuff!), but use the de-facto standard solution, namely JSON Web Tokens.
Documentation on the site, but the basic idea is, that you only need to store one value (the server's private key), and then you can verify every claim, issued originally by the server (which will in your case contain an expiry time).
You should use JsonWebToken (JWT in short) for this kind of stuff. JWT has build in support to set the expiration date. There are plenty of libraries to use this method and you can read more here
There are currenlty 4 java implementations and all of them can check if the token is still valid (exp check)
So if I'm understanding correctly you are using the same token for all of your requests (which means as long as your app is up and running and you refreshing the tokens, you should be ok. I literally had the same problem and this is how I've resolved it. I have a singleton class, which is initialized at the app start for once and refreshes the token when its invalidated. I'm using C#, Asp.NET MVC5 and AutoFac for DI, but I'm sure you can do the same with Java and Spring.
Updating property of a singleton with Thread Safety
Use json web tokens , to exchange information between two clients. The token will only alive for the 24 hours period, after that time all consequent calls in the header will be rejected.
Auth Token for each request is correct approach, Consider auth server scaling for performance issue.
On first successful authentication (username and password), generate private public keypair. Store private key as Session Security Token (SST) and send public key as Public Security Client Key (PSCK) to client
In all request other than login (or authentication) client will send PSCK to protect theft of username and password and server can verify PSCK for expiry internally at regular intervals saving processing time.
If system is having performance issue on authentication side, setup seperate auth server with scalability.
No token or password to be cached, exchanged unencrypted and send outside security zone. Do not post using URL parameters.
Just wondering if my following authentication method is correct or not. Is there any pitfall or anything missing? Suggestions and discussions are very welcome.
1> User provide user name and password, and send to the server by RPC. Comparing with the hashed value stored in DB.
2> Assuming the user name and password are accurate, an Auth Token is saved in session. The auth token will be checked when accessing the servlets.
3> The user id (integer) is returned to the client by RPC onSuccess. The user id is saved in a static variable on the client side.
4> Whenever the user specific information is needed, the rpc call with the user id (the static variable) will be sent to the server for database query.
Thanks
You'd better return the token to client side, and verify token instead of user id.
If user id is used, a user A is logged in, then another user can send request to server pretended to be user A. Your authentication method failed to protect data.
You don't need to send a user id to the client. The server has already all information he need's to recognize the user.
This code snippet creates a session cookie, with session.getId() you get the content of it, which you should save to recognize the user:
HttpServletRequest request = this.getThreadLocalRequest();
HttpSession session = request.getSession(true);
Then when the user calls your Server, you just read back the session id.
HttpServletRequest request = this.getThreadLocalRequest();
HttpSession session = request.getSession(false);
With session.invalidate() you can destroy the session, it's also possible to store objects in the session.
The this.getThreadLocalRequest() only works in *Impl .
you quoted
3> The user id (integer) is returned to the client by RPC onSuccess. The user id is saved in a static variable on the client side.
If a user refreshes his page, the value that is stored on the client side static field will be reset, right? in that case will the session ends? and user will be prompted for login again?
We are using restFB 1.6.12. I am getting the facebook access token in two ways,
1. CLIENT_APP_ID = "XXXXXXXXXXXXXXXXXX";
CLIENT_SECRET = "XXXXXXXXXXXXXXXXXX";
REDIRECT_URL = "XXXXXXXXXXXXXXXXXX";
AUTH_CODE = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
SCOPE = "email,read_stream";
Redirect to facebook as the example. As a result I'll get an
authorization code
https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope=email,read_stream
asking for an access_token using,
https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE
this returns the access token like this,
access_token=CAAHWfjdHDKcBAIL0zHMeJKzJw8Ug7WrrrkNxpBnK7ubnFR1RGtIIZA7T3UPlhCSV0hPJXZAgTcKfBSfHZAyxsndc3RT72XMREjACxnGb0ZCGMZAUgDWH3FgOhnaoSBMgkaQBPDOCCEKcLnznMYSncWS7dVxl9IFrSzeFjF6LKOWB3NTynl5X1&expires=5125218
2. AccessToken accessToken = new
DefaultFacebookClient().obtainAppAccessToken(appid,appsecret);
String token=accessToken.getAccessToken();
It reurns the access token like this,
access_token=517312558337191|5oHY9T3cZICO_TCeK8OdXKg5Y08
If I use the first(1) one, it works fine for first access after then every access throws an error
Auth Token= {"error":{"message":"This authorization code has been used.","type":"OAuthException","code":100}}
If I use the second(2) one, it works fine only for publicSearchMessages but when I access publicEvents or other searches it throws an error
com.restfb.exception.FacebookOAuthException: Received Facebook error response of type OAuthException: (#200) Must have a valid access_token to access this endpoint
at com.restfb.DefaultFacebookClient$DefaultGraphFacebookExceptionMapper.exceptionForTypeAndMessage(DefaultFacebookClient.java:766)
at com.restfb.DefaultFacebookClient.throwFacebookResponseStatusExceptionIfNecessary(DefaultFacebookClient.java:688)
at com.restfb.DefaultFacebookClient.makeRequestAndProcessResponse(DefaultFacebookClient.java:630)
at com.restfb.DefaultFacebookClient.makeRequest(DefaultFacebookClient.java:592)
at com.restfb.DefaultFacebookClient.makeRequest(DefaultFacebookClient.java:556)
at com.restfb.DefaultFacebookClient.fetchConnection(DefaultFacebookClient.java:219)
My question is, what is the difference between these two access token and how can I programmatically generate access code for first one to works publicSearchMessages, getPublicEvents and other searches?
Which one access token is used to works as expected?
Access_tokens allow users to interact with your apps in secure and social ways. While we are removing the use of the offline_access permission, through a migration setting in the App Dashboard, we are now allowing the option to use access_tokens with a long-lived expiration time that can be renewed each time the user revisits your app
When a user visits your site with an existing, valid, short-lived user access_token, you have the option to extend the expiration time of that access token.
extend the expiration time once per day, so even if a user revisits your site multiple times a day, the token will be extended the first time requested. You must make sure to call the new endpoint below before the short-lived access_token expires.
Using the new endpoint below, you will be able to extend the expiration time of an existing, non-expired, short-lived user access_token.
To get the long-lived user access_token simply pass your own client_id (your app_id), your app_secret, and the non-expired, short-lived access_token to the endpoint. You will be returned a new long-lived user access_token; this access_token will exist in addition to the short-lived access_token that was passed into the endpoint
In short Get a page access token – those don’t expire per default; and make sure to do so with a long-time user access token
You can access facebook doc here for more info
To get an extended Page Access Token, exchange the User Access Token for a long-lived one and then request the Page token. This "extended" token for Pages will actually not have any expiry time.
https://developers.facebook.com/docs/howtos/login/extending-tokens/#step1
resolve this by executing a curl request, and saving "Page access token" in your code manually
When a user has an associated HttpSession object and then want to "log out" of the application you would invalidate that HttpSession which in turn would remove it from the map that the ServletContext keep of all sessions. But this only removes it on the server side, what happens on the client side? Does the user still keep keep the cookie with the session ID which now no longer has a corresponding session object on the server and keeps sending this to the webserver? And what happens when the user wants to login again after logging out?
I imagine the sessionId cookie will still be kept, but since this sessionId will not match any session object in the server's memory, it will be discarded by the server next time user tries to login again. On the server side it will be quite transparent, request.getSession() will return a new session object automatically.
I would like to add to the answer of maksimov.
Although the cookie is still present on the client side, it is possible for the server to delete the cookie also on the client side. Spring Security does that when a user logs out. Here's the code:
Cookie cookie = new Cookie(cookieName, null);
String cookiePath = //cookie's path
cookie.setPath(cookiePath);
cookie.setMaxAge(0);
response.addCookie(cookie);
The important instruction is cookie.setMaxAge(0). Setting the max age to 0 means the cookie has to be deleted. Thus, the server may ask the client to delete the cookie by sending it the same cookie with a max age of 0.
I need to implement a simple remember me option in a java servlet with cookies, without using any advanced framework.
First, at login, I create the cookie and send it in response to the browser (client). The value to be stored in the cookie is just a simple hash from username + password.
How should I manage the incoming request from the browser, sending the cookie?
My approach is to check between registered users if there is any user that has the hash from username + password equal to the value in the cookie?
Is this approach correct?
Also, I did not understand exactly what is the mechanism of the expiration date. Does the browser delete the cookie when it is expired, it not, how do I check if the cookie is expired?
As long as you're not using HTTPS the method you suggest is highly insecure. I would suggest to generate some sort of session token (e.g. use java.util.UUID.randomUUID()) and set this as cookie and store it somewhere on the server side so you later can identify the user associated with this session id in the cookie.
This gives you the opportunity to reset a certain session cookie if you think there's some fraud happening and there's no direct relation between the user name/password and the cookie id you use. But note: this method is still vulnerable to a man-in-the-middle attack.
Concerning the expiration: yes the cookie becomes invalid and might get deleted by the browser if it is expired. But you can set the cookie to something in the year 3000, so it lives forever.