Pular para o conteúdo principal

Certificate authentication - Rest PKI

Legacy product

Rest PKI is a legacy product: it still receives bug and security fixes, but new cloud integrations should use Rest PKI Core, which also serves most Rest PKI APIs. This page is for existing Rest PKI integrations. See the Rest PKI quick reference.

Users sign in to your application with their digital certificate: Rest PKI issues a one-time token, Web PKI signs it with the user's certificate in the browser, and Rest PKI checks the signature and the certificate.

The code on this page is from the ASP.NET MVC samples project: C# on the server, with Lacuna.RestPki.Client 1.24.1, and JavaScript in the browser, with Web PKI.

Flow​

  1. Server: start the authentication with the security context; Rest PKI returns a token.
  2. Browser: Web PKI lists the user's certificates; when the user picks one, signWithRestPki() signs with it, using the token.
  3. Server: complete the authentication with the token; Rest PKI returns the validation results and the user's certificate.
  4. Server: if the results are valid, find your user by a field of the certificate and sign them in.
StepClient methodEndpoint
StartStartWithWebPkiAsync(securityContextId)POST Api/Authentications
CompleteCompleteWithWebPkiAsync(token)POST Api/Authentications/{token}/Finalize

1. Start the authentication​

The server starts the authentication and renders the page with the token, which is a 22-character, case-sensitive, URL-safe string. It is not your API access token.

var auth = Util.GetRestPkiClient().GetAuthentication();
var token = await auth.StartWithWebPkiAsync(Util.GetSecurityContextId());
base.SetNoCacheHeaders();
  • The token works for a single authentication. The sample sends headers that keep the browser from caching the page, so that the back button doesn't show a page with a used token.
  • The authentication must be completed within one hour by default; on an on-premises instance, the TimeToCompleteAuthentications setting changes this (since Rest PKI 1.12.6).
  • The security context decides which certificates are accepted; the samples use LacunaTest in debug builds, to accept the test certificates, and PkiBrazil otherwise. See Security context.
  • To ignore errors due to an unknown revocation status, start with an AuthenticationOptions whose IgnoreRevocationStatusUnknown is true (since Rest PKI 1.16.0); the sample doesn't.

2. Sign the token in the browser​

The page keeps the token in a hidden field, with a <select> for the certificates and a Sign In button that is not a submit button: the form is submitted by script once Web PKI finishes. The script initializes Web PKI with your Rest PKI endpoint in restPkiUrl:

var pki = new LacunaWebPKI(_webPkiLicense);

pki.init({
ready: loadCertificates, // As soon as the component is ready we'll load the certificates.
defaultError: onWebPkiError, // Generic error callback defined below.
restPkiUrl: _restPkiEndpoint // REST PKI endpoint to communication between Web PKI.
});

When the user clicks Sign In, it calls signWithRestPki() with the token and the chosen certificate, then submits the form:

var selectedCertThumbprint = formElements.certificateSelect.val();
pki.signWithRestPki({
token: formElements.token,
thumbprint: selectedCertThumbprint
}).success(function () {
formElements.form.submit();
});
  • _webPkiLicense and _restPkiEndpoint come from the WebPkiLicense and RestPkiEndpoint settings. RestPkiEndpoint is only needed on-premises, and a Web PKI license only to run on a host other than localhost. See also Custom RestPKI configuration.
  • Web PKI exchanges the signature data with Rest PKI directly.

3. Complete the authentication​

Back on the server, complete the authentication with the token. If the results are not valid, show what failed; otherwise, read the user's certificate:

var auth = Util.GetRestPkiClient().GetAuthentication();
var validationResults = await auth.CompleteWithWebPkiAsync(model.Token);

if (!validationResults.IsValid) {
return View("Failed", validationResults);
}

return View("Success", new AuthenticationInfoModel() {
UserCert = auth.GetCertificate()
});
  • Rest PKI answers HTTP 200 whether the authentication succeeded or not: check IsValid. ValidationResults.ToString() lists every check, and the sample shows it on its failure page.
  • Completing removes the authentication: a second call with the same token fails.
  • If the browser didn't sign, completing fails with ClientSignatureNotSet (HTTP 422). See Return codes.
  • GetCertificate() can only be called after a complete method.

4. Sign the user in​

When the results are valid, the sample's comment says that the certificate is valid according to the security context chosen at the start and that the user is the certificate's subject. Look up your user by one of the certificate's fields, such as EmailAddress or, for ICP-Brasil certificates, PkiBrazil.Cpf; which field depends on your application.

The certificate (PKCertificate) has SubjectName, EmailAddress, IssuerName, SerialNumber, ValidityStart, ValidityEnd, ThumbprintSHA256 and, for ICP-Brasil certificates, PkiBrazil with CertificateType, Cpf, Cnpj, Responsavel, CompanyName, DateOfBirth and the RG and OAB fields.

TODO(docs): what Rest PKI checks when completing, beyond the certificate's trust under the security context.

Errors​

  • When an account limit is set and exceeded, Rest PKI answers HTTP 429 with the headers X-RateLimit-Limit and X-RateLimit-Remaining.
  • For the other codes, see Return codes and the quick reference.

See also​

View as Markdown