I have some problems to understand how to secure REST API.
When a client sign up, the password is hashed and sent to the server through HTTPS.
Then, the server store hash(password+privatesalt).
When the client consumes a rest service, he creates the request and a signature HMAC-SHA1 with his own password (like here).
Server side, how to sign the request to compare with the client signature if the password is hash-salted in the database ?
I know the data appears in clear over the web, but I just want to authenticate the user.
You are right. If the password is stored hashed & salted on the server side, it is not possible to verify the HMAC computed on the request: a MAC required a shared secret between the client and the server.
Some solutions could be:
using a dedicated API key which is not the user password. As far as I know, this is the AWS choice. The password is used for administrative operation on the user account (e.g. changing the billing contact) and the API key is only used by the API client. In this case if this API key is compromised, it is relatively easy to revoke it and generate a new one with a more limited impact on the security.
using HTTPS with X509 client certificates. This is a more heavyweight solution and probably more complex to setup. However it is transparent for the API users since the authentication is moved to the transport layer of the protocol.
Related
Let say i have an android app with Reddit OAuth2 authentication. I initiate authorize request with my client id and user accepts the consent. Now i got the authorization code which will be exchanged for token in my server via HTTP request. This process will protect my client secret as it is in my server, but it actually doesn't. Anyone can take the client ID from the app by decompiling and initiate authorize request to reddit and exchange code for token from my server. They don't even need to know secret to get the token.
How can one protect the API against this kind of misuse (or attack?)?
Is there any way i can allow my API to accept requests only from my app and reject other requests (using SHA256 or etc.)?
I have looked up and studied about PKCE. But this is not useful in case as it only protect again code sniffing/intercepting and accept only the original authorize request initiator.
You will probably want to store a secret. When first opening the app (and after certain interval of times to keep it secure) you will need to generate a keypair. Store the private key on the device's Keystore and send over the public key to your backend. When authenticating to your api, sign the client's secret with the private key and verify it using the public key on the backend.
Note that this will induce substantial overhead to your login process. Because mobile devices are not necessarily well equipped to perform cryptography. Though this is less and less true.
EDIT: Your keypair will need to be issued from a CA you trust, otherwise this is all useless.
I'm building a REST API using Elixir's Phoenix framework. In the API, I need to authenticate the user by phone number i.e., via sending an SMS OTP code. After authenticating the user, the Auth server sends the Access token and Refresh token to the client. The client(mobile app) stores those tokens locally and sends the Access token in the HTTP header as Authorization: Bearer <Access_Token> in every request to resource server. My actual question is, how do resource server validates the Access token that is received from the mobile app/client?
Does resource server needs to contact Auth server to validate the Access Token? That would a lot of overhead. Please help me understand RestFull API Authentication.
Thanks for taking the time to read my question.
It sounds like you have everything working up to validating the token. You are going to need the public key for the server that signed the token. It depends on what auth server you're working with on how you get that. In some cases you may be able to preload this key as a configuration setting on your backend. Otherwise you can probably get it via https request to the auth server. Most auth servers these days I expect to provide a JWKS api that you can use to get the keys you need. Then with the token and the public key you can use your elixir jwt library to validate that the token you have was signed by the server you trust, meaning the SMS code was validated, and you can proceed with whatever is needed in the backend to handle the request.
If you're using Joken for elixir you can review https://hexdocs.pm/joken_jwks/introduction.html and https://hexdocs.pm/joken/introduction.html for more information.
how do resource server validates the Access token that is received from the mobile app/client?
The same way a nightclub bouncer verifies your driving license as proof-of-age to let you in: by validating the authority and signatures, but it does not need to phone-up your DMV to verify that your license is real because it trusts the signatures (in this case, cryptographic signatures).
That said, some systems do use "reference tokens" which are short (say 32 bytes) of meaningless random data which are used as an unpredictable record identifier for some user-permissions record held by the authorization server. The resource-server will need to contact the auth server initially, but then it can simply cache the auth result itself for some time window.
I am creating a Flutter app which uses Node Js server API. For the authorization I decided to use JWT with private/public keys. Communication between Server and mobile client uses HTTPS. Flutter app stores the token in a keychain (ios) or a keystore (android). My question is related to the need of the additional security measures implementations. I am wondering if the following points are required:
Verification of the server responses with public key by checking the token to identify the server
Verification of the client requests with the private key on the server side (client signs the token with public key)
Are these really needed in order to avoid man in the middle attacs? My objection is related to the performance related to signing/verifying tokens for each communication.
Thank you
I've used JWT our mobile apps for security and these apps had taken the security test(3.party company). The company says: secret your stored token or any keys.
And we know doesn't enough just JWT security. We wrote a custom encrypted algorithm to hide JWT (like sha-1) so we encrypt JWT to this.( you must write encryption code client-side & backend side)
Normal jwt : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
After encriypt: xxs{4=-23dasdxe3 (example)
We passed the security rules with this solution.
I have a backend which exposes a RESTful API which is currently 'free for all' (but uses https).
I now want to add RBAC (role-based access control) and JWT seems the way to go and I read a lot about JWT, but don't see the advantage of using RSA over SHA to sign the token.
Assumption is that the user has authenticated and obtained a key, be it shared or public/private.
Now, it seems to me that in both cases - SHA or RSA HMAC - both parties (client and server) must have the shared key, or their half of the private/public key in the case of RSA. And the server must find that key (in a table or database) based on a claim in the JWT in order to verify the token's signature. Once it has confirmed the purported user in the JWT it will then authorise the request using the configured roles.
So what are the advantages of RSA in that scenario ?
I assume you're talking about RSxxx (e.g. RSA256) and HSxxx (e.g. HS256 (HMAC-SHA256)) algorithms here. The main difference is that HS256 is an symmetric algorithm while RS256 is an asymmetric algorithm. Symmetric algorithms just use one key (or secret) for signing and verifying, whereas asymmetric algorithms use the private key to sign and the public key to verify the token.
If you share the secret used for HS256, everyone knowing the secret could issue or modify and re-sign a token. That would defeat the purpose of the signature if you share the secret with the client. In case of RS256 or any other asymmetric algorithm, only the authentication server knows the private key and anyone who need to verify the token can use the public key to do so. The matching key is usually identified by the KID (Key Id) claim in the header of the token.
But usually, signing and verifying is only done on server side, the client does not need to verify the token and thus does not need to know the key or secret at all. Therefore you can in case of a simple service, when authentication and resource server are the same, still rely on a symmetric algorithms. But once you have one separate authentication server for several resource servers, asymmetric algotrithms should be used.
Thanks for the response, that does help make it clearer.
So basically, for a simple RESTful API, there is no real advantage using RSA over HSA.
Some points that may help others about token-based authentication:
Preamble: the following are all in the context of using SSL.
Firstly, a token is a substitute for username/password credentials: if a client has a token, it is equivalent to having username/password. It took me a while to figure that out. A bit like using a badge at a corporate printer: instead of entering username and password you just place your badge (the token) on the printer and it knows who you are and prints your document.
However, tokens make using an API much simpler because
the client simply adds its token to the http header,
the server only verifies the token,
neither have to deal with authentication flows involving username/pw and managing session cookies.
But the downsides are that
losing the token is like losing the username/password, and
in a complex system involving many components, tokens would have to be shared across all involved backend servers.
Secondly, the client doesn't strictly need to verify the token - it only needs the token - if someone gives you a key to their house or car, you don't typically check the key, you trust the person (maybe sometimes foolishly so) and use it. So a simple random string can serve as a token; the server maintains a simple table correlating tokens to users, no keys involved at all. If a client sends a token that the server doesn't have --> access denied. If it has a matching token --> look up the user that correlates to the token (typically followed by authorisation).
Thirdly, the server typically generates a token either based on trusting the client, or after the client has somehow authenticated, e.g . oauth. Afterwards, the client just sends the token with every request and the server looks it up in its table. However, such server-side tables for random-string tokens may become large and have to be persistent, so either a database or a file is required, and they are typically comparably slow, require maintenance etc, so enter using cryptographic signatures and jwt:
Fourthly, tokens with signature:
the server signs the token and sends it to the client - but the server does not have to store it, also no session cookies as described above
the client stores the token securely and sends it with every subsequent request (just like with a random string token)
the server receives the request, calculates the signature of the jwt, and compares it with the signature of the token sent by the client. Note that there is no file or DB lookup, only computing the signature again and comparing it with the signature sent by the client. If the signatures match then the token must be the same as the one the server issued and hence the jwt header and payload are also the same as issued by the server
the server now interprets the payload, esp. the user (and typically performs authorisation)
So, using jwt means the server does NOT need
a database or file with user names and tokens
to save tokens
to maintain session cookies
It only needs to create and compare a signature. And for that it needs a cryptographic key. This can be a symmetric key for a simple API or an asymmetric key for more complex systems where public keys must be shared.
Hope this helps some other tortured souls who grappled with this topic.
Background:
I'm designing the authentication scheme for a REST web service. This doesn't "really" need to be secure (it's more of a personal project) but I want to make it as secure as possible as an exercise/learning experience. I don't want to use SSL since I don't want the hassle and, mostly, the expense of setting it up.
These SO questions were especially useful to get me started:
RESTful Authentication
Best Practices for securing a REST API / web service
Examples of the best SOAP/REST/RPC web APIs? And why do you like them? And what’s wrong with them?
I'm thinking of using a simplified version of Amazon S3's authentication (I like OAuth but it seems too complicated for my needs). I'm adding a randomly generated nonce, supplied by the server, to the request, to prevent replay attacks.
To get to the question:
Both S3 and OAuth rely on signing the request URL along with a few selected headers. Neither of them sign the request body for POST or PUT requests. Isn't this vulnerable to a man-in-the-middle attack, which keeps the url and headers and replaces the request body with any data the attacker wants?
It seems like I can guard against this by including a hash of the request body in the string that gets signed. Is this secure?
A previous answer only mentioned SSL in the context of data transfer and didn't actually cover authentication.
You're really asking about securely authenticating REST API clients. Unless you're using TLS client authentication, SSL alone is NOT a viable authentication mechanism for a REST API. SSL without client authc only authenticates the server, which is irrelevant for most REST APIs because you really want to authenticate the client.
If you don't use TLS client authentication, you'll need to use something like a digest-based authentication scheme (like Amazon Web Service's custom scheme) or OAuth 1.0a or even HTTP Basic authentication (but over SSL only).
These schemes authenticate that the request was sent by someone expected. TLS (SSL) (without client authentication) ensures that the data sent over the wire remains untampered. They are separate - but complementary - concerns.
For those interested, I've expanded on an SO question about HTTP Authentication Schemes and how they work.
REST means working with the standards of the web, and the standard for "secure" transfer on the web is SSL. Anything else is going to be kind of funky and require extra deployment effort for clients, which will have to have encryption libraries available.
Once you commit to SSL, there's really nothing fancy required for authentication in principle. You can again go with web standards and use HTTP Basic auth (username and secret token sent along with each request) as it's much simpler than an elaborate signing protocol, and still effective in the context of a secure connection. You just need to be sure the password never goes over plain text; so if the password is ever received over a plain text connection, you might even disable the password and mail the developer. You should also ensure the credentials aren't logged anywhere upon receipt, just as you wouldn't log a regular password.
HTTP Digest is a safer approach as it prevents the secret token being passed along; instead, it's a hash the server can verify on the other end. Though it may be overkill for less sensitive applications if you've taken the precautions mentioned above. After all, the user's password is already transmitted in plain-text when they log in (unless you're doing some fancy JavaScript encryption in the browser), and likewise their cookies on each request.
Note that with APIs, it's better for the client to be passing tokens - randomly generated strings - instead of the password the developer logs into the website with. So the developer should be able to log into your site and generate new tokens that can be used for API verification.
The main reason to use a token is that it can be replaced if it's compromised, whereas if the password is compromised, the owner could log into the developer's account and do anything they want with it. A further advantage of tokens is you can issue multiple tokens to the same developers. Perhaps because they have multiple apps or because they want tokens with different access levels.
(Updated to cover implications of making the connection SSL-only.)
Or you could use the known solution to this problem and use SSL. Self-signed certs are free and its a personal project right?
If you require the hash of the body as one of the parameters in the URL and that URL is signed via a private key, then a man-in-the-middle attack would only be able to replace the body with content that would generate the same hash. Easy to do with MD5 hash values now at least and when SHA-1 is broken, well, you get the picture.
To secure the body from tampering, you would need to require a signature of the body, which a man-in-the-middle attack would be less likely to be able to break since they wouldn't know the private key that generates the signature.
In fact, the original S3 auth does allow for the content to be signed, albeit with a weak MD5 signature. You can simply enforce their optional practice of including a Content-MD5 header in the HMAC (string to be signed).
http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html
Their new v4 authentication scheme is more secure.
http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
Remember that your suggestions makes it difficult for clients to communicate with the server. They need to understand your innovative solution and encrypt the data accordingly, this model is not so good for public API (unless you are amazon\yahoo\google..).
Anyways, if you must encrypt the body content I would suggest you to check out existing standards and solutions like:
XML encryption (W3C standard)
XML Security