Pular para o conteúdo principal

Authentication with a cloud certificate

A cloud certificate can sign users in to your application the same way a smart card does: the user proves that they control the certificate's key by signing a random challenge (a nonce), and your signature library checks the signature and validates the certificate. With CloudHub, the user approves that signature in their provider's app instead of typing a PIN into a token.

The flow is the signature flow with a nonce in place of a document:

  1. Create a session with SingleSignature and send the user to a provider.
  2. When the user comes back, read their certificate from CloudHub.
  3. Have your signature library create a nonce, and have CloudHub sign the nonce's hash.
  4. Have your signature library check the signature and validate the certificate.
  5. Find the user by the certificate's CPF and sign them in.

Use SingleSignature for this, not AuthenticationSession: most providers don't support authentication sessions, and a session that cannot sign cannot prove anything about the key.

The certificate alone is not proof. Step 4 is what shows that the user controls the key right now and that the certificate is valid and trusted.

The example​

Each example is the redirect URI's handler; the handler that creates the session is the same as in Get started, without an identifier if you prefer to let the user identify themselves at the provider. The examples follow the samples in PKI Suite Samples:

LanguageSignature library
C#PKI SDK (PKCertificateAuthentication)
PHPPKI Express (Authentication)
PythonPKI Express (Authentication)
Node.jsRest PKI (Authentication)
JavaPKI Express (Authentication)

PKI SDK and Rest PKI give you the hash to sign. PKI Express gives you the nonce itself, so those examples hash it with the digest algorithm PKI Express names.

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");
}
}

Matching the certificate to a user​

The validated certificate identifies a person, not an account in your application. Map it the way your business requires; with ICP-Brasil certificates, the CPF (e-CPF) or the CNPJ and the responsible person's CPF (e-CNPJ) are the usual keys. If you created the session with an identifier, also check that the certificate carries that identifier: the user may have signed in at the provider with another account.

View as Markdown