How to set up a TLS termination proxy for client authentication with X.509 certificate

The Connect2id server allows OAuth 2.0 clients to authenticate with a client X.509 certificate submitted during the TLS handshake. The two variants of this authentication are specified in the Mutual TLS Profile for OAuth 2.0 (RFC 8705):

  • tls_client_auth -- The client authenticates with an X.509 certificate issued by a Certificate Authority (CA) that is trusted by the authorisation server. This method relies on the client and server participating in a Public Key Infrastructure (PKI) governed by a CA or a hierarchy of CAs.

    Support for this method is available since Connect2id server 11.0.

  • self_signed_tls_client_auth -- The client authenticates with a self-signed (and self-issued) X.509 certificate. The validity of the certificate is established by the client having its certificate RSA or EC public key registered with the Connect2id server.

    Support for this method is available since Connect2id server 6.13. It is easier to setup because it doesn't rely on a PKI and CA.

TLS (HTTPS) can be handled by the Java servlet container (e.g. Apache Tomcat) where the Connect2id server is deployed, or by a dedicated TLS termination proxy, such as Nginx or Apache httpd. We recommend the TLS termination proxy method, because it's more flexible and makes load balancing simpler.

Instructions

1. Define an HTTP header name for passing the client X.509 certificate

If the client submits a certificate in the TLS handshake the TLS termination proxy must check it according to the method (tls_client_auth or self_signed_tls_client_auth) and then pass on the certificate to the Connect2id server so that the server can obtain the necessary details from it.

How is the certificate passed?

  1. The client certificate is first encoded into a PEM-encoded string, with optional additional URL-encoding applied to the PEM string;

  2. The PEM string is then inserted as a special new HTTP header into the HTTP request.

To prevent injection attacks the TLS termination proxy must be configured to remove all incoming HTTP headers bearing the same name. For extra security, in case the TLS termination proxy gets misconfigured and incoming HTTP headers are not sanitised, the header should be given a name that is hard to guess (e.g. by including a long random portion) and kept secret.

Example header to pass a PEM-encoded encoded client certificate from the TLS termination proxy to the Connect2id server:

Sec-Client-X509-Cert-alaeLuL8geiqu3OhOg1Mafa4Ecu9ahsh: -----BEGIN CERTIFICATE-----MIICsDCCAZigAwIBAgIIdF+Wcca7gzkwDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UEAwwNY2FvajdicjRpcHc2dTAeFw0xNzA4MDcxNDMyMzVaFw0xODA4MDcxNDMyMzZaMBgxFjAUBgNVBAMMDWNhb2o3YnI0aXB3NnUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdrt40Otrveq46K3BzZuds6wDqsP0kZV+C3GdyTQWl53orBRtPIiEh6BauP17Rr19qadh7t4yFBb5thrXwBewseSNEL4j7sB0YoeNwRsmA29Fjfoe0yeNpLixFadL6dz7ej9xW2suPppIO6jA5SYgL6+S42ZlIauCnSQBKFcdP8QRvgDZBZ4A7CmuloRJst7GQzppa+YWR+Zg3V5reV8Ekrkjxhwgd+rMsGahxijY7Juf2zMgLOXwe68y41SGnn+1RwezAhnJgioGiwY2gP7z2m8yNZXhpUiX+KAP2xvYb60wNYOswuqfpya68rSmYT8mQjld1EPR21dBMjRQ8HfUBAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAIUlqltRlbqiolGETmAUF8AiC008UCUmI+IsnORbHFSaACKW04m1iFH0OlxuAE1ECj1mlTcKb4md6i7n+Fy+fdGXFL73yhlSiBLu7XW5uN1/dAkynA+mXC5BDFijmvkEAgNLKyh40u/U1u75v2SFS+kLyMeqmVxvUHA7qA8VgyHi/FZzXCfEvxK5jye4L8tkAR34x5j5MpPDMfLkwLegUG+ygX+h/f8luKiQAk7eD4C59c/F0PpigvzcMpyg8+SE9loIEuJ9dRaRaTwIzez3QA7PJtrhu9h0TooTtkmF/Zw9HARrO0qXgT8uNtQDcRXZCItt1Qr7cOJyx2IjTFR2rE=-----END CERTIFICATE-----

Some proxies, such as Nginx, allow the PEM string to be additionally URL-encoded in order to escape special characters that may potentially break the header:

Sec-Client-X509-Cert-alaeLuL8geiqu3OhOg1Mafa4Ecu9ahsh: -----BEGIN%20CERTIFICATE-----MIICsDCCAZigAwIBAgIIdF%2BWcca7gzkwDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UEAwwNY2FvajdicjRpcHc2dTAeFw0xNzA4MDcxNDMyMzVaFw0xODA4MDcxNDMyMzZaMBgxFjAUBgNVBAMMDWNhb2o3YnI0aXB3NnUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdrt40Otrveq46K3BzZuds6wDqsP0kZV%2BC3GdyTQWl53orBRtPIiEh6BauP17Rr19qadh7t4yFBb5thrXwBewseSNEL4j7sB0YoeNwRsmA29Fjfoe0yeNpLixFadL6dz7ej9xW2suPppIO6jA5SYgL6%2BS42ZlIauCnSQBKFcdP8QRvgDZBZ4A7CmuloRJst7GQzppa%2BYWR%2BZg3V5reV8Ekrkjxhwgd%2BrMsGahxijY7Juf2zMgLOXwe68y41SGnn%2B1RwezAhnJgioGiwY2gP7z2m8yNZXhpUiX%2BKAP2xvYb60wNYOswuqfpya68rSmYT8mQjld1EPR21dBMjRQ8HfUBAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAIUlqltRlbqiolGETmAUF8AiC008UCUmI%2BIsnORbHFSaACKW04m1iFH0OlxuAE1ECj1mlTcKb4md6i7n%2BFy%2BfdGXFL73yhlSiBLu7XW5uN1%2FdAkynA%2BmXC5BDFijmvkEAgNLKyh40u%2FU1u75v2SFS%2BkLyMeqmVxvUHA7qA8VgyHi%2FFZzXCfEvxK5jye4L8tkAR34x5j5MpPDMfLkwLegUG%2BygX%2Bh%2Ff8luKiQAk7eD4C59c%2FF0PpigvzcMpyg8%2BSE9loIEuJ9dRaRaTwIzez3QA7PJtrhu9h0TooTtkmF%2FZw9HARrO0qXgT8uNtQDcRXZCItt1Qr7cOJyx2IjTFR2rE%3D-----END%20CERTIFICATE-----

Note: The additional URL-encoding of the PEM string is accepted since Connect2id server 8.1.

We recommend you use a random 32 character string for this header. You can use the Linux pwgen utility to generate suitable random strings:

pwgen 32

The Sec-Client-X509-Cert- prefix is intended to aid logging and debugging.

2. Configure the Connect2id server

Edit the Connect2id server configuration for the client X.509 certificate header:

op.tls.clientX509CertHeader=Sec-Client-X509-Cert-alaeLuL8geiqu3OhOg1Mafa4Ecu9ahsh

Note that the Connect2id server will check if the header name is at least 32 characters long, for the mentioned injection attack prevention. Future versions may also include a randomness check.

Also, make sure the Connect2id server is actually configured to allow tls_client_auth or self_signed_tls_client_auth authentication.

Remember to restart your Connect2id server instances for the configuration to take effect.

3. Configure the TLS termination proxy

The exact TLS termination proxy configuration is software specific, but the objectives are these:

  1. Depending on the configured mTLS client authentication method:

    • For tls_client_auth:

      • configure client certificates as optional;
      • if a client certificate is submitted configure validation for it being issued by a trusted CA (typically by providing a file with the root certificate, plus any intermediates, of the CA that issues the client certificates).
    • For self_signed_tls_client_auth:

      • configure client certificates as optional;
      • if a client certificate is submitted configure acceptance of self-signed certificates.

    Note, due to limitations of the commonly available TLS termination software, configuring simultaneous validation of CA-issued client certificates as well as acceptance of self-signed client certificates is normally not possible. Because of that a Connect2id server deployment can be configured to support either tls_client_auth or self_signed_tls_client_auth, but not both.

  2. Remove all HTTP headers with the name used to pass the client certificate to the Connect2id server, in order to block injection attacks.

  3. Insert the PEM-encoded certificate into the special HTTP header. Applying additional URL-encoding of the PEM string is recommended if the TLS termination proxy supports that.

Example proxy configurations:

Nginx (ngx_http_ssl_module)

For tls_client_auth:

server {
    listen 443 ssl;
    ssl_verify_client optional;
    ssl_trusted_certificate /path/to/clients_root_CA_cert_plus_intermediates.pem;
    proxy_set_header Sec-Client-X509-Cert-liede5vaePeeMiYie0xu2jaudauleing "";
    proxy_set_header Sec-Client-X509-Cert-liede5vaePeeMiYie0xu2jaudauleing $ssl_client_escaped_cert;
}

For self_signed_tls_client_auth:

server {
    listen 443 ssl;
    ssl_verify_client optional_no_ca;
    proxy_set_header Sec-Client-X509-Cert-liede5vaePeeMiYie0xu2jaudauleing "";
    proxy_set_header Sec-Client-X509-Cert-liede5vaePeeMiYie0xu2jaudauleing $ssl_client_escaped_cert;
}
Apache HTTPd (mod_ssl)

For tls_client_auth:

SSLVerifyClient optional
SSLCACertificateFile "/path/to/clients_root_CA_cert_plus_intermediates.pem"
RequestHeader set Sec-Client-X509-Cert-liede5vaePeeMiYie0xu2jaudauleing ""
RequestHeader set Sec-Client-X509-Cert-liede5vaePeeMiYie0xu2jaudauleing "%{SSL_CLIENT_CERT}s"

For self_signed_tls_client_auth:

SSLVerifyClient optional_no_ca
RequestHeader set Sec-Client-X509-Cert-liede5vaePeeMiYie0xu2jaudauleing ""
RequestHeader set Sec-Client-X509-Cert-liede5vaePeeMiYie0xu2jaudauleing "%{SSL_CLIENT_CERT}s"
Traefik (mTLS clientAuth)

Setting of security header name not supported as of v2.2.

TLS termination proxy configuration caveats

  1. No new lines or white space must be present in the PEM-encoded client certificate else processing of the HTTP headers may fail.

  2. Again, remember to sanitise the incoming HTTP headers -- this is imperative for security!

Tips

1. Log message displaying if the client certificate header is configured

If the Connect2id server has a client certificate header configured it will log the following line at startup:

MAIN - [OP6900] TLS termination proxy: Client X.509 certificate HTTP header: X-Client-X509...

If the header is disabled:

MAIN - [OP6900] TLS termination proxy: Client X.509 certificate HTTP header: not configured

2. mTLS authentication fails with HTTP 401

If the token request appears to be correct, but it fails with 401 check the server log. The Connect2id server returns an error message enumerating all common causes for a failed client authentication, but will deliberately not specify the concrete reason why a particular authentication failed.

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "error"             : "invalid_client",
  "error_description" : "Invalid client: Possible causes may be missing / invalid client_id, missing client authentication, ..."
}

If the logs contain the following line this is a clear sign that no client certificate was presented, most likely due to a client or proxy misconfiguration:

TOKEN - [OP6203] Missing client authentication: client_id=...

3. How to verify an mTLS deployment

A quick way to verify a Connect2id server deployment enabled for mTLS with self_signed_tls_client_auth is to register a client for the client_credentials grant and then make a token request.

  • Go to mkjwk.org and generate a new RSA key of size 2048 bits, use signature, algorithm RS256, some key ID and self-signed X.509 certificate.

  • Save the generated private key in a file key.pem.

  • Save the generated certificate in a file cert.pem. The certificate content can be examined with openssl x509 -in cert.pem -noout -text.

  • Copy the public key in JWK format and insert the certificate BASE64 string into the JWK, by setting the x5c (X.509 certificate chain) parameter.

    Example public JWK with the certificate (BASE64 / PEM encoded) in the x5c parameter, as single valued JSON array:

    {
    "keys": [
        {
            "kty" : "RSA",
            "alg" : "RS256",
            "use" : "sig",
            "kid" : "1",
            "n"   : "9HrVGuF7iyoR9oOIu-kISItytKxDLb-BdGmsqx-EBhVI11Q4DhfoxzNyaOWPaPcR6RpPbVAFY-drZgEH4SAQcVUzCUB2DKjLaZaBbCOWu3NYnif2XN0EwMiw4X7XD1qsvzoZbM72ApJ9AcZgPpq9suv8fZoOc__-lhTLTqAK5Ww9j-a_Fh3ADzWYcUfaHXZqQSMfIZTx2b0_X5Uech4ILrFUiEPhpf9zEmF5_Git2UYScwfXb9mW2OjXVVrE8zuI_RH97mSV82QVD_pr2Ikd1LJgB1xYkms5kUlzAm2diw60nqty3KMp_XAUe8fv0vD58Oqe2rNvl-4y8KIBWi8piQ",
            "e"   : "AQAB",
            "x5c" : [ "MIICljCCAX6gAwIBAgIGAYgE5hzPMA0GCSqGSIb3DQEBCwUAMAwxCjAIBgNVBAMMATEwHhcNMjMwNTEwMDkwMjQ5WhcNMjQwMzA1MDkwMjQ5WjAMMQowCAYDVQQDDAExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9HrVGuF7iyoR9oOIu+kISItytKxDLb+BdGmsqx+EBhVI11Q4DhfoxzNyaOWPaPcR6RpPbVAFY+drZgEH4SAQcVUzCUB2DKjLaZaBbCOWu3NYnif2XN0EwMiw4X7XD1qsvzoZbM72ApJ9AcZgPpq9suv8fZoOc//+lhTLTqAK5Ww9j+a/Fh3ADzWYcUfaHXZqQSMfIZTx2b0/X5Uech4ILrFUiEPhpf9zEmF5/Git2UYScwfXb9mW2OjXVVrE8zuI/RH97mSV82QVD/pr2Ikd1LJgB1xYkms5kUlzAm2diw60nqty3KMp/XAUe8fv0vD58Oqe2rNvl+4y8KIBWi8piQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQC9YQvdqFUfXXOEw0X+z/14RQwAVzTK1cqqtBZJTmUCyXc51jm5hfsN3jnoYEmS888EM55KWF1PlPr0G1P7kvs6sMhhKRJQigxeQmw1YHOIWLRHywI+M0ZLpDcBRLbWtEBPIEuN4DLXM9vnGX/UF05Zgk5/U1oM8Vg1MIfXaIIwshpB3y41vRSJXrdrqxGIwApdCRZX6usYZpiHmbkLWN+0t/jsEggmCoPfOfZKwFTetkAU+hxGE4QJPQ+I/ahhu1XCrejMEAShV2pLFm9VP4ECwjlbQjAqmInE7GhZlerNdwYEbLjr5yOnVLT+XJUPjDdzs/ImDk/8mEQ0qpzSZxTl" ]
        }
    ]
    }
    
  • Register a client for the client_credentials grant with mTLS authentication using a self-signed certificate. Pass the public JWK in a JWK set structure. The registration request is authorised with the configured master token for the clients endpoint.

    Example HTTP request:

    POST /clients HTTP/1.1
    Host: demo.c2id.com
    Content-Type: application/json
    Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
    
    {
    "grant_types"                : [ "client_credentials" ],
    "scope"                      : "read write",
    "token_endpoint_auth_method" : "self_signed_tls_client_auth",
    "jwks"                       : {
        "keys": [
            {
                "kty" : "RSA",
                "alg" : "RS256",
                "use" : "sig",
                "kid" : "1",
                "n"   : "9HrVGuF7iyoR9oOIu-kISItytKxDLb-BdGmsqx-EBhVI11Q4DhfoxzNyaOWPaPcR6RpPbVAFY-drZgEH4SAQcVUzCUB2DKjLaZaBbCOWu3NYnif2XN0EwMiw4X7XD1qsvzoZbM72ApJ9AcZgPpq9suv8fZoOc__-lhTLTqAK5Ww9j-a_Fh3ADzWYcUfaHXZqQSMfIZTx2b0_X5Uech4ILrFUiEPhpf9zEmF5_Git2UYScwfXb9mW2OjXVVrE8zuI_RH97mSV82QVD_pr2Ikd1LJgB1xYkms5kUlzAm2diw60nqty3KMp_XAUe8fv0vD58Oqe2rNvl-4y8KIBWi8piQ",
                "e"   : "AQAB",
                "x5c" : [ "MIICljCCAX6gAwIBAgIGAYgE5hzPMA0GCSqGSIb3DQEBCwUAMAwxCjAIBgNVBAMMATEwHhcNMjMwNTEwMDkwMjQ5WhcNMjQwMzA1MDkwMjQ5WjAMMQowCAYDVQQDDAExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9HrVGuF7iyoR9oOIu+kISItytKxDLb+BdGmsqx+EBhVI11Q4DhfoxzNyaOWPaPcR6RpPbVAFY+drZgEH4SAQcVUzCUB2DKjLaZaBbCOWu3NYnif2XN0EwMiw4X7XD1qsvzoZbM72ApJ9AcZgPpq9suv8fZoOc//+lhTLTqAK5Ww9j+a/Fh3ADzWYcUfaHXZqQSMfIZTx2b0/X5Uech4ILrFUiEPhpf9zEmF5/Git2UYScwfXb9mW2OjXVVrE8zuI/RH97mSV82QVD/pr2Ikd1LJgB1xYkms5kUlzAm2diw60nqty3KMp/XAUe8fv0vD58Oqe2rNvl+4y8KIBWi8piQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQC9YQvdqFUfXXOEw0X+z/14RQwAVzTK1cqqtBZJTmUCyXc51jm5hfsN3jnoYEmS888EM55KWF1PlPr0G1P7kvs6sMhhKRJQigxeQmw1YHOIWLRHywI+M0ZLpDcBRLbWtEBPIEuN4DLXM9vnGX/UF05Zgk5/U1oM8Vg1MIfXaIIwshpB3y41vRSJXrdrqxGIwApdCRZX6usYZpiHmbkLWN+0t/jsEggmCoPfOfZKwFTetkAU+hxGE4QJPQ+I/ahhu1XCrejMEAShV2pLFm9VP4ECwjlbQjAqmInE7GhZlerNdwYEbLjr5yOnVLT+XJUPjDdzs/ImDk/8mEQ0qpzSZxTl" ]
            }
        ]
    }
    }
    
  • Make a token request with a client credentials grant, remembering to pass the self-signed client certificate.

    Example HTTP request (the client certificate cannot be shown):

    POST /token HTTP/1.1
    Host: demo.c2id.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=client_credentials&client_id=b6pci47ccuoum
    

    As curl command:

    curl -v --cert cert.pem --key key.pem https://demo.c2id.com/token \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'grant_type=client_credentials' \
    --data-urlencode 'client_id=b6pci47ccuoum'
    

    Example HTTP response:

    HTTP/1.1 200
    Cache-Control: no-store
    Pragma: no-cache
    Content-Type: application/json;charset=UTF-8
    
    {
    "access_token" : "eyJraWQiOiJDWHVwIiwidHlwIjoiYXQrand0IiwiYWxnIjoiUlMyNTYif
                      Q.eyJzdWIiOiJiNnBjaTQ3Y2N1b3VtIiwic2NwIjpbInJlYWQiLCJ3cml
                      0ZSJdLCJpc3MiOiJodHRwczovL2RlbW8uYzJpZC5jb20iLCJjbmYiOnsi
                      eDV0I1MyNTYiOiI1TGpfVU4yZDVyWklpUVB4Yl9Jd01yRGl4RnBhSDlXN
                      Ud1U291MTd0MDk4In0sImV4cCI6MTY4Mzc4OTQ3OCwiaWF0IjoxNjgzNz
                      g4ODc4LCJqdGkiOiJhajdsWUVnazU4MCIsImNpZCI6ImI2cGNpNDdjY3V
                      vdW0ifQ.MuEY4-cmfO3ZjhwO0xAXjlUXEu-MKOsewhotNTtyzSyLhS3Yh
                      G8F6OgVEfCN0oEBiym916qqsNPHn_K0zJrSwVvpGwTB3S3hlba5mH8VJa
                      bb1lpxsOYVKTGtSy_rsupIRif_freJw2n-h4m0wh7rCzPciBM3Rhjapbd
                      s9ae2YYYsULnWqZ6NbN_9CZXmPCrydzmbv8B0uQF430n401FanRHmNF3F
                      YNvWBjHJSOQSuUdB29II-yqBeJ0AyIMYthAtL0dK-ylI0D1q3Q6ljHzFo
                      ntkkxxtE1AB_N7Q1w_B4taMW53r0awT0OGfxlicBGUBuk4QT2yGCz3ZSw
                      1b_iiBwA",
    "token_type"   : "Bearer",
    "scope"        :  "read write",
    "expires_in"   : 600
    }
    

    Inspecting the access token as JWT must show the client certificate binding in the cnf.x5t#S256 (confirmation of X.509 certificate SHA-256 thumbprint) claim:

    {
    "iss" : "https://demo.c2id.com",
    "sub" : "b6pci47ccuoum",
    "cid" : "b6pci47ccuoum",
    "scp" : [ "read", "write" ],
    "iat" : 1683788637,
    "exp" : 1683789237,
    "jti" : "JJk9goknCGg",
    "cnf" : { "x5t#S256" : "5Lj_UN2d5rZIiQPxb_IwMrDixFpaH9W5GuSou17t098" }
    }
    

    Transcoding the cnf.x5t#S256 to HEX must produce the same output as the openssl x509 -sha256 -in cert.pem -fingerprint -noout command.

    The SHA-256 hex fingerprint output by openssl for the example certificate:

    sha256 Fingerprint=E4:B8:FF:50:DD:9D:E6:B6:48:89:03:F1:6F:F2:30:32:B0:E2:C4:5A:5A:1F:D5:B9:1A:E4:A8:BB:5E:ED:D3:DF
    

4. How to configure Tomcat to log a request HTTP header

The Apache Tomcat HTTP access logging is configured by the following XML element in tomcat/conf/server.xml:

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       prefix="localhost_access_log" suffix=".txt"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />

To log an incoming HTTP header add %{xxx}i to the pattern element where xxx is the name of the HTTP header.

If the header name is X-Client-X509-Cert-alaeLuL8geiqu3OhOg1Mafa4Ecu9ahsh:

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       prefix="localhost_access_log" suffix=".txt"
       pattern="%h %l %u %t &quot;%r&quot; %{X-Client-X509-Cert-alaeLuL8geiqu3OhOg1Mafa4Ecu9ahsh}i %s %b" />

This will then log a line similar to this one in tomcat/logs/localhost_access_log.YYYY-MM-DD.txt:

127.0.0.1 - - [15/May/2020:12:54:10 +0300] "POST /c2id/token HTTP/1.1" -----BEGIN%20CERTIFICATE-----MIICsDCCAZigAwIBAgIIQSxFDTCDGrEwDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UEAwwNajZvdWdmeHVmN2E1dzAeFw0yMDA1MTUwOTU0MDlaFw0yMTA1MTUwOTU0MTBaMBgxFjAUBgNVBAMMDWo2b3VnZnh1ZjdhNXcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrBbE8ONDDSN
ugiW8KgSMSST6BepNDUnvm8vYPNm0j0%2BPAaUYmQ%2F%2BYtbd8OG%2BFyWfzbk0fYnUdNI15cwjh2%2F3SK2DWpRtLgTPzoqJAZoNrLv9ygyvj%2BU%2FTKFFrLGU9xsPx%2BaNVE%2FbTj01TqAzHhUnEI2aocY3AO2Guigkb%2F%2FaQxZI6FKi3dmmXr5l0EyJhbKEiOY8%2Fc3%2B57Pfv8AVKD8v%2BG3yyf3NeIthXLLuuyBZR%2F3rnn6FHAX0Rv0l0AibudN8v9YjjgGkOROTTcuOtcDeh9qeXwNVf5CXqu3K75A%2Bq
u1lR6bDREoU6lpCYKspYn2tOs8d8VN1XGGUV4241wFbNAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAvyw44rwgAOClRXyNhbjQhi9LdTMRsx8LDFhAgM9XrSws8czi2sPF2D587xPPu%2F3ZufFduTqnoP3KI0aRwrOL%2FDDCo3QeMku9rVPxG3bB7nZ%2F%2Fr2%2FWGVJe%2Bi1sQSAaP5MQ%2FoakOtr1obKNo9NZNIQwS6LcrY778SSn%2BrlB9lzqs0Q8bF%2FZkyqVnVL9e18UKvO3fU8M8BI2KJh1xQpKFPGJUuQEhklq5
cfAWyZjx6x2wvHuSxbq%2FSWh%2F%2FhEpFjMSihO%2BllU2WV%2FqQueFRm2E0w7J2FdRM9l2PpKdNs8Txj5EAg7PasENKOjCOeU5l1Y7lvnE3fmHSSQpbsv4pXvaLmU%3D-----END%20CERTIFICATE----- 200 781