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.
Related
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.
My Java app server is about to integrate with a RESTful web service and will be polling it for content (JSON) to display to my users.
My users login with their usernames/passwords, which I must then hash + salt and then forward on to the web service with each call. The web service takes the hashed/salted login info and authenticates it (again, each call).
Assuming that I can't change anything on the web service end, and that the webservice expects hashed/salted login credentials as input parameters (along with the API endpoint, HTTP body, etc.), what are some security measures I can take on the client-side to keep the user-supplied username/password safe.
The worst thing I could probably do is just keep them in memory. What are my other options?
The main question is "against what do you want protection". Your user already know they username and passwords, so you can consider that keeping them client side is mostly secure (at least, you don't need to protect those credentials against the user). The salted + hashed password can be used as credential against the web service, so they have the same value as a username / password. Your user already send its password to your server, so implicitly, it already trust your server.
Conclusion : keeping hashes directly in memory is fairly safe in this context.
To limit risk, you should probably not store this hash in permanent storage (database, file on disk, ...).
If you want to ensure that your application stay stateless, it is not a bad idea to store this hash on the client itself (in a cookie). We might argue that this reduce the security somewhat, as it is opens the hash to client side attacks as well.
What's the real problem here ?
The real problem, is that the client needs to trust your server, so you need to take the burden of ensuring that trust is kept. That's why solutions like OpenId are interesting : they limit the trust given to a third party.
My company is building a RESTful API that will return moderately sensitive information (i.e. financial information, but not account numbers). I have control over the RESTful API code/server and also am building the Android app. I've setup the API to use OAuth 2 with authorization code grant flow (with client ID and secret), and I auto-approve users without them having to approve the client since we own both client and provider. We use CAS for SSO and I am using this for the Authorization server as part of the OAuth 2 process when the user logs in to retrieve the token.
I am contemplating various ways to secure the data on the Android app. I've concluded that storing the client id and secret on the device is definitely not going to happen, but am thinking that storing the auth token might work, since it is only risk to the individual user (and really only if they happen to have a rooted phone).
Here are two options I have thought of. They both require me to have a sort of proxy server that is CAS protected, does the dance with the API server, and returns the auth token. This gets rid of the need for storing the client id and secret in the app code.
Here are what I've come up with:
1) Require the user to enter their password to access data each time they startup the App. This is definitely the most foolproof method. If this were done, I'd probably want to save the userID for convenience, but in that case couldn't use the CAS login (since it's web-based). I might be able to use a headless browser on the backend to log the user into CAS and retrieve the token based on what they enter in the Android form, but this seems hacky. Saving the userID is similar to what the Chase app does (if you happen to use this one) - it saves the userID but not your password between sessions.
2) Store the auth token on the Android device. This is a little less secure, but almost foolproof. When the user starts the app for the first time, open the webpage to the CAS login of the proxy server that returns the token (similar to https://developers.google.com/accounts/docs/MobileApps). After the user logs in and the token is returned to the app, encrypt it and store it private to the application. Also, use ProGuard to obfuscate the code, making the encryption algorithm more difficult to reverse engineer. I could also work in a token refresh, but I think this would be more of a false sense of security.
3) Don't use CAS but come up with another way to get an auth token for the service.
Any advice of how others have implemented similar scenarios (if it's been done)?
Thanks.
Well the reason why standards like OAuth are developed is that not everyone has to rethink the same attack vectors again and again. So most often it is your best choice to stick to something already available instead of baking your own thing.
The first problem with clients that are not capable of secretly storing data is that the user's data could be accessed by some attacker. As it is technically not possible to prevent this (code obfuscation won't help you against an expert attacker), the access token in OAuth 2 typically expires after short time and doesn't give an attacker full access (bounded by scope). Certainly you shouldn't store any refresh token on such a device.
The second problem is client impersonation. An attacker could steal your client secret and access your API in his own (maybe malicious) app. The user would still have to login there himself. The OAuth draft there requires the server to do everything it can to prevent this, but it is really hard.
The authorization server MUST authenticate the client whenever possible. If the authorization server cannot authenticate the client due to the client's nature, the authorization server MUST require the registration of any redirection URI used for receiving authorization responses, and SHOULD utilize other means to protect resource owners from such potentially malicious clients. For example, the authorization server can engage the resource owner to assist in identifying the client and its origin.
I think Google are the first to try another approach to authenticate a client on such devices, by checking the signature of the application, but they are not yet ready for prime time. If you want more insight into that approach, see my answer here.
For now, your best bet is to stay on the OAuth way, i.e. having the access token, client ID and client secrect (when using the authorization code grant flow) on the device, and configure your server to do additional checks. If you feel more secure obfuscating these, just do it, but always think of it as if these values were publicly available.
I have a case where non-interactive devices have to push data to a server periodically over HTTP. I am thinking of taking an auth token approach to verify the validity of requests from these devices.
First the device wakes up and initiates a ssl connection and submits its credentials to the server; the server verifies the credentials and generates a SHA based token, based on the credentials + some random input, and sends the token back to the device
This token must be present as a header in each http request that the device sends up. The server will use a servlet filter that looks for this header and filters out messages that don't have it.
There is no sensitive information transferred, I just want to make sure that the device talking to the server is a valid one, and not someone trying to mess around with invalid data. (Wannabe hackers, script kiddies etc..)
The token needs to be stored somewhere where multiple 'nodes' can verify that the request is valid - where do you recommend doing this ?
I can think of 3 approaches
1) Have a separate web service that maintains tokens and does the authentication ( I cringe on the performance overhead of this for each request)
2) Maintain a Set of authenticated token in the Session, and let the servlet container take care of it using the built in clustering support (Not sure if this is the most fool proof way )
3) Use a database to store the tokens and verify it (Considering Redis for this)
Also, I think this approach has a vulnerability of allowing man in the middle attacks, but since the client sends data only for a few minutes I am taking a chance, any better approaches would be welcome.
My opinion:
1) Have a separate web service that maintains tokens and does the authentication
If it's about performance and you have to maintain a lot of devices, I agree that this may become a performance bottleneck.
2) Maintain a Set of authenticated token in the Session, and let the servlet container take care of it using the built in clustering support.
Personal opinion: never rely on sessions in a systems integration scenario. Second, in clustered environments you have to replicate session state between members. Although the container takes care of this it will have impact on performance as well in case of in-memory replication.
3) Use a database to store the tokens and verify it (Considering Redis for this)
If a database is already in place, do it here
Alternative: Use a symmetric hashing approach. After the device authenticated itself return a one time token (digest) each server node can verify independently (based on certain criteria, e.g. a password). "Shared nothing".
BTW: no question, the transport has to be secured (TLS/SSL).
I think that the 1st solution will be the most scalable and flexible.
Try OpenAM with SAML. This is out-of-the-box solution. It has such a filter and can manage repository with such data. A more bulletproof solution could be based on WebSphere DataPower and SAML. If SAML is too complex you can use lightweight, custom solution, but IMHO the 1st idea will be the best.
I am in the middle of developing a PHP social media web application which will be supported by various web services each operating a REST API. Web services will probably be implemented in Java with MySQL data layer but the whole point of what I am trying to do is make it really easy to implement modules in different languages/data stores depending on what is approriate.
So for example when the user logs into the application via a login form the PHP code connects to a web service and POSTs the username and password to check if they should be authenticated. I would normally at this point start a session and store it in a session data store.
Another example could be if a user sends a private message to another user. The message would be POSTed to the private messaging web service which would take care of all the storage. Similarly the web service could be contacted to retrieve messages for a user.
Although I understand how to implement the REST web service in Java and make the connection to it in PHP I am totally unsure as to how to secure the data being passed and make sure that it is the users data being returned. If for example I want to get all of user As private messages how does the web service know to return that users. I could pass that users identifier as part of the GET url but then surely any old user could just figure out the GET url and use it to look up other peoples messages. I thought maybe I could pass over the session identifier and IP address which would allow me to check the session data store and make sure it is the correct user?
To secure the data that is important - like the username/password I thought I would just pass it over SSL.
Hope this explains my problem better.
Thanks
Take a look at HTTP Digest authentication. Most clients should support it, and it means the auth details can be passed securely with each request as part of the headers without interfering with the payload of the request itself.
I think requiring OAuth is a good choice. Your end users should appreciate that other websites don't need to ask usernames and passwords to access their data. As far as SSL, it's clearly worth doing if you can. You'll have to see if the performance trade-off is acceptable.
Keep in mind that your api must mimic the HTTP protocol.
Http is stateless, and by adding any Sessions or so, you're trying to fake an "Alwaysconnected" method.
With a LoginForm, it's like I'll have to send two requests for each calls ;)
These are basically 2 questions.
When privacy is a concern I'd go for the safest option: Serve data over SSL (via HTTPS).
As far as authentication is concerned, there are several possibilities. Basic over SSL is one of them, but a simple login form with a cookie can be another one. (ASP.Net Forms Authentication for example.) This all depends on how you want to implement your authentication mechanism.