Currently, I am writing server-side functionality to verify a JWT provided by the GCP Metadata Server (see https://cloud.google.com/compute/docs/instances/verifying-instance-identity for details).
In my first (dirty) implementation, I fetched Google's certificates from https://www.googleapis.com/oauth2/v1/certs for every incoming request. This works like a charm, but does not really scale. So I want to cache the certificates.
One approach would be to create a cache that stores certificates corresponding with a kid. However, this allows an adversary to let the server make many requests to the Google server by sending false JWT's with random kid's.
So what I rather want, is to store the complete response from the certificate endpoint. However, for this to work, I need know how long before usage the certificates are published.
I could not find anything about this any RFC, nor in the GCP documentation. Does anyone know if this is specified somewhere?
I asked this question to the GCP support and they came back with the following:
We cannot provide any guarantees about certificate rotation. The keys may rotate and additional valid certs may appear within the max-age. The server should pull [1] again to refresh the cert cache if it receives a token with an unknown kid.
https://www.googleapis.com/oauth2/v1/certs
So to summarize: it is only possible to cache individual keys, it is not possible to cache the complete result. Any cache misses should always be rechecked at Google's endpoint.
Related
I have a django application that puts a task in a queue. Another service is used to read that queue and process some files. At the end I need to save the processed files in the database managed by the django application.
I do not want to give the microservice access directly to the database, since I want the responsibility only to be to process the files.
So I wanted to post the changes to django using HTTP request. The problem is that I do not have any authorization at the time, even though I know that HTTP from this type of machine is to be accepted.
For the django application I use JWT as an authorization token. How is the best way to approach this type of problem? Maybe just send a token together to the queue? But how to make such token? It's not certain when the process will be executed..
When you really think about it, there is no need for your internal services to authenticate themselves if they are in the same network.
In that case - You can put Django behind an API gateway (don't write your own, find an open source highly rated project). Then you can control via this gateway which end point is allowed by which traffic source. Then you can easily control end points that are specifically for internal services and which end points need authentication by an external entity.
If they aren't in the same network (which means they are separated by the great gulf of the cloudy net) then the usual way two machines communicate is with an API key. In that case, you can configure your services with symmetric keys, or private/public pair, it doesn't really matter. Machines can be trusted with secret keys. Why would you need to send the token in the queue? If the service is allowed to post results to Django, its allowed to do so for all requests, so it needs to be configured with an API key that tells your API that it is allowed to post processed files.
I have created a web service API and it's architecture is such that the server requires a client to sign the request along with a secret key assigned to it (signature is always different between multiple requests).
Server matches the client's signature with its own computed signature. If they are a match then the server returns the response.
I am wondering if a client should check the response coming back from the server to see if it's from the same application to which the request was made.
Is any kind of attack possible between HTTP request and HTTP response?
Do we need a security signature for the web service response?
It depends. There are a few types of web service APIs out there. Some need strict security other might not. You could have a few types of APIs:
(1) completely opened API. Say you have a blog where you post about writing RESTful services and clients. You host a complete working REST service based on one of your posts so that people give it a spin. You don't care who calls your service, the service returns some dummy data etc. It's just a demo, a toy, no security here, no request signing, nada. It's just plain HTTP calls.
(2) service with an API key. Say you have a web service and you want to know who calls it. This kind of service needs a pre-registration and each client who wants to call your service needs to register and obtain a key first. Do note that the registration is not about authentication or authorization, you just want to know who's using your API (e.g. what business sector they operate in, how many clients they have, why are they using your API for etc) so that you later make some analysis of your own and take some (marketing maybe) decisions of some sort later on based on the data you get back.
There is nothing secret about this API key. It's just an UUID of some sort, the most basic way of differentiating between calls. This again involves only plain HTTP calls with the key as an additional request parameter.
(3) service with an API key and a secret key. This is similar to number (2) but you need to absolutely make sure that the calls are coming from the client that presents some API key. You need this because you probably want to bill the client for how much they have used your service. You want to make sure the calls actually come from that client and not someone ill intentioned that maybe wants to overcharge the client's bill.
So the client uses it's key for identification and a signature of the request with the secret key to actually vouch for it's identity. This again can be plain HTTP calls with the key and signature as additional request parameters.
(4) data "tampered-safe" web services. For numbers (1), (2) and (3) above I haven't considered any message security issues because most APIs don't need it. What's exchanged isn't confidential and not all that important to protect. But sometimes although the data isn't confidential you need to make sure it wasn't tampered with during transit.
Say you are the owner of a shop that builds some product and you want to advertise your product on some partner web sites. You expose a service with the product details and your partners just use this data to display your product details on their sites. Everybody knows what products you are building so you don't need to hide that, but you are paranoid about your competition trying to ruin you so you want to avoid them intercepting the
request and multiplying by 10 all your prices in the responses of your result just to scare potential buyers away.
Number (3) above, although uses the signing part as a way to prove the identity of the caller, also assures the request was not tampered with (server will reject the request if the signature does not match). So if you need to assure an original response you can also sign the response.
For this, the service can provide the client with an API key and two secret keys. One secret key is used by the client to sign their requests while the second secret key is used by the client to verify the signature of the response (using an unique secret key for the server isn't all that safe so the server emits a server secret key specific to each client).
But this has a weak point: you would need to trust your partners that they will indeed validate the response signature before displaying the information on the site and not just bluntly display it. Paranoid as you are you want to protect against this and for this you need HTTPS.
As #SilverlightFox mentioned this proves the validity of the response. The data was not tempered with because it's encrypted. The client does not need to have an extra step to verify the response signature because that verification is already done at a lower (transport) level.
(5) secure services. And now we reach the last type of service where the data is actually confidential. HTTPS is a must for these services. HTTPS ensures the data remains confidential, that it isn't tempered in transit, identifies the server and can also identity the client if client side certificates are used.
So, in conclusion, it depends on what type of service you have.
Make the request over HTTPS to ensure the validity of the response.
This will ensure your data is not vulnerable to a MITM attack. Rolling your own untested encryption/hashing methods is a sure way to open up your application to attack, so you should use TLS/SSL which means that you should connect to your web service API over HTTPS. TLS is the proven and secure way to ensure the response is coming from the application that the request was made to.
I need to centralize authentication to my rest web services and make this authentication the same for all of our webservices. So I started writing an external web service to take care about the authentication.
To keep compatibility, since the authentication was performed using a HMAC signature (signed using a private key) alongside the single request (so there is no token of any sort) I thought to make all web services to send the HMAC included inside the incoming request and the StringToSign (a representation of data used to generate the HMAC).
So the Authorization service can (knowing the private key) try to compose the same signature, if it matches then answers with 200 OK and with a JSON object saying "authorized".
All this communication happens over HTTPS, but I'm trying to figure out what could happen if someone would intercept or modify this answer, making a 403 Forbidden to become 200 OK...
Should I use some sort of way to recognize this is the original answer? If so, what could I do?
I do agree that ssl certificates released by CA's are secure, but how could I make sure my HTTPS layer has not been compromised allowing an attacker to modify authorization responses?
P.S. please provide some standard solution if any, I don't want it to be related to the technology I'm using right now, since each service may use its own stack and I don't really want it to be .NET or something else because there's a proprietary implementation for the authentication mechanism.
All this communication happens over HTTPS, but I'm trying to figure
out what could happen if someone would intercept or modify this answer
This is what the S in HTTPS is for: SSL guarantees integrity of the message. If the attacker forges the request, the client will notice it.
You can ask the experts at #security.
I am creating a web service for end users which will have a front-end in the form of an Adobe AIR desktop app but users will be able to access their data through the website too. User's data will be synchronized between the server and the local data store. The problem is that I cannot get an SSL certificate. Is there a way to make this more secure....
I think I can use something like two-legged oAuth or an Amazon S3 like authentication system?
What do you recommend in such a situation?
The first question is: why can you not get an SSL certificate? I can think of two reasons:
SSL certificates are too expensive
You don't want to have a certificate issued by a third party
If your problem is #1, StartSSL provides free certificates with a 1-year validity or charges $50 for unlimited certificates valid for 2 years (including wildcards). They are recognized by both Mozilla and the Microsoft trust store.
If the issue is #2, why not issue a self-signed certificate and hard-code it into your application? That does not compromise the security of the system at all (only your particular cert will be accepted by the app), but eliminates the need to "get" an SSL certificate from somewhere else.
If you really really can't use SSL, look at challenge-response systems such as Kerberos or anonymous key-material generators like Diffie-Hellman (with an asymmetric key for server identity validation). Many methods exist for secure two-party authentication over an insecure line. The key is that the ID verification step must be challenge-response instead of a "send me your secret" scheme.
I wonder what is the optimal authentication method for services and webservices:
user/password is sent on each request
user/password is sent once to obtain an authentication code that will be sent on each request
Is there any alternative? Which is better? Why?
Depends on the protocol.
If the service requests are in the clear (http), then you might want to consider a secure (https) logon transaction, which gains you a limited-time token to authorise future requests (a session cookie, in effect). Then at least eavesdroppers don't get credentials that work forever, just for a limited period.
Likewise even if the logon transaction isn't secure, at least if it only happens once it's slightly harder to eavesdrop. It's also slightly harder to use.
If you don't care about security, I wouldn't even use a username/password, just an API key. Amounts to the same thing, but if the user doesn't choose it then at least it won't be similar to any of their other passwords, so it doesn't affect anything else when it's stolen.
If you care about security sufficiently that everything is done over https, then it doesn't really make a lot of difference what identification mechanism you use, AFAIK. So do something simple.
Finally, you might care about the security of the authentication, but not about the secrecy of the requests themselves. So, you don't mind eavesdroppers seeing the data in flight, you just don't want them to be able to issue requests of their own (or spoof responses). In that case, you could sign the requests (and responses) using a public/private keypair or a shared secret with HMAC. That might (or might not) be easier to set up and lower bandwidth than SSL. Beware replay attacks.
By optimal are you thinking about performance ? I would suggest to send credentials and authenticate on each request unless you really find this to be a bottleneck. SSL is not enough at all, it only provides encryption and authentication of the web service. But think about client authentication (a client cert can help here) and authorisation, may be not all users of the web service is not allowed to call all methods and all methods calls needs to be logged for auditing. In this case the user identity needs to presented for each call.
I develop and maintain a SOA based core system web service developed in WCF that authenticates and authorises against .Net based clients using windows identity and uses 2-way certs authentication against Java clients and I have no performance problem.
Steve Jessop clarified things for me:
if the credentials are memorized I should provide a transient authentication cookie after they are received,
but if the credentials are digitally stored then I should only use an API key, because anyone who can access the credential storage wouldn't need to access the cookie