I am building a public facing REST application for clients to access. In trying to develop security for it, I looked at how AWS handles their REST authentication using an access key and secret key to sign the message before sending to the AWS server. So I coded an example with Jersey, JSP, and javascript (jsonp) to test, and it seems to work ok.
1.) On page load the JSP takes the client's access key and date/time (converted to EPOCH) and writes out to the page. It also takes those two pieces of information and combines them with the client's unique secret key via HMAC-SHA1.
2.) When I execute the JQuery ajax request, I pass in all three pieces of information.
user access key
date/time (EPOCH)
signed message
3.) On the Jersey side I take the access key and date/time and check a database for the users secret key. Then I perform my own HMAC-SHA1 signature and compare that to the signed message from the user submitted signed message. If they match, then allow them to use our web service. I also check the date/time and only accept messages signed within the last 15 minutes.
My question is, is this secure enough?
This isn't a complete answer, but I don't have the points to just comment quite yet. I would add to your security a salt on the server side. Please see this article for a good discussion on hashing using Master Keys and salts.
Related
I'm trying to create RestApi first time. Looking for assistance after reading text present online.
My requirement is, I want to create an rest api which will be having username and password. Password will be in encrypted format. So when this api client will request to a web server, that password will be decrypted first on server side and then if the user name and password authenticates then it will send back a temporary token with expiry date. Then again that token will be used in rest api to request data from the web server in xml format.
How can we achieve this ?
And I also want to understand if we encrypt a password in client server then how its get decrypts on web server side. Is the same instance travels from client to web server side while making request ?
Second, The data which I'm trying to consume from web server are the email ids of users which registers on website. My question, If user is getting registered on website then website must be storing those email ids somewhere like in database right ? And my restApi will be accessing the code on web-server side which is responsible to get email ids from database in xml format. Is my understanding correct ?
First, don't concern yourself directly with encrypting details client-side and decrypting them server-side. If you are using TLS/HTTPS (which you should be) then all is well, everything is already encrypted.
The token generation is slightly more difficult but still easy enough. A commonly used and simple to implement method is to use JWT tokens. The general idea is that you create a JSON object like the following:
{ "userID": "FC5A47CC", "expiry": "12/10/2017" }
And then run it through an HMAC using a key only your server knows. You append the result of the HMAC to the JSON object using base64 encoding and then send this to your client after they have logged in.
Using this method, authentication is very fast, as your web server won't need to make any requests to your database server to determine if the token is valid. You can read more about JWT here. I've answered a similar question in more detail here.
As your question asks, these userIDs will obviously need to be stored in your database.
Seems like you want client app to consume resources on behalf of user. I propose OAuth 2.0, which provides mechanism, which you have described to access protected resources without storing passwords. Client app requests a username and password from the user (for example by using a login form) and then send that credentials to the server. Upon receipt and validation server returns token to the client. Client stores token locally and discards username and password. All subsequent request are authorized by token, which can be accomplished using a custom HTTP header, for example X-Auth-Token. Server can optionally provide a refresh token along with the access token, which is used by client to obtain new access token, once current expires. HTTPS/SSL technology is required by OAuth 2.0, so data over wire will be encrypted.
There are 4 roles defined by OAuth 2.0 :
1) Authorization Server — does identity verification and grants token to the client app.
2) Resource Server — Server which hosts actual protected user resource.
3) Resource Owner — User willing to provide access to his protected resource.
4) Client — application that gets access to a user’s resources.
You can use Spring Security OAuth framework to implement this requirement.
This kind of question is already ask for IOS
How To Secure Web Service Without Login
but still I am not able to find the solution to make the web service secure without user authentication.
I have a web service made specially for android app as of now. I want that all the api hit should be only from my android app to the server. No one hack it and hits the api from restclient or postman.
How server will identify that request is coming from android app explictly the developed one and respond accordingly.
Method 1
I thought to do generate an api key and send that api key in request header which can be verified at server end. If key matches then server can assume the request is coming from whitelisted android app. But problem is that key has to be present inside android app which can be easily decompiled and can be hacked. Attacker may send api request directly from there app/web/ios rest client after obtaining the key .
Method 2
Api key can be easily stolen even kept in sharedprefernce. So i kept that in native code using jni which can not be decompiled, but that code can be dessembled and key can be read from there. So keeping the key within apk is unsecure. So this approach failed.
Method 3
I thought not to keep the original key inside app initially. but to use Asymmetric Keys. Private key was kept at server and encrypted key which got generated from public key was kept in android app.
API is called with input as encrypted key and server decrypts API key using private key and returns that key in response. that key is kept in the application scope and for subsequent request that key is sent in headers. So from now request becomes unsecured as original key is not known to attacker. but problem comes here
that
encrypted key + 1st api is exposed in the apk
Hacker will call the Api sending encrypted key along with url and get the actual key in response then that key can be used anywhere. So question is how to secure it so that no one can exploit the resources without login. I have to ensure that hit is coming from app only.
Method 4 It required login with google providing JWT Id token which can be easily verified at server end. but I dont want user to login with google. Just to know request is coming from android app only.
I'm afraid the only possible secure option is option 4.
In any case android app can be easily hacked without having 3rd party service that verifies correctness of the token.You don't have a choice.
My current system architecture for a web application looks like above. Essentially, its just one code base, that is being deployed in different contexts, so for instance, app1.localhost.com, app2.localhost.com.
These are my current challenges -
I need query my webservices using ajax calls from user browser. But, somehow I need to tell the webservices, that the request is coming from user1 for app1 or user2 or app2. Accordingly, the webservice can go query the right schema in the database and return the results.
My webservices need to be stateless.
I cannot have the user tamper with the request from the browser.
Is this a flawed model? Are my expectations out of standard way of doing this? What is the best way to realize this architecture?
Let's go through this step by step.
So your webservice needs to know the application and the user.
Easy: just include it in the request as a parameter or as part of the url.
Same goes for some information possibly provided by the user.
The challenge comes with the requirement that the user must not be able to change the request.
This is typically achived by cryptographic signing the request (or the sensitive parts). I kind of assume that replay attacks are also an issue.
Create a certificate for the apps.
On the application server create a nonce.
Sign the nonce, the application name and the user name using the certificate.
Include nonce, servername, username and signature in the request used for the ajax call.
Check nonce, servername, username and signature match in the webservice
Check also that the nonce wasn't used before.
Checking the nonce does require some state, but just a list of nonces. If you make the nonces increasing you can even discard any nonces much smaller than the last one you received, limiting the amount of state even more.
You should check if something like this exists as a ready made protocol, because it is always a bad idea to create your own security relevant protocols.
I am using AngularJS along with REST API on Java EE 7 backend.
The project is deployed on a Wildfly application server and I have some questions regrading securities:
To Encrypt/decrypt data I am using CryptoJS to encrypt and decrypt on server side ( Java ) but apparently we have to send the passphrase in clear, the cipher and salt are only encrypted.
My question is why the passphrase is clear text ? it should be secret and then encrypted as well no ?
For the REST API, what is the standard to use for Java EE 7, HTTP security header (basic-auth) ? Json Access token ? and how it really works, where to store user session/token, on a cookie ? I just want to know how to do it with Angular.
Maybe I can use the classic JAAS with form-based authentication and then having request.login() on server side to be authenticated then my EJB will be all protected by #Role.
What is the way to protect pages in AngularJS ? For the moment I am using the web.xml and putting the URL patterns, maybe there is a better way ?
I already found lot of examples like this:
AngularJs and Jboss and JAAS ( omnisecurity )
how to integrate angularjs and java jaas based authentication?
Some users mentions this:
* index.html page should contain token inside html to avoid CSRF
* token shouldn't be stored in a cookie storage
* Each request should be signed with header param
* Server should validate every request by passed header
* If cookie usage is a must you should validate referer in order to prevent CSRF
But there is not concrete example on how to implement this, especially the CSRF.
To Encrypt/decrypt data I am using CryptoJS to encrypt and decrypt on
server side ( Java ) but apparently we have to send the passphrase in
clear, the cipher and salt are only encrypted. My question is why the
passphrase is clear text ? it should be secret and then encrypted as
well no ?
As soon as you are sending a key (passphrase?) in clear - the encryption is useless.
To achieve reasonable client-server security, use the HTTPS. Simple, effective and much more secure. Generally it is a bad idea to encrypt on the web application side, as the user or a 'man-in-the-middle' can retrieve or modify the key and data.
The different case is end-to-end security, when the client encrypts, posts encrypted data and they are stored/processed as they are, with the encryption key available only to the user. If it's not the case and the service needs the data for further operations, the HTTPS is the way to go.
For the REST API, what is the standard to use for Java EE 7, HTTP security header (basic-auth) ? Json Access token ? and how it really
works, where to store user session/token, on a cookie ? I just want to
know how to do it with Angular.
Effectively you listed you options. This is your decision. Every option has its pros and cons. Basically - if you're talking about (REST) services, it shouldn't matter what technology is used.
For the REST services called directly from the browser I'd omit the basic authentication (otherwise user would get the pop-up authentication window)
You can use the JWT token (signed by the application secret, just add some expiration date), but then you cannot 'logout' the user, just wait until the token expires. The advantage is, that the token is 'self-sufficient' and you need not to worry about the session management. The client sends the JWT token in the Authorization HTTP header, you just decode it, validate and then you can assume the identity from the token.
Another option is a session token (cookie or sent as an Authorization header), where you need to manage the sessions (store the tokens, clear the token out on logout, ...). Using the app server session cookies makes your services unusable by other applications (still a question - do you want/need the services to be reusable by third parties), but you achieve built-in authorization (JAAS , Roles, ...).
Maybe I can use the classic JAAS with form-based authentication and
then having request.login() on server side to be authenticated then my
EJB will be all protected by #Role.
Indeed, this is a way how you authenticate and authorize the user and issue a token (jwt, cookie, other...).
What is the way to protect pages in AngularJS ? For the moment I am
using the web.xml and putting the URL patterns, maybe there is a
better way ?
The default web authorization should be ok.
Still - keep it simple. According to my experiences the static resources (web pages, images, scripts, css) should be static and it shouldn't really matter if they are publicly available. The important is the execution (operations, data, ...) are exposed as the services and that's the point where you do proper authentication and authorization.
Have fun
I'm working on a small piece of middleware based on RESTlet that's providing a REST API to several back-end systems.
There for, my JAX-RS Application requires credentials for some of its methods to authenticate calls to back-end systems using (clear text) user name and password.
So far, I found a lot of documentation on Authorization/Authentication, but all of it only goes as far as validating access to methods and providing user groups. None of it seems to give me the possibility to pass the users' credentials to the actual methods. Is there a nice way to inject them without being REST framework dependent?
A common (and not very secure unless you're on HTTPS) strategy is to put them in the HTTP Request Header if you just want plain authentication. On the server side you can use those values and do whatever you want with them, including evaluating access to the requested service. If you use JAX-RS is relatively simple to create a utility method that does that.
If you also want to ensure integrity you may want to include an hash obtained hashing the concatenation of all param string representation with a simmetric key (known both by client and server). On the server side you recompute the hash to check if the request has been tampered or not. In this way even if an eavesdropper get your credentials sniffing the netwkork traffic he would have difficult times in sending fake requests or tampering a correct one.