Trabajar con SSL en Web API

Algunos de los esquemas de autenticación comunes no son seguros a través de HTTP sin formato. En particular, la autenticación básica y la autenticación mediante formularios envían credenciales no cifradas. Para que sean seguros, estos esquemas de autenticación deben usar SSL. Además, se pueden usar certificados SSL de cliente para autenticar a los clientes.

Habilitación de SSL en el servidor

Para configurar SSL en IIS 7 o versiones posteriores:

  • Cree u obtenga un certificado. Para probar, puede crear un certificado autofirmado.
  • Agregue un enlace HTTPS.

Para obtener detalles, consulte Procedimientos para configurar SSL en IIS 7.

Para las pruebas locales, puede habilitar SSL en IIS Express desde Visual Studio. En la ventana Propiedades, establezca SSL habilitado en True. Anote el valor de la Dirección URL de SSL; use esta dirección URL para probar las conexiones HTTPS.

Image of S S L enabled true in properties

Aplicación de SSL en un controlador de API web

Si tiene tanto un enlace HTTPS como HTTP, los clientes pueden seguir usando HTTP para acceder al sitio. Puede permitir que haya algunos recursos disponibles a través de HTTP, si bien otros recursos requieren SSL. En ese caso, use un filtro de acción a fin de requerir SSL para los recursos protegidos. El código siguiente muestra un filtro de autenticación de API web que comprueba el estado de SSL:

public class RequireHttpsAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
        {
            actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
            {
                ReasonPhrase = "HTTPS Required"
            };
        }
        else
        {
            base.OnAuthorization(actionContext);
        }
    }
}

Añada este filtro a todas las acciones de API web que requieran SSL:

public class ValuesController : ApiController
{
    [RequireHttps]
    public HttpResponseMessage Get() { ... }
}

Certificados SSL de cliente

SSL proporciona autenticación mediante el uso de certificados PKI (infraestructura de clave pública). El servidor debe proporcionar un certificado que autentique el servidor en el cliente. Es menos habitual que el cliente proporcione un certificado al servidor, pero es una opción para autenticar a los clientes. Para usar certificados de cliente con SSL, necesita una forma de distribuir certificados firmados a los usuarios. Para muchos tipos de aplicaciones, esta no será una buena experiencia de usuario, pero en algunos entornos (por ejemplo, el empresarial) puede ser factible.

Ventajas Inconvenientes
- Las credenciales de certificado son más seguras que el nombre de usuario y la contraseña. - SSL proporciona un canal seguro completo con autenticación, integridad de los mensajes y cifrado de estos. - Debe obtener certificados PKI y administrarlos. - La plataforma del cliente debe admitir los certificados SSL de cliente.

Para configurar IIS de forma que acepte certificados de cliente, abra el Administrador de IIS y realice los pasos siguientes:

  1. Haga clic en el nodo del sitio en la vista de árbol.

  2. Haga doble clic en la característica Configuración de SSL en el panel central.

  3. En Certificados de cliente, seleccione una de estas opciones:

    • Aceptar: IIS aceptará un certificado del cliente, pero no requiere uno.
    • Requerir: se requiere un certificado de cliente. (Para habilitar esta opción, también debe seleccionar "Requerir SSL").

También puede establecer estas opciones en el archivo ApplicationHost.config:

<system.webServer>
    <security>
        <access sslFlags="Ssl, SslNegotiateCert" />
        <!-- To require a client cert: -->
        <!-- <access sslFlags="Ssl, SslRequireCert" /> -->
    </security>
</system.webServer>

La marca SslNegotiateCert significa que IIS aceptará un certificado del cliente, pero no requiere uno (equivalente a la opción "Aceptar" en el Administrador de IIS). Para requerir un certificado, establezca la marca SslRequireCert. Para las pruebas, también puede establecer estas opciones en IIS Express, en el archivo applicationhost.Config local, ubicado en "Documents\IISExpress\config".

Creación de un certificado de cliente para pruebas

Para realizar pruebas, puede usar MakeCert.exe para crear un certificado de cliente. En primer lugar, cree una entidad raíz de prueba:

makecert.exe -n "CN=Development CA" -r -sv TempCA.pvk TempCA.cer

El archivo MakeVert le pedirá que escriba una contraseña para la clave privada.

A continuación, agregue el certificado al almacén "Entidades de certificación raíz de confianza" del servidor de prueba, como se indica a continuación:

  1. Abra MMC.
  2. En Archivo, seleccione Agregar o quitar complemento.
  3. Seleccione Cuenta de equipo.
  4. Seleccione Equipo local y complete el asistente.
  5. En el panel de navegación, expanda el nodo "Entidades de certificación raíz de confianza".
  6. En el menú Acción, apunte a Todas las tareas y, a continuación, haga clic en Importar a fin de iniciar el Asistente para importación de certificados.
  7. Vaya al archivo de certificado, TempCA.cer.
  8. Haga clic en Abrir, después en Siguiente y complete el asistente. (Se le pedirá que vuelva a escribir la contraseña).

Ahora debe crear un certificado de cliente firmado por el primer certificado:

makecert.exe -pe -ss My -sr CurrentUser -a sha1 -sky exchange -n "CN=name" 
     -eku 1.3.6.1.5.5.7.3.2 -sk SignedByCA -ic TempCA.cer -iv TempCA.pvk

Uso de certificados de cliente en Web API

En el lado del servidor, puede obtener el certificado de cliente mediante una llamada a GetClientCertificate en el mensaje de solicitud. El método devuelve null si no hay ningún certificado de cliente. De lo contrario, devuelve una instancia de X509Certificate2. Use este objeto para obtener información del certificado, como el emisor y el asunto. Después, puede usar esta información para la autenticación o la autorización.

X509Certificate2 cert = Request.GetClientCertificate();
string issuer = cert.Issuer;
string subject = cert.Subject;