I am writing a JAVA REST webservice, I'm trying to understand how it all works, but I've managed to make simple methods where my client will send a JSON with information, and the server does something with it. Very easy.
So what I am doing: My client wants to create a new object, for example, an account, yet I don't want everyone on the world to simply send a json to my website and create an object.
However I don't want to filter on IP's, because I got no clue who or what will use my client application.
So what have I done to prevent everyone to simply send data? I've created a secret key for the players and they use it like:
http://[website]/[Applicationname]/Webresources/[SECRETKEY]/create
(Send a json with the request)
This works, since now only people with the secretkey can create, and they will only get a secret key if I give it to them. I am pretty sure they won't be giving this secret key to others, since if they do so, they only screw themselves, their services will get loads of fake data...
Yet I want it to be more secure, so noone can obtain the key no matter what, and I don't know if HTTPS will also hide the domain + parameters, I think not, right?
So my question is: how can I send a secret key, without anyone EVER finding out what the secret key is?
Using HTTPS, send POST requests for which you specify your secret key data in the body. You should specify the Content Type to be "x-www-form-urlencoded". The content should be encoded, and adversaries who intercept the url will not be able to decipher the body.
However, your implementation is pretty insecure for sending each request by using the secret key in the URL path, as any adversary intercepting the REST call will know the secret key just by looking at the url. It's way harder and longer to implement but if you can do a Basic Auth or OAuth authorization service, it will authorize only specific users with valid tokens issued to them to access the service, which is the general way of securing your REST services.
Related
I'm new to cryptography, I want to implement https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-10 to my spring-boot application (requirement from the client). The client asks me to implement a header something like this,
Authorization: Signature keyId="Test",algorithm="rsa-sha256",
signature="SjWJWbWN7i0wzBvtPl8rbASWz5xQW6mcJmn+ibttBqtifLN7Sazz
6m79cNfwwb8DMJ5cou1s7uEGKKCs+FLEEaDV5lp7q25WqS+lavg7T8hc0GppauB
6hbgEKTwblDHYGEtbGmtdHgVCk9SuS13F0hZ8FD0k/5OxEPXe5WozsbM="
I have no idea about the Authentication signature generation based on this specification.
Anyone help me to understand these terms in a simple manner
what is the KeyId & usage of it?
what is the signature value and how to generate it?
I have no idea help me to understand this
What you see here is yet another layer of protection in case someone brakes the TLS. The documentation states it like this:
For high security transactions, having an additional signature on the
HTTP header allows a client to ensure that even if the transport
channel has been compromised, that the content of the messages have
not been compromised.
So what you really want to do is to use some kind of Message Authentication Code (MAC) so even if an active attacker has the ability to manipulate the message sent, the MAC will not match and the whole message will be rejected by the server.
I have looked through the docs and implementing this stuff is not a trivial matter. But it looks like there are libraries already present which can help you achieve this. First Google hits:
https://github.com/tomitribe/http-signatures-java
https://github.com/joyent/java-http-signature
Regarding keyId:
The keyId field is an opaque string that the server can
use to look up the component they need to validate the signature. It
could be an SSH key fingerprint, a URL to machine-readable key data,
an LDAP DN, etc. Management of keys and assignment of keyId is out
of scope for this document.
In short - you decide what it is going to be. It needs to be something that allows you to identify the subject and enables to verify the signature in the first place.
I saw many services, mainly map services like GMaps or MapQuest, that requires users registers previously to obtain an appKey. Later, on each request the user must attach the appKey like http://server/service?appKey=sdf7dfj34.
I understand this kind of appKeys are insecure and are mainly usefull to know the useage of your service. Anyone can see your appKey and make use on its own app.
I saw other services that, on registration proces, requires you put the domain where you will execute your code. This way they can check if the domain from which the request is made corresponds to the appKey generated for that domain.
My questions are:
Is this kind of control secure?
Can I ensure the user is really the one who register.
If the domain-appKey options is possible, how can implement it? (I'm using Java-Spring).
I must clarify my intention is users can requests data via appKey using JavaScript+AJAX.
Thanks.
Can't you just include the domain in the appKey? E.g. part of the appKey is hash of the domain (for simplest key you can use MD5 and base64 to encode hash bytes).
Then to validate domain you hash the request's domain and compare it with the appKey.
To clarify:
User wants to obtain an appKey for domain "user.domain.com".
You hash the "user.domain.com" to SOME_DOMAIN_HASH_TOKEN.
The appKey would be SOME_GUID + SOME_DOMAIN_HASH_TOKEN (+ may be something else)
User sends the appKey to your server from some domain.
You hash the domain from request and compare with hash from the appKey.
If both are SOME_DOMAIN_HASH_TOKEN the domain is valid.
I need to encrypt a string at client side and send it to the server.
Once there I need to decrypt it.
Is the Using Password-Based Encryption the best solution?
I need it because I have a voting mechanism, where I send ajax posts to vote an entry.
This mechanism use the Facebook id from the current user. My goal is to encrypt the FB id from client side to avoid that they hack it by sending requests with differents ids.
If a second post with the same id is sent I will block the vote.
Once the id is decrypted I will check if it is a real FB user using the graph.
Javascript encryption won't help here. Any good detective/hacker can see how it's all done on the client and see what the data was before it was encrypted and see how it's encrypted.
The only way to prevent a user from voting multiple times is to have the vote tied to an account or token that you can both verify on your server and tie to a particular user that isn't easy for the user to make lots of different accounts. In general, you probably can't stop this entirely, but you can make it enough trouble that most won't do it by making it require enough steps (including some sort of captcha so it can't be automated).
SSL will protect client/server communications, but won't do anything to stop the client from doing things you don't want them to do.
“Encryption” does not make any sense here as you have already been told (because the value that would be encrypted client-side could be manipulated before you encrypt it), and SSL does of course not solve this problem either.
Send the access token of the user to the server instead. And then either make a request for user data with it (/me), or debug it – then you will know that the request is genuine, because a user can not “fake” an access token for another user.
Considering that there is no authentication an HTTP fingerprint can be used to check if requests with different userId come from the same user.
Fingerprint will be create from HTTP request data like:
-user agent
-language
-IP
-charset
and other data present in the http request.
This is an existing system with a login screen, now I expose some services as REST service. I build an authentication-token login system for this Rest(jersey) service. User sends username-password then server returns a token calculated as;
sha1(username+password+currenttime(or any random number))
User will use this token to login the app for further requests. And server keeps a copy of the token in the database with a time stamp and user id, and logins that user if timestamp is valid.
Considering HTTPS will be used, a few questions;
Does everything looks ok in my design? (generation of hash and the way I save in DB) Looks to me the weakest point is I need to send plain username and password over POST request, but since it is HTTPS I guess it will not be a problem.
another thing, for the first request, since it is an existing system I dont have the user passwords in my DB but keep a salted hashed version of them. Which I guess not safe to give all the clients this salted algorithm to send me a hash of their passwords so I compare hashs but not the passwords. does this make sense=
1/2- I'd suggest POSTing the username/password to the server, which can then return the token in the body. Makes most sense to me: you're not actually storing much on the server, so PUT would be wrong, and a query parameter doesn't make sense at all. Headers are supposed to be somewhat consistent across requests, so they don't make sense either. When actually communicating using the token, feel free to use a query parameter or header. Doesn't really matter.
3- I'd pick a slightly longer hashing algorithm (sha256?)
I would typically pass the token in an HTTP header.
Whether you use POST or PUT shouldn't matter.
Something else I would suggest to help prevent replay type attacks would be to include a nonce (ever increasing value) with each POST request. The server would then track the last used nonce and prevent any requests that use a previously used nonce from executing.
i intend to use JSON to implement a client server communication. My goal is for a Java-server to receive data via HTTP-Post from an Iphone-app.
I'm concerned about the fact of how I can be sure, that the data the Java-server receives only come from the Iphone-app? It may be possible that somebody else is catching the Java-Server URL and send rigged data?
Do I have a chance to recognize that? SSL encrypts transferred data only, but doesn’t solve the problem, i think.
kind regards
stormsam
You could send a token that is hardcoded into your application. Everything that comes without this valid toke should be rejected. Or you can use .htaccess and specify a user and password within your app.
You could use public key encryption, with users having their own keys and you keeping track of who are the legitimate users. This is the most reliable scheme I can think of. That, or giving each user a username and password. However, it's probably a lot more trouble than it's worth, and still doesn't protect against users that have registered with you but are still malicious.
Embedding a token in your application and then sending it with requests, as Cyprian suggests, is probably the easiest scheme and would probably work pretty well, but might be relatively easy to reverse engineer.
A somewhat better solution might be to program into your app a function that transforms any given input into an output; then, your server responds to a request by giving the app a piece of data to transform, and checks the result. A client that passes the test gets a session token which allows it to proceed. This does require an extra round-trip for authentication, though. And it's still not immune to being reverse engineered, since all the information needed to do so is stored in the app that's present on the user's machine.
Assuming you can reasonably protect your iOS app from being dissambled, you could use "signed requests" like the Facebook API (and probably others):
You'll need a shared secret on both client and server (e.g. a random string/byte array). The iOS app then hashes all request parameters plus the shared secret and appends the hash as additional request parameter, e.g. myserver.com/ws?item=123&cat=456 becomes myserver.com/ws?item=123&cat=456&hash=1ab53c7845f7a. Upon receiving a request, the server then recomputes the hash from the regular parameters and the shared secret and compares it to the value sig parameter. If both are equal, the request is considered valid (assuming integrity of your iOS app).
An advantage of this method is that it doesn't require additional round trips to fetch any one-time/CSRF-prevention tokens and does not require encrypting requests and responses (as long as you only care about the integrity of requests, not confidentiality).
You might have to take a look at this. It may give you some directions.