Web Servers have settings by which you request client certificates - for eg. SSLVerifyClient require in Apache, a different setting in IIS etc. If this is set, then the browser throws up a dialog asking you to chose a certificate.
Is it possible to ask for a certificate dynamically? i.e. I am really not interested in 2 way SSL - however, I want to ask the user to register his certificate with my application which will be used in a different context. So I need to let the user chose one of the certs registered in his browser and access the cert in my application. How do I do this?
Is this possible at all?
I have figured out one way to do this - I have a upload link in my application - this points to a Virtual Directory which has Client Side Authentication required property. So when the user clicks on the link - it triggers a SSL Renegotiation. The browser throws a dialog which lets the user chose from the registered certs. Once he chosen the certificate, SSL renegotiation happens and the I can access the cert in the application. The SSL renegotiation ensures that the user has the private key corresponding to the Cert.
If there any problems with this method or if there is a better way to do this, I am most certainly interested in doing it.
Also, I am currently doing this in IIS - but I think something like this should be possible in most other webservers also.
Related
Facebook recently changed the security settings on Account Configs, now there is no more an option to force, or not, an application to use HTTPS protocol.
Therefore, it isn't possible to do a App without a SSL key. Previously we could just don't fill Secure Canvas URL field, and access the canvas app through the HTTP protocol. But now, without the option in the security user config, the facebook app keeps redirecting to the HTTPS protocol.
So, there is some workaround for this ?
As CBroe says, you need SSL.
There are 2 things you need in my opinion:
A webserver with SSL.
IF you're in OSX and you run Apache, this tutorial really helps:
http://blog.andyhunt.info/2011/11/26/apache-ssl-on-max-osx-lion-10-7/, plus you might want to add your certificate as a trusted (root?) certificate, or certificate authority. (I'm not very well versed in this)
The only caveat I found, specially for Chrome, is that when you're generating the Certificate Request File, under Common Name place "localhost" or the host you're using for development. This last caveat should be similar in Windows, since it's a browser requirement that the certificate common name matches the actual host. Browsers like Firefox allows you to permanently trust a certificate, thus avoiding all the certificate installation on the OS and trusting.
A proxy app
proxy-like app to act as a man in the middle and decode the encrypted information, in order to see the actual requests and response being sent and received from the server. There should be other software, but the one I use and love is Charles Proxy, which can do this and tons more.
Hope it helps!
Is it possible to use two authentications methods side by side in Tomcat 6.xxx?
Story:Right now my app runs on ports 80 and 443. In 443 connector there is clientAuth="want" parameter.
If client is coming over 80, no cert is required. But when client is coming over 443 and client has smart card in reader, the cert is automatically asked, even if the client don't wan't to log in.
For login with user-cert, i have FormFallBack authenticator, which means that if client doesn't send certificate (he has not smart card in reader) or certification fails in authenticator, authenticator directs to form, where he can login with password and username.
My english isn't very good, so here is better overview of similar system : http://wiki.apache.org/tomcat/SSLWithFORMFallback
But the process of asking user-cert is annoying for user if browser multiple times asks for cert, if user don't want use smart card for login(but he has it in reader), instead he want's to login with username and password.
So is there option for following:
I have login page where are username and password field and login button. If user presses login button, he will be logged in with username and password(directed to form authenicator).
But in the same page there is button "Login with smartcard". If he presses this button, the server asks for user-cert and gives it to authenticator.
Hope you understand the problem.
I believe you will have to write your own Tomcat authenticator that understands these requirements.
It may not actually be possible because AFAICT you are asking to be able to reconfigure the behavior of the SSL connector on a per-user basis, and you can't configure the connector for the user before the SSL negotiation has taken place.
If you keep the authenticated state with the servlet session, you can offer to log on via either a form or client-certificates by providing two distinct buttons (or links) indeed.
I'm assuming here that you can have paths like /login/form for the form and /login/cert for authentication via a client-cert.
You can trigger client-certificate authentication on demand, when visiting /login/cert using SSL/TLS renegotiation. To do this, use clientAuth="false" in the connector configuration, but put a security constraint on that path in the webapp, using <auth-method>CLIENT-CERT</auth-method>: this will trigger renegotiation when required.
For this to work, you'll need a version of the JRE that supports RFC 5746 (Oracle Java 6 r22 or later), and your clients should support it too. Modern versions of browsers/OSes should support this by now.
See the AuthenticRoast project in Google Code. It does exactly this and more.
I am working on an application that uses a private web service.
We currently use a bundled client certificate to enable 2-way SSL connectivity however the password for the certificate is in the code and it is a concern that this could be de-compiled and used with the (trivially)extracted certificate file for nefarious purposes.
Is there a method by which I can pre-load a password into the application keychain for distribution with the app so that the password is never left in the open?
No matter how you put your password into your binary, there will be someway to exploit this, be it with debugging tools, code analysis etc.
You better treat your web service as open... maybe unlikely to get not properly authorized requests in the very next future, but basically you give away access to the public.
Keychain should be encrypted with user specific key, and this you obviously cannot do - or you would be able to read everyones data anyway.
If you really need to protect it, you probably need user accounts on your server... if this is more secure than obscurity it up to you.
I'd like to make requests from an iphone app to a web service I've built. How can I verify that requests made to the web service come from my iphone app (or indeed any authorised source) and are not forged?
I have looked at basic auth over HTTPS but is baking credentials into an application secure?
This question isn't really iphone specific; I'd like to know how to protect and authenticate requests in general.
Authentication can be asserted by presenting something you know, something you have, something you are or a combination of the three.
The iPhone doesn't have retinal or fingerprint scanners, so there are no "something you are" options available.
Client certificates work well as a "something you have" token. Most smartcards work by signing a message with an embedded certificate. When a certificate is compromised, it can be put onto a Certificate Revocation List (CRL) referenced by the webservers. Obviously, you wouldn't want to put your app's embedded certificate in the CRL -- that would deny access to all your users. Instead, you'll want users to download individual certificates to their iPhone.
After that, it's a matter of monitoring for unusual behavior to find the bad actors and adding those certs to the CRL. Two dead giveaways would be clients who send too many requests at once or from too many different IPs in too short a time.
Login/password is a simple "something you know" token. Like certificates, login/password combinations can be compromised and similar monitoring can be set up to find inappropriate behavior. The difference is compromised accounts would be marked "blocked" rather than added to a CRL.
By requiring both a client certificate and a login/password you increase the amount of effort needed to compromise an account.
Of course, you must ensure only valid accounts are added to the database. If there is an automated way to create new accounts and corresponding client certificates, then that account creation server/process becomes the easiest way for bad actors to create viable, unauthorized accounts. Requiring a real person to sign-off on accounts removes the automation process, but means a disgruntled or corrupt employee could create invalid accounts. Requiring a second person to counter-sign the account makes it harder for a single person to be an inside threat.
In short, ensuring high integrity of the clients is a process that can be made arbitrarily complex and expensive. What tools and processes you decide to deploy as the authentication scheme has to be balanced by the value of what it is protecting.
In theory, if you want the connection to be secure, the best is to have the client sign their request using a certificate. There are multiple resources about this. Look for "client certificate" on Google.
This example from Sun is in Java, but the concept is similar whatever the language.
PS: obviously, this doesn't prevent you from using other authentication methods such as passwords, etc...
PPS: Keep in mind that if someone manages to extract the certificate from your application, you are screwed either way ;-). You can imagine a store providing an individual certificate to each app and invalidating the certificates that are compromised.
I'm building a solution consisting of an app and a server. Server provides some methods (json) and the app uses them. My aim is to make those API methods inaccessible to other clients. What is the best way to do so?
Should I take a look at certificates (to sign every outgoing request)? If yes, where do I start and what is the performance impact of doing so?
What are alternatives?
Put another way, you need a way to distinguish a valid client's request from an invalid client's request. That means the client needs to present credentials that demonstrate the request comes from a valid source.
SSL certificates are an excellent way to assert identity that can be validated. The validity of an SSL certificate can be confirmed if the certificate contains a valid signature created by another certificate known to be secure, a root cert. As noted in other answers an embedded certificate won't do the job because that certificate can be compromised by dissecting the app. Once it is compromised, you can't accept any requests presenting it, locking out all your users.
Instead of one embedded app cert, you need to issue a separate certificate to each valid user. To do that, you need to set up (or outsource to) a Certificate Authority and issue individual, signed certificates to valid clients. Some of these certificate will be compromised by the user -- either because they were hacked, careless or intentionally trying to defraud your service. You'll need to watch for these stolen certificates, place them on a certificate revocation list (CRL) and refuse service to these compromised certificates. Any web server is able to refuse a connection based on a CRL.
This doesn't solve the security issues, it just moves them out of the app. It is still possible for someone to create what appears to be a valid certificate through social engineering or by stealing your root certificate and manufacturing new signed certificates. (These are problems all PKI providers face.)
There will be a performance hit. How much of a hit depends on the number of requests from the app. The iPhone NSURLConnection class provides support for SSL client certificates and client certificates can be installed in the phone from an e-mail or authenticated web request. Managing the infrastructure to support the client certs will require more effort than coding it into the app.
Incidentally, voting down any answer you don't like creates a chilling effect in the community. You're not nearly as likely to get advice -- good or bad -- if you're going to take a whack at everyone's reputation score.
I will now freely admit that it's an interesting question, but I have no idea how it could be done.
Original answer:
Interesting question. Assuming people can't reverse-engineer the iPhone app, the only solution that comes to mind would be to sign requests with a public key, or some other secret known only to the application. By that, I mean adding an extra argument to every API call that is a hash of the destination URL and other arguments combined with a secret known only to your server and application.
To expand upon this: suppose your API call has arguments foo, bar and qux. I would add a signature argument, the value of which could be something as simple as sorting the other arguments by name, concatenating them with their values, adding a secret, and hashing the lot. Then on the server side, I would do the same thing (excepting the signature argument) and check that the hash matches the one we were given in the request.
Consider authenticated HTTP.
For a cheaper alternative, there's shared secret/hash scheme. The client and the server have a shared secret string of text. Upon request, the client hashes together (using MD5, or SHA1, or SHA something else - you choose) the request fields and the secret. The hash value is attached to the request - say, as another POST field.
The server does the same operation with the request and with its copy of the secret, then compares the hash values. If they don't match - service denied.
For added security, you may encrypt the hash with a RSA public key. The client has the public key, the server keeps the private key. The server decrypts the hash with the private key, then the same. I did that with a C++ WinMobile client and a PHP-based service - works like a charm. No experience with crypto on iPhone, though.
UPDATE: now that I think of it, if we assume that the attacker has complete control over the client (ahem jailbroken iPhone and a debugger), the problem, as formulated above, is not solvable in theory. After all, the attacker might use your bits to access the service. Reverse-engineer the executable, find the relevant functions and call them with desired data. Build some global state, if necessary. Alternatively, they can automate your UI, screen scraper style. Such is the sad state of affairs.