I would like to know what is the best practice on how to work with authorized RESTful server.
Say that after login the server provides me a token, and then for each request I will have to provide it as well. My question is: should I save this token in my server's session? or should I do authentication against the data base for each request?
There are several ways. You could only keep it in memory, but then if you have multiple servers in a cluster, you'll have to make sure a request for a given token always goes to the same server, or to distribute the token among all the servers.
You could also cryptographically sign the token data, include the data and the signature in the token, and verify the signature at each request. That way you can be certain that the token has been issued by you, and you can be completely stateless.
Note that, if you're using HTTP sessions already, the token is redundant, since the session mechanism already uses a token in a cookie to track sessions.
Use a session cookie to track an authenticated session instead of hitting the database each time.
Related
If BASIC authentication was not build to handle logging out, what alternate authentication methods exist for authenticating backend services that need to be able to log out?
I found these references stating that BASIC auth is not able to do log
out without some hackiness:
How to log out user from web site using BASIC authentication?
How do I log out?
We are using BASIC authentication to log into backend applications, and FORM authentication for frontend applications. After our team tested the stack on FireFox/IE, it was found that a user would not be able to log out if they logged into the backend services via BASIC authentication on those browsers. The hacks and workarounds are unacceptable to my team (asking user to enter incorrect credentials, making user close browser, use javascript to send incorrect credentials, ask user to clear browser cache, etc), so we are seeking advice on alternative authentication methods that DO allow logging out
EDIT- My temporary workaround for logout:
I am currently getting around this problem by using FORM authentication. One problem is that my backend services rely on the shared frontend login.html form, and another problem is that Postman does not support logging in via a redirected FORM input, and our client Arquillian calls blow up from the login form.
FORM authentication gets rid of the "I can't log out with BASIC" problem, but now I can't authenticate as straightforwardly.
Form based-authentication
If it's okay to keep the session state on the server, you can go for form-based authentication.
Send the credentials in the form, if the credentials are valid, the server will issue a cookie that will be sent back and forth to identify the session on the server. To logout, the session can be invalidated:
session.invalidate();
You also can configure your application to expire the sessions due to timeout:
<session-config>
<session-timeout>60</session-timeout> <!-- minutes -->
</session-config>
Token-based authentication
If you want a stateless mechanism, go for token-based authentication.
The client exchanges hard credentials (such as username and password) for a piece of data called token. For each request, instead of sending the hard credentials, the client will send the token to the server to perform authentication and then authorization.
For the token, you could use JSON Web Token (JWT). It's an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.
JWT is a generic name for the following types of token:
JSON Web Signature (JWS): The payload is encoded and signed so the integrity of the claims can be verified.
JSON Web Encryption (JWE): They payload is encrypted so the claims are hidden from other parties.
The image was extracted from this page.
The token can define an expiration date in the exp claim. For logout, you can remove the token from the client.
You also could keep the track of the tokens in a whitelist on server-side and invalidate them as you need. There's no need to store the whole token on server side though: Store only a token identifier in the whitelist and use the jti claim to store the token identifier in the token.
I suggest you to have a look at Apache Shiro, especially the way session are managed (https://shiro.apache.org/session-management.html).
They have namely abstracted the concept of session so that it can work in various situations: in a webapp (in such case, it's simply a wrapper around the HTTP session), in a standalone app, etc...
In your particular case, the front-end could open and close (logout from) a Shiro session that is shared with the backend layer.
See the sentence:
Heterogeneous Client Access
(...)
For example, a (desktop) application could ‘see’ and ‘share’ the same physical session. We are unaware of any framework other than Shiro that can support this
I'm using JWT authentication for my Spring Boot application. The front-end is going to be a single-page-application.
Should I handle logout functionality on the server side? As far as I understand, there's no way to invalidate a JWT token unless we have a stateful server (storing logged out tokens for the maximum lifetime of a token).
The SPA passes the JWT token every time making a request in its header, and it can delete it from the localStorage when the user visits /logout without making a call to the server.
What are the potential issues? Is this idea used anywhere else? What is the best practice?
First of all you must decide wether you want a statefull server, or not.
statefull server
this is easy. Just send a logout request to the server and throw the session away. That's it. That's the safest way.
stateless server
I like stateless servers because you don't have to manage the state. But of course you have a tradeoff. In this case the securety. There is no way to logout because you don't have a session that you can invalidate on the server side.
So an attacker which steels your JWT-token can use the session until it ends and there's nothing to do to prevent this.
But you can do something to avoid that the atacker can get the JWT Token. Here are some things that you can do and that you have done already right
Don't use cookies to send the token. The way you do it is perfect. Use the header. This is encryptet by SSL and Single-page-app must send it on purpose.
Put a timestamp into the JWT-Token so that it invalidates itselve after some time. But be aware of effects like Timezones and Clocks wich are out of sync.
Put some browser fingerprinting information into the Token like the OS or the Browser version. In that way the atacker has also to fake that.
But these mechanisms are all there to make it harder for an atacker. A real logout is not possible.
Note
If you use JWT correctly your server will have a "state". You have to define a secret that is the same on all servers. That's something you must be aware of, if you use multiple servers.
I logged in as Scott who only has read permission. The oauth2 server(JAVA based) gave me a token. Then I asked my teammate to send me his non-expired token. I updated my Angular application and hardcoded the token that was given to me. I tried to make changes to the api and I was able to make some change.
How can backend api prevent this?
You've successfully implemented a session hijack. This happens because sessions are based on tokens stored in the web page or cookies rather than IP addresses or something. This makes sense because IP addresses can be spoofed while a cryptographically secure session token is practically impossible to spoof.
While you could add strategies to make this more difficult (eg: some kind of hardware token that is involved in cryptographically signing every message), why do you feel you need to? All but the most secure sites rely on this mechanism.
I'm working on a web application for internal use that is driven by many web service requests to another remote server. The internal site maintains its own session, authenticated by username/password credentials that are themselves backed by the web service(i.e. we make a remote authentication call to verify the login to the internal site). The web service requests also require authentication using these same credentials.
We were hoping these web service requests could remain stateless, which means passing the credentials in with every request for authentication. The problem is remembering the credentials to be used(the ones entered during the initial login) in a way that is secure. I'm not aware of any truly safe way to store a password for later re-use - hashing it would sacrifice our ability to use it again. The best we could do would be to encode it in the session scope and hope that no malicious developer will ever try to catch it in a thread dump or something.
Is there a better solution to this that I'm missing? Am I being overly paranoid about the risk of storing an encoded password in memory, or is our approach to this project flawed?
i would suggest to use token based authetication, a token is passed to the user for cheap user verification on the fly. One implementation of this would be to generate a cookie that is passed to the user for session management.
i have not used but you should look at oauth may be example
Ultimately our conclusion was that no, storing user credentials on the server that are re-usable in any way is not safe, so we can't do truly stateless re-authentication on each web service request. We simply had to compromise and preserve a stateful connection that is initiated and stored during the user's initial login.
What is the best way to have a session between a Restlet Java API and GWT? In my app the user will login with a username and password and if it successfully authenticates the userID is returned. This is then stored in a cookie and used in calls to the API. This is obviously completely insecure because someone could just change the userID and start updating and retrieving another user.
Is the best way to also hand a token back with the userID and the API calls must contain that token?
The token is a good way and I've seen it in a lot of implementations. Usually, this is handed over as a simple parameter for each request. Following the RESTful idea you can also just include the credentials in the HTTP request each time.