WebAPI + Azure WebSite + Client WebSite + SSL - how many certs do I need? - asp.net-mvc

I have a WebAPI solution hosted in an Azure Web Site (appnameapi.azurewebsites.net) that has some endpoints exposed to regular http right now.
I also have a client application hosted in a separate Web Site under appname.azurewebsites.net.
I purchased appname.com from hover and am forwarding appname.com to appname.azurewebsites.net with masking. The client application makes requests to appnameapi.azurewebsites.net right now, but not encrypted.
My goal is to get SSL working on the web client so that users see SSL in the browser bar, and so that anything that goes from the client to the api endpoints is encrypted.
I went to rapidSSL and purchased a certificate for appname.com. Now I'm not sure if I need to put this in my WebAPI web site, or my client web site. I've found some documentation on setting up SSL in Azure but nothing that's given me a good grasp of what needs to be done in this scenario.
What's the next step? Do I need one cert per site, and if not, where does the single cert go?

You client web site is appname.azurewebsites.net. You have appname.com mapped to this. Your SSL certificate is for this domain. So, you will need to put the certificate with the client app. As an end user, if I go to appname.com, the certificate your application will present to my browser will be the one you purchased for appname.com. This is for the pages rendered by the client web application.
Now, as the browser renders the page from the client web application, say it needs to make jQuery AJAX calls to your web API site appnameapi.azurewebsites.net. You can use a domain name for this one as well, some thing like api.appname.com but regardless, this will be a cross-origin call, BTW. If this call is also through HTTPS, then for this case also, a valid cert must be presented to the browser. Assuming you have api.appname.com which is a sub-domain of appname.com, you can use the same certificate you bought from rapidSSL with web API site as well provided it is a wild-card cert, which is obviously more expensive. Otherwise, you will need one more certificate for the web api site (or the domain name if you plan to use one for API) and install that new cert in the api app.

Related

Getting client certificates in Azure Web App using OWIN

If you are using Azure Web Apps to host your web application (let it be an ASP.NET MVC web app) you do not have the possibility to set up the IIS behind the Azure Web App to accept client certificates through an HTTPS connection. My application has some Web API endpoints that would be only accessible if the user has the correct certificate with the allowed thumbprint. However, I have other endpoints as well (and of course the website) that would be accessible without a client certificate. So in my case the only way is to accept client certificates.
I am not sure about that, but if I know well I can still get the client certificate by using OWIN while the SSL Settings in IIS is set to Ignore. If I use OWIN and go through the OWIN environment I can see a key called ssl.LoadClientCertAsync.
I am implementing endpoints that a third-party service will call, so I have no control over the content of the request. I know that there is a ssl.ClientCertificate key, with type X509Certificate, but in my case this key doesn't exist.
I have found some C# solution about using this ssl.LoadClientCertAsync key to get the certificate like in the CheckClientCertificate method of Katana or the solution in this C# Corner article. In every solution that I can find in the net, the author gets this type as a Func<Task> and then calls this task, by for example using the await operator.
var certLoader = context.Get<Func<Task>>("ssl.LoadClientCertAsync");
if (certLoader != null)
{
await certLoader();
...
After that they retrieves the certificate by using the ssl.ClientCertificate key.
var asyncCert = context.Get<X509Certificate>("ssl.ClientCertificate");
In this example, my asyncCert variable is always null. There weren't any ssl.ClientCertificate key in the OWIN context. I have tried to use the X509Certificate2 instead of X509Certificate, but I still got null.
My question is is it possible to get the client certificate in an Azure Web Site while the default SSL setting is Ignore by using OWIN? If yes, why can't I get the certificate using the ssl.LoadClientCertAsync key?
According to your description, I have created my ASP.NET MVC web application for working with client certificate in OWIN to check this issue. The following code could work on my local side:
if (Request.GetOwinContext().Environment.Keys.Contains(_owinClientCertKey))
{
X509Certificate2 clientCert = Request.GetOwinContext().Get<X509Certificate2>(_owinClientCertKey);
return Json(new { Thumbprint = clientCert.Thumbprint, Issuer = clientCert.Issuer }, JsonRequestBehavior.AllowGet);
}
else
return Content("There's no client certificate attached to the request.");
For SSL Settings set to Accept, I could select a certificate or cancel the popup window for selecting a certificate.
AFAIK, we could enable the client certificate authentication by setting clientCertEnabled to true and this setting is equivalent to SSL Settings Require option in IIS.
As How To Configure TLS Mutual Authentication for Web App states about accessing the Client Certificate From Your Web App:
If you are using ASP.NET and configure your app to use client certificate authentication, the certificate will be available through the HttpRequest.ClientCertificate property. For other application stacks, the client cert will be available in your app through a base64 encoded value in the X-ARR-ClientCert request header.
My question is is it possible to get the client certificate in an Azure Web Site while the default SSL setting is Ignore by using OWIN?
AFAIK, the current SSL Settings for client certificates only supports Ignore and Require for now. When hosting your web application on azure web app, for the client users who access your azure web app with client certificate authentication, they could specify the certificate to a base64 encoded value as your custom request header when sending request to your azure web app, then your could try to retrieve the header and verify the cert if the cert custom request header exists. Details, you could follow this sample.
Additionally, you could use Azure VM or Azure Cloud Service instead of azure web app, at this point you could fully control the SSL Settings in IIS.

Rails public/private key authentication, but user has no server

I've built a JavaScript app that's powered by a Rails back-end. The JavaScript app (the built/minified version) is going to live on an S3 bucket.
The app Iv'e built is going to run on other people's websites, similar to Stripe (Stripe has you include this code in your HTML):
<form action="" method="POST">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="api_key"
data-amount="999"
data-name="Stripe.com"
data-description="Widget"
data-image="/img/documentation/checkout/marketplace.png"
data-locale="auto">
</script>
</form>
The difference is that my user will have no back-end, it's all handled by my Rails API. The end-user fills out the form on my user's website, and that data is POSTed to my API, not my user's API. My user signs up, posts a snippet with a script to my JavaScript app on their website, and then they have users fill out a form (again, like Stripe) on their website which sends a request to my API.
How can I manage authentication in this circumstance? The key that will be provided in the code snippet is obviously public, given that it's in the HTML on my user's website. How can I verify the request is coming from the correct person given the key? Should I look at IP Address and/or domain name that the request comes from?
Let's pretend your user's website is www.example.com.
You want to know did this request come from the real www.example.com ?
There are two possible solutions :
1- Certificates
If your user's site uses https(it has a certificate) the certificate identifies a unique site(that what it's for), on signup you can request that certificate and add it to your rails trust store, then in your javascript app you send the certificate on every request and your rails verifies it.
advantages
1- no backend needed.
2- more secure than a simple api-key, that's because an api-key could provide authentication but not non-repudiation which the certificate provide.
3-easy for your user(provided they already have a certificate).
disadvantages
1- too secure : you didn't mention that non-repudiation is a goal, if it is this disadvantage doesn't count.
2- might hurt performance : on every request a certificate is posted and verified, not only verifying a certificate is slower than verifying an api-key but sending the certificate on every request may heart bandwidth.
3- requires your user is using https, what if he/she doesn't want to use https for some reason ???
2- Setting a proxy
You store the api-key on the server and don't post it in the snippet and you assemble a simple backend that its only job is to send the api-key (some sort of a proxy).
advantages
1-not too secure : it provides the authentication you want without providing more needless goals.
2- good on performance : yes there is a proxy which may be slower, may be faster but that's faster than verifying a certificate and sending it on every request in my opinion.
3-simpler to program : I think assembling this backend is easier than writing certificate verification code in a Rails app.
4- doesn't require https.
disadvantages
1-more installation for the user : that's because they have to install a backend besides the include snippet.
2-the form data should be sent to this backend and then to your rails backend, so we have two round trips.
Now web servers (Apache,Nginx) can be configured to work as proxies but I don't know if they can be configured to send the api-key too.

IIS Passing client certificate to rails

I have an application written in Rails that must be ran behind a IIS server due to restrictions by the client, the government. We have to have SSL authentication. So what I can't figure out in my hours of searching Google is how to get IIS to pass the client certificate to the rails server (thin).
I've seen tutorials on Apache that use:
SSLOptions +ExportCertData
Which then make it available to the request object. Any ideas on how to configure IIS to do the same?
At least in the way that you ask the question IIS cannot provide a client certificate as the client cert would be issued by a third party. So you need to get the x509 cert that your application and then the cert is authenticated as part of the initial connection request with iis.
As to the apache function to provide the ssl cert from the server to the client, this functionality is not exposed by iis.
That's why you were not able to find anything on google
The main reason companies want to run Rails(or Other) applications behind an IIS server is for SSO apart from protecting the resources.
See if this helps.
We have been running our Rails app behind IIS at quite a few customer locations. We run our Rails app in JRuby inside Tomcat.
The steps to install the JK ISAPI redirector plugin are here
http://tomcat.apache.org/connectors-doc/webserver_howto/iis.html
All Rails contexts are protected in IIS using standard IIS authentication schemes, Integrated Windows Authentication ( Negotiate, NTLM).
Within the Rails app one can get the logged in user's information.
request.env['java.servlet_request'].get_remote_user
The Rails app also connects to Microsoft AD for additional user information like email, department etc.,
Since the Rails is blindly trusting the IIS server for authenticaiton it needs to be prevented from direct access.
1. Disable HTTP ports in Tomcat
2. Enable only the AJP port
3. Add an IP restriction so that it accepts connection only from the IIS server(s)
==
I do not think it is possible for IIS to pass on the certificate details. We tried to extract the Kerboros tokens ( for kerboros authentication delegation ) without much success and realized it is not possible.
After being told this may be impossible. I've finally figured it out! Here are the steps that I took.
Using OpenSSL create your own CA certificate.
Using the generated CA certficate create and sign other certificates with Open SSL.
Open Internet Information Service Manager click on the server, then click on server certificates.
Click Import under the Actions column
After importing click on your site.
In the Actions column click bindings...
Click add, scroll to https, and select the CA certificate that you imported
Click on your site again to get to the menu and click on SSL settings
Check require SSL and then click the radio buttion, require
Click your site again then click on the configuration editor (installed in IIS 7.5 can add-in in 7.0)
Go to system.webServer/security/authentication/iisClientCertificateMappingAuthentication
Set enabled to true
Set manyToOneCertificateMappings to true
Click on the ... box on the far right-end of manyToOneMappings
Click add under actions column, under collections
Add the username and password of the user you created (can be on local machine)
Now, go to the main server and restart.
You should be able to see the certificate using request.headers hash.
Variables for the hash include:
CERT_SERIALNUMBER
CERT_SUBJECT
CERT_ISSUER
HTTPS_SERVER_ISSUER
HTTPS_SERVER_SUBJECT
If you cannot find something you may have to install a module (for like authentication). I don't remember which ones I installed.

How do you configure a Heroku Rack/Rails app to authenticate the client certificate of an incoming request?

Say I have a Web service, called JokeService, which is a Rack/Rails3 app deployed on Heroku. And lets say I have an application, called ComedyApp. Now, I want JokeService to only entertain requests from ComedyApp. To do so, I would like ComedyApp to use a client certificate, which it uses to authenticate itself with JokeService.
My question is, how the heck can I configure the JokeService (again, a Rack/Rails3 app on Heroku) to check the validity of the client certificate?
This is related, but unanswered: How to access SSL client certificate from rack app
In short, you can't, since we don't have control of the http layer (thin or the routing mesh) in the stack.
An alternative is to authenticate one's requests simply using a custom request header.

Windows Azure Multi-Tenant Application and SSL

We are creating a multi-tenant ASP.NET MVC application that will be deployed onto Windows Azure. We will have some custom domain www.abc.com that will map to our given Windows Azure url abc.cloudapp.net. We are considering giving each tenant their own subdomain that will identify them on our application (tenant1.abc.com, tenant2.abc.com, tenant3.abc.com, etc) and then creating a CNAME record for each subdomain to map to abc.cloudapp.net. I have a few questions with this design.
Will a single wildcard SSL certificate for *.abc.com allow all the tenants to access the site over a secure connection?
Do we purchase the SSL certificate for *.abc.com or for abc.cloudapp.net?
Will the url that our ASP.NET MVC application sees be the tenant1.abc.com url or the abc.cloudapp.net url?
Thanks
Yes, one wildcard certificate should be all you need
You want it for *.abc.com
I'm less sure about this one, but I'm pretty sure it's tenant1.abc.com
knightpfhor's answer is perfect, but just in case you need to have a custom domain (using CNAME as well) for some of your premium tenants, now you can have "SSL hostheaders" with a new IIS 8 (Windows Server 2012) supported feature called SNI .
I'm a Microsoft Technical Evangelist and I have posted a detailed explanation and a sample "plug & play" source-code that address your current (sub-domain wildcard certificate) and possibly future needs (custom domain certificates) at:
http://www.vic.ms/microsoft/windows-azure/multiples-ssl-certificates-on-windows-azure-cloud-services/

Resources