Let's say I have 2 servers (server and authenticator), and I have a client. My end goal here is to be able to identify the client on server. My solution was to come up with a token/secret system like OAuth: client has a token and secret. It passes it to server. Server passes it to authenticator. If valid, server allows the request.
Obviously, this is nonoptimal just for the number of requests being made. The reason authenticator and server are separated is because this is for a decentralised service-- any number of servers may be used, and it's impractical to ask client libraries to register on each server.
So, the question remains, what's the best/correct way to do this? The goal is to create a system that is decentralised, but can still have clients identify themselves in a relatively secure fashion to the server.
Disclaimer: I'm not a security expert so I could be off-base here and in actual implementation there seems to be a number of security issues that would need to be ironed out.
In the broadest sense, could you have the client supply credentials to the authenticator and then upon verification the authenticator supplies the client and the server both with matching security tokens and then the client and server can communicate directly?
Just curious about there a reason you don't want to implement OAuth and run your own OAuth server.
Additional reference: http://groups.google.com/group/37signals-api/msg/aeb0c8bf67a224cc
Turns out the solution was to define my problem a bit better. As I'm only trying to create a way to block applications, I only need to store their name and key when they request the server. Then, as long as they're not blocked and the key matches the one in the datastore, they'll be identified. So I'm not trying to authenticate so much as identify. Thanks for the input!
Related
I have a Cloudflare Worker that presents a registration form, accepts input from the user that is posted back to the Worker which then sends that on to an Node HTTP API elsewhere (DigitalOcean if that matters) that inserts the data into a MongoDB (though it could be any database). I control the code in both the CF-Worker and the API.
I am looking for the best way to secure this. I am currently figuring to include a pre-shared secret key in the API call request headers and I have locked down what this particular API can do with database access control. Is there an additional way for me to confirm that only the CF Webworker can call the API?
If this is obvious to some I apologize. I have always been of the mind that unless you are REALY good at security it is best to consult those who are.
You can research OAuth2.0 standard. That is authorization standard for third party clients. Here is link: https://oauth.net/2/
This solution is the most professional.There are other less secure ways to do it, but easier to implement. Password and username, x-api-key, etc..
It sounds to me that you can also block all IPs and allow only requests from that specific domain name (CF Worker)
I am trying to build a registration/login system using the PERN stack (Postgres, Express, React & Node) for a client website.
I was doing some researching and came across HTTP Cookie and JWT token authorizations (many more but apparently those two are the dominant).
I noticed alot apps and tutorials that uses Node JS seems to use JWT alot, and store these in localstorage. But I'm doubtful about the security because I feel like a developer can basically go into localstorage and get the JWT token which o
Is there a better way to secure user authentications with this stack or is using localstorage the rule of thumb? If so, why is that?
Thank you for your time.
One limiting medium to the security of both session IDs and JWTs is network transmission. In this case, both are only as secure as the network itself. But most likely, your application would be using something like HTTPS or SSL, in which case any data being sent across the network would be reasonably secure.
Regarding your other edge case of someone trying to sniff at a JWT in local storage, there are a few options you may consider:
First, the nature of the JWT is that it is generally tamper-proof. A JWT contains inside of it a checksum, which is a unique hash based on the actual contents of the JWT. Let's says that some malicious user sniffed local storage, and then tried to change e.g. the claims section of the JWT. In doing so, this would also change the checksum (which that user would not be able to figure out, lacking the server key). Then, the next time the compromised JWT is sent to the server, the server would reject it, because the computed checksum would not match with the value contained in the JWT.
Second, in the event the above be deemed not secure enough, it is possible to pass around encrypted JWT. If you go with this option, both the server and client would encrypt/decrypt before sending a JWT, which adds an extra layer of protection.
Security of network transmission is just one case of whole solution in web applications.
Im currently in the research of the same topic and as you said a lot of tutorials, blogs, youtube and other sources gives an excellent examples of using JWT tokens for handling user data. Unfortunately hardly anyone go deepest in handling and processing user sessions from administration point of view - where the real problems starts.
Logging the user in and sends JTW token in response to the client is not a problem at all. The problem begin when you as administrator want to invalidate a user.
Refer to this sources:
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
Logout/invalidate a JWT
The session cookie with session data stored in server-side is currently the best option for web application.
I'm writing an API that will be hosted without SSL support and I need a way to authenticate the requests. Each client would have a different ID, but if requests were authorised with that, anyone with a packet sniffer could forge requests. Is it possible to make a secure system WITHOUT relying on SSL?
(Some thoughts I had included OAuth, could that be implemented?)
Many thanks
Have each client cryptographically sign its requests with a client-specific key. Verify the signature on the server.
Using cryptography pretty simple. The main challenge is setting up the clients' keys. It'll be hard to do that securely without using SSL. There's no information in the question about how you set up client IDs, so I don't know if it's secure enough to set up keys at that point as well.
It's also going to be a problem if you serve the client code without SSL.
But hey, it's just an API you're building. Maybe the code that interacts with it is served over HTTPS. Or maybe the code is stored locally on the client.
I feel like a lot of people are going to complain about this answer though.
A classic dumb thing to do is pass something security related info via a GET on the query string ala:
http://foo?SecretFilterUsedForSecurity=username
...any yahoo can just use Fiddler or somesuch to see what's going on....
How safe is it to pass this info to an app server(running SSL) via a POST, however? This link from the Fiddler website seems to indicate one can decrypt HTTPS traffic:
http://fiddler2.com/documentation/Configure-Fiddler/Tasks/DecryptHTTPS
So is this equally dumb if the goal is to make sure the client can't capture / read information you'd prefer them not to? It seems like it is.
Thanks.
Yes, it's "equally dumb". SSL only protects data from being read by a third party; it does not prevent the client (or the server) from reading it. If you do not trust the client to read some data, they should not be given access to that data, even just to make a POST.
Yes, any user can easily examine the data in a POST request, even over HTTPS/SSL, using software like Burp Suite, Webscarab, or Paros Proxy. These proxies will complete the SSL transaction with the server, and then pass on the data to the client. All data passing through the proxy is stored and is visible to the client.
Perhaps you are trying to store sensitive/secret data on the client-side to lighten the load on your server? the way to do this so that the user cannot look at it (or change it) even with a proxy, is to encrypt it with a strong symmetrical secret key known only to the server. If you want to be sure that the encrypted data is not tampered with, throw on an HMAC. Make sure you use a sufficiently random key and a strong encryption algorithm and key length such as AES 256.
If you do this you can offload the storage of this data to the client but still have assurance that it has not changed since the server last saw it, and the client was not able to look at it.
This depends on who you're trying to protect your data from, and how much control you have over the client software. Fundamentally, in any client-server application the client must know what it is sending to the server.
If implemented properly, SSL will prevent any intermediary sniffing or altering the traffic without modifying the client. However, this relies on the connection being encrypted with a valid certificate for the server domain, and on the client refusing to act if this is not the case. Given that condition, the connection can only be decrypted by someone holding the private key for that SSL certificate.
If your "client" is just a web browser, this means that third parties (e.g. at a public wi-fi location) can't intercept the data without alerting the person using the site that something is suspicious. However, it doesn't stop a user deliberately by-passing that prompt in their browser in order to sniff the traffic themselves.
If your client is a custom, binary, application, things are a little safer against "nosy" users: in order to inspect the traffic, they would have to modify the client to by-pass your certificate checks (e.g. by changing the target URL, or tricking the app to trust a forged certificate).
In short, nothing can completely stop a determined user sniffing their own traffic (although you can make it harder) but properly implemented SSL will stop third-parties intercepting traffic.
The other, more important reason not to add confidential information into URL with GET requests is that the web server and any proxies on the way will log it. POST parameters don't get logged by default.
You don't want your passwords to show up in server logs - logs are usually protected much, much less than, for example, the password database itself.
My API (a desktop application) communicates with my web app using basic HTTP authentication over SSL (Basically I'm just using https instead of http in the requests). My API has implemented logic that makes sure that users don't send incorrect information, but the problem I have is that someone could bypass the API and use curl to potentially post incorrect data (obtaining credentials is trivial since signing up on my web app is free).
I have thought about the following options:
Duplicate the API's logic in the web app so that even if users try to cheat the system using curl or some other tool they are presented with the same conditions.
Implement a further authentication check to make sure only my API can communicate with my web app. (Perhaps SSL client certificates?).
Encrypt the data (Base 64?)
I know I'm being a little paranoid about users spoofing my web app with curl-like tools but I'd rather be safe than sorry. Duplicating the logic is really painful and I would rather not do that. I don't know much about SSL client certificates, can I use them in conjunction with basic HTTP authentication? Will they make my requests take longer to process? What other options do I have?
Thanks in advance.
SSL protects you from the man-in-the-middle attacks, but not from attacks originated on the client side of the SSL. A client certificate built into your client API would allow you to identify that data was crafted by the client side API, but will not help you figuring out if client side manually modified the data just before it got encrypted. Technically ssavy user on the client end can always find a way to modify data by debugging through your client side API. The best you can do is to put roadblocks to your client side API, to make it harder to decipher it. Validation on the server side is indeed the way to go.
Consider refactoring your validation code so that it can be used on both sides.
You must validate the data on the server side. You can throw nasty errors back across the connection if the server-side validation fails — that's OK, they're not supposed to be tripped — but if you don't, you are totally vulnerable. (Think about it this way: it's the server's logic that you totally control, therefore it is the server's logic that has to make the definitive decisions about the validity of communications.)
Using client certificates won't really protect you much additionally from users who have permission to use the API in the first place; if nothing else, they can take apart the code to extract the client certificate (and it has to be readable to your client code to be usable at all). Nor will adding extra encryption; it makes things much more difficult for you (more things to go wrong) without adding much safety over that already provided by that SSL connection. (The scenario where adding encryption helps is when the messages sent over HTTPS have to go via untrusted proxies.)
Base-64 is not encryption. It's just a way of encoding bytes as easier-to-handle characters.
I would agree in general with sinelaw's comment that such validations are usually better on the server side to avoid exactly the kind of issue you're running into (supporting multiple client types). That said, you may just not be in a position to move the logic, in which case you need to do something.
To me, your options are:
Client-side certificates, as you suggest -- you're basically authenticating that the client is who (or what, in your case) you expect it to be. I have worked with these before and mutual authentication configuration can be confusing. I would not worry about the performance, as I think the first step is getting the behavior your want (correctness first). Anyway, in general, while this option is feasible, it can be exasperating to set up, depending on your web container.
Custom HTTP header in your desktop app, checking for its existence/value on the server side, or just leveraging of the existing User-Agent header. Since you're encrypting the traffic, one should not be able to easily see the HTTP header you're sending, so you can set its name and value to whatever you want. Checking for that on the server side is akin to assuring you that the client sending the request is almost certainly using your desktop app.
I would personally go the custom header route. It may not be 100% perfect, but if you're interested in doing the simplest possible thing to mitigate the most risk, it strikes me as the best route. It's not a great option if you don't use HTTPS (because then anyone can see the header if they flip on a sniffer), but given that you do use HTTPS, it should work fine.
BTW, I think you may be confusing a few things -- HTTPS is going to give you encryption, but it doesn't necessarily involve (client) authentication. Those are two different things, although they are often bundled together. I'm assuming you're using HTTPS with authentication of the actual user (basic auth or whatever).