Pular para o conteúdo principal

Autenticação com certificado em nuvem

Um certificado em nuvem permite que o usuário entre na sua aplicação do mesmo jeito que um smart card: o usuário prova que controla a chave do certificado assinando um desafio aleatório (um nonce), e a sua biblioteca de assinatura confere a assinatura e valida o certificado. Com o CloudHub, o usuário aprova essa assinatura no aplicativo do provedor, em vez de digitar um PIN em um token.

O fluxo é o fluxo de assinatura com um nonce no lugar do documento:

  1. Crie uma sessão SingleSignature e envie o usuário a um provedor.
  2. Quando o usuário voltar, leia o certificado dele no CloudHub.
  3. Peça à sua biblioteca de assinatura que crie um nonce e peça ao CloudHub que assine o hash dele.
  4. Peça à sua biblioteca de assinatura que confira a assinatura e valide o certificado.
  5. Encontre o usuário pelo CPF do certificado e autentique-o.

Use SingleSignature para isso, não AuthenticationSession: a maioria dos provedores não oferece sessões de autenticação, e uma sessão que não assina não prova nada sobre a chave.

O certificado sozinho não é prova. É o passo 4 que mostra que o usuário controla a chave neste momento e que o certificado é válido e confiável.

O exemplo​

Cada exemplo é o handler da URI de redirecionamento; o handler que cria a sessão é o mesmo de Primeiros passos, sem identificador se você preferir que o usuário se identifique no provedor. Os exemplos seguem os do PKI Suite Samples:

LinguagemBiblioteca de assinatura
C#PKI SDK (PKCertificateAuthentication)
PHPPKI Express (Authentication)
PythonPKI Express (Authentication)
Node.jsRest PKI (Authentication)
JavaPKI Express (Authentication)

O PKI SDK e o Rest PKI fornecem o hash a assinar. O PKI Express fornece o próprio nonce, então esses exemplos calculam o hash dele com o algoritmo que o PKI Express indica.

Controllers/CloudLoginController.cs
using Lacuna.Cloudhub.Api;
using Lacuna.Cloudhub.Client;
using Lacuna.Pki;
using Lacuna.Pki.Stores;
using Microsoft.AspNetCore.Mvc;

public class CloudLoginController : Controller {

private static readonly CloudhubClient cloudhub = new CloudhubClient(
"https://cloudhub.lacunasoftware.com/",
Environment.GetEnvironmentVariable("CLOUDHUB_API_KEY"));

// GET /CloudLogin/Complete?session=…: the redirect URI
public async Task<IActionResult> Complete(string session) {
if (string.IsNullOrEmpty(session)) {
return RedirectToAction("Index"); // not authorized
}

// 1. The user's certificate, from CloudHub
byte[] certificate = await cloudhub.GetCertificateAsync(session);

// 2. PKI SDK creates a nonce. Store nonces in your database in production.
var auth = new PKCertificateAuthentication(new FileSystemNonceStore(nonceFolder));
byte[] nonce = auth.Start();

// 3. CloudHub signs the nonce's hash with the user's key
var signature = await cloudhub.SignHashAsync(new SignHashRequest {
Session = session,
Hash = PKCertificateAuthentication.DigestAlgorithm.ComputeHash(nonce),
DigestAlgorithmOid = PKCertificateAuthentication.DigestAlgorithm.Oid,
});

// 4. PKI SDK checks the signature and validates the certificate
var validationResults = auth.Complete(nonce, certificate, signature,
TrustArbitrators.PkiBrazil, out PKCertificate userCert);
if (!validationResults.IsValid) {
return View("Failed", validationResults);
}

// 5. Find the user by userCert.PkiBrazil.CPF and sign them in
return RedirectToAction("Index", "Home");
}
}

Associando o certificado a um usuário​

O certificado validado identifica uma pessoa, não uma conta na sua aplicação. Faça a associação como o seu negócio exigir; com certificados ICP-Brasil, as chaves usuais são o CPF (e-CPF) ou o CNPJ e o CPF do responsável (e-CNPJ). Se você criou a sessão com um identificador, confira também se o certificado traz esse identificador: o usuário pode ter entrado no provedor com outra conta.

Ver em Markdown