Handling Certificates

Certificate handling

Certificates are used in multiple places in OIDC:

  • authenticating the server
  • authenticating the client
  • augmenting a public key with metadata
  • establishing trust on a public key

Authorization servers are required to expose and consume certificates to support those use cases, therefore Authlete allows certificates to be included in different attributes of Service and Client to facilitate implementation of the authorization server.

Trusted root certificates

The trusted_root_certificates property (list of trusted root certificates) of service is a list of the root CA’s certificates in PEM format. The example below shows how you can declare multiple CA certificates using the local_file data source:

data "local_file" "ca_ec" {
   filename = "${path.module}/ca_ec.crt"
}

data "local_file" "ca_rsa" {
   filename = "${path.module}/ca_rsa.pem"
}

resource "authlete_service" "as" {
   issuer = "https://${terraform.workspace}.mydomain.com"
   service_name = "My_RSA_AS_${terraform.workspace}"
   description = "A terraform based service for managing the ${terraform.workspace} Authlete based OAuth server"
   supported_grant_types = ["AUTHORIZATION_CODE"]
   supported_response_types = ["CODE"]
   access_token_sign_alg = "RS256"
   access_token_signature_key_id = "rsa1"
   trusted_root_certificates = [ data.local_file.ca_rsa.content, data.local_file.ca_ec.content ]
...
}

JWS and JWE support

The public keys of clients and services can be fetched from PEM certificate files, including or not the chain of certificates. When loading the public key from X509 certificates, the provider will populate the x5c, x5t, and x5t#S256 properties of JWK.

If you use a private key PEM file (via the pem_private_key property), the public keys will be already available.

If you provide a certificate using RSA or EC key, some JWK attributes will be populated for you. The kid, use, and alg might be guessed but can’t be inferred from the certificate, so you will need to define those attributes.

  • In case of RSA public key, the attributes kty, e, n, x5c, x5t, and x5t#S256 are populated from the X509 certificate.
  • In case of EC public key, the attributes kty, crv, x, y, x5c, x5t, and x5t#S256 are populated from the certificate.

The declaration of the public keys will be as the examples below:

resource "authlete_service" "as" {
  ...
   jwk {
      kid = "rsa4"
      alg = "RS256"
      use = "sig"
      pem_certificate = file("server_rsa_cert.pem")
      pem_certificate = file("server_rsa_cert.pem")
   }
   ...
   jwk {
      kid = "ec4"
      alg = "ES256"
      use = "sig"
      pem_certificate = file("server_ec_cert.pem")
      pem_private_key = file("server_ec_key.pem")
   }
}
  
resource "authlete_client" "portal" {
...
   jwk {
      kid = "cli1"
      alg = "RS256"
      use = "sig"
      pem_certificate = file("client_rsa_cert.crt")
   }
  
}

resource "authlete_client" "portal2" {
...
   jwk {
      kid = "cli1"
      alg = "ES256"
      use = "sig"
      pem_certificate = file("client_ec_cert.pem")
   }
  
}

That will generate JWKs including all the attributes required for representing the public key as below:

Service JWKs:

{
  keys: [
    {
        "d": "qEgVnYm62SCf0WYy8Q5SncOCV8Y-aOQ5MbcTwWgh5J5nn3wnTvq_efQiGwXekdcPhiI0oQz_USHEOGwPhiQtY_grhutnzK7wIDvrzrNtDU8jnNXn5XZAbLYinerChICTjGZqdyoHElHPLPpYdAqD2Gxn_0LEw7BRr67_sox2x0W9W3EIzWQhO-1a_Ur3VRTqYfO-dA737cB3cr2Snvbt1Y3AtCxgNahWXlIMH8pzWhnMcImf4Gdr5wGwFvoO2KX3ak7OJd9skAJbsNwrYNaWLc8-DNYl-Dsl-S1jEvz_9V6_X1yxktB_BGKAAm_pm-Szk0esVh0GaX6OwJkxKzOpcQ",
        "e": "AQAB",
        "use": "sig",
        "kid": "rsa2",
        "x5c": [
          "MIIEwTCCAqmgAwIBAgIID+K+XgJff98wDQYJKoZIhvcNAQELBQAwUDELMAkGA1UEBhMCYnIxCzAJBgNVBAgTAkVTMRAwDgYDVQQHEwdWaXRvcmlhMREwDwYDVQQKEwhBdXRobGV0ZTEPMA0GA1UEAwwGcnNhX2NhMB4XDTIyMDcwNjE5NTEwMFoXDTIzMDcwNjE5NTEwMFowUzELMAkGA1UEBhMCYnIxCzAJBgNVBAgTAkVTMRAwDgYDVQQHEwdWaXRvcmlhMREwDwYDVQQKEwhBdXRobGV0ZTESMBAGA1UEAwwJc2VydmVyX29wMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA71UPBn2cS7qP89sdIlWEv2KrsTopLuWeIpbzB98V8U1OIvb0YPcCHtpLq+P8u1aceyPotR3AW49BIJ4VzPdTSx+rMmBV0iNv4y289eEZa5Ipvk9TFtEmf7vR6ZMmM1xK7+fcYyf5AIhcZClt5OrFpTboHYadJ5l/rjpRSNxE7i7b34Bi1A/HEgmA3GuPV8yf8nDRwGtzBC+nd5tX7gugDbVw/5fF+HDBGcB4u7Fm6fK6T4C37ohxvI6RWphB3AuEa+UdkR9ceill1Pz0ID+SLdO2Jt+DnxNCNqBa0ezLY70g0no6YkvLcnzbaNh82yE28p1IhweF4CP4b6NyPDIisQIDAQABo4GbMIGYMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFGrTFrTNXRXUDJwCxueMIhznWSw9MAsGA1UdDwQEAwID6DATBgNVHSUEDDAKBggrBgEFBQcDATAUBgNVHREEDTALgglzZXJ2ZXJfb3AwEQYJYIZIAYb4QgEBBAQDAgZAMB4GCWCGSAGG+EIBDQQRFg94Y2EgY2VydGlmaWNhdGUwDQYJKoZIhvcNAQELBQADggIBACBKbO/kmaQ2HGxjmy4Vnap5D45ydgOVzFy1juw/QhyyX+Cth71CONt/39tJlE12vJcqcZxV1JMnY3JI5rrX62YxuczCrU5W2+Xn5Jo7lY0mFvGbi89bXQruHIDMnLpyXw4Ri5UkaMTuG/crAj26pMGnCcWFhos7knKQQ4Yu2zwYymhNWlVAbNxTPvM5fcTHSNB2nxU/Q8UqOIzFAKL1iCBPlF3BDaLijQxA6aGYzouiefnzy3ODjOuIy3qM4yfD1gh9jHrRs+h+TJZ3PQ4xZfBkgVMkQcOcsjWEOZf+uXQTVMHF7Y4c41u8VG3IljLCS0ipD86nLq9wbTYRlA3to3IRCj9PwGCZIUALqmmmgRnw834P90mp8GsLtTbVTGO/zLRI46MHeeLiJmeaHVItOpqn5ahpiauqrdXpoGTlecqmfAkyREn64xkTwGqDqL5X0NMIXre+7ydZb56PpZFb8CBviEGmTW6hYvsqHp7E3phPoOs72zww1jTipCC43DrGbYk/FoBjj6SORHpE456Zaj7rboJortVwkI8uwzg799wimTWvz2kGQT4+zDvQMa38XrEuAO8fhqf+2I9QSSLrHMO4MyflFnuLf8KLC3ochRzCJDbkB9K8s/DiELK3pj7NZXwUzT5pxF3n5oZDm/0k4YruLQ7bFY+/xjRBH+741916"
        ],
        "dp": "T8u01EO-rMrx4oR2OnAVg8of6Z-anxFoc_63RGsxlnNvNuKhIbzaxl97MJ5GTKaLWYzQ7Hc_sYOJ2i5-M-eyUYfU3COX4vJ0_H90YJYsemcI1QmaPiQ6da2AZJwXLz_b4x4xTupdOfKpkhiT2yMOvVy8JWGf5GppfWaJ6H43LAE",
        "dq": "XPsQmfFR5VgERHFmzZMz7MOyao0rH6zU9vykvUdj58bdsJ5S_xNrV9QoHhZn9iCVk0TTaIvlWoGrkx9UJ3vnGOL09xklC2hwFTzRC5UhF7mpQaP7Wbl0uKIFS-E-_HH1QLBeOllfidWzq788JsVMSHhyHkAJcNrLTl2a3Pq1Gd0",
        "n": "71UPBn2cS7qP89sdIlWEv2KrsTopLuWeIpbzB98V8U1OIvb0YPcCHtpLq-P8u1aceyPotR3AW49BIJ4VzPdTSx-rMmBV0iNv4y289eEZa5Ipvk9TFtEmf7vR6ZMmM1xK7-fcYyf5AIhcZClt5OrFpTboHYadJ5l_rjpRSNxE7i7b34Bi1A_HEgmA3GuPV8yf8nDRwGtzBC-nd5tX7gugDbVw_5fF-HDBGcB4u7Fm6fK6T4C37ohxvI6RWphB3AuEa-UdkR9ceill1Pz0ID-SLdO2Jt-DnxNCNqBa0ezLY70g0no6YkvLcnzbaNh82yE28p1IhweF4CP4b6NyPDIisQ",
        "p": "_DKf_-iHtdjfYEagYah-RSGgPmntz45QqMelLKwfoA_fVlgADc1jmGxEJj2EewXTwRal1836Lqg9NNgBNvyFcn7kyi2t6GyK2e5uOQTm67Kbmxd_TjQOisPT-gfZbIgJ6c2vLJarHW5EAmWatmgF7l0niETOS_qkDAy7ceDJNm0",
        "kty": "RSA",
        "x5t#S256": "xIFtb8juze-EPXBpJHFIXESG2aSP_lM41iFsz0lQwzo=",
        "q": "8vDHRkSvfaBNsZKk2_EdR_Bljaq24b0ItDcxHwnCSQr3VGo4qIHYsuM_suiJYTgEsX0KwtPgwMNdxYxwYKxDxtNtqk-B0TW64YDLOm6KBAyf8XA0uMedomWm9fkRlP0Bq5I2Q1X8QaiMiFewnex_JTqpGh546SahvOoPJt7nAtU",
        "x5t": "SZQ3eVG5qqIgWYwbb5rzQDEWA4s=",
        "qi": "91xsKekO9sAv2-eKBxUEheHUFHpQz4kmoZY5FpujUYKsSvTQ8OzaZ1S3hoFXwPGd7b6V0oICZhANVTbfPTSq48w63L3MU8x1f4CJjcgaYrH7FR0K3YIaG3818T8971SIzCxhGKVrpnf550XlroXAtq1HaP0tFnO_ggAbOwd1HWY",
        "alg": "RS256"
    },
    {
        "kty": "EC",
        "x5t#S256": "hXIRmXMcBhGWUXT-3jjiu3FsfHtNRzS8zo_yHKeEtNU=",
        "d": "b61zHfrU7_2UzYeKx7xV0fw4rcVLtr80QMlmD3AaayU",
        "use": "sig",
        "x5t": "ce9gSmOTYfOPZQTm9EPLbLjzzMY=",
        "crv": "P-256",
        "kid": "ec2",
        "x5c": [
          "MIICTTCCAdKgAwIBAgIIJWO8OofetF8wCgYIKoZIzj0EAwIwTzELMAkGA1UEBhMCYnIxCzAJBgNVBAgTAmVzMRAwDgYDVQQHEwdWaXRvcmlhMREwDwYDVQQKEwhBdXRobGV0ZTEOMAwGA1UEAwwFZWNfY2EwHhcNMjIwNzA2MTk1NTAwWhcNMjMwNzA2MTk1NTAwWjBPMQswCQYDVQQGEwJCUjELMAkGA1UECBMCRVMxEDAOBgNVBAcTB1ZpdG9yaWExETAPBgNVBAoTCEF1dGhsZXRlMQ4wDAYDVQQDDAVlY19vcDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKR8g0fG81EGXSsU96GDjK8PtWPBPbPb3S3J35X+En7p1RYH8nmzmsJ1wxabpvjYdWR8FI8M3Tm2vfMh3TIu0USjgZcwgZQwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUGI75XaWvWLi6rqx8FYbeiNdhfJswCwYDVR0PBAQDAgPoMBMGA1UdJQQMMAoGCCsGAQUFBwMBMBAGA1UdEQQJMAeCBWVjX29wMBEGCWCGSAGG+EIBAQQEAwIGQDAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRlMAoGCCqGSM49BAMCA2kAMGYCMQCLDureFMtAi7YP21tGLOfKDgT5O23lLqgbOWBmhki41Tg0mWDlq/9HrV12Qo07lnoCMQDSeAkpO27p3qqYN18h669COiRfkAxnUXVmc+Ot5yzaMTqjAM2J+JgzNW6sf2sOyYw="
        ],
        "x": "pHyDR8bzUQZdKxT3oYOMrw-1Y8E9s9vdLcnflf4Sfuk",
        "y": "1RYH8nmzmsJ1wxabpvjYdWR8FI8M3Tm2vfMh3TIu0UQ",
        "alg": "ES256"
    }
  ]
}

The JWK rendered on client definition on the server side will be as below:

RSA client:

{
  "keys": [
    {
      "kty": "RSA",
      "x5t#S256": "t-a0q1pOUE1bTh0JtIRKyv4pcRbGP69M2ZJd7hZ5BxE=",
      "e": "AQAB",
      "use": "sig",
      "x5t": "gHwC6AvSUo3_0kdMNePZ3Lln4Ww=",
      "kid": "cli1",
      "x5c": [
        "MIIEqTCCApGgAwIBAgIIMS7U5PYTrDcwDQYJKoZIhvcNAQELBQAwUDELMAkGA1UEBhMCYnIxCzAJBgNVBAgTAkVTMRAwDgYDVQQHEwdWaXRvcmlhMREwDwYDVQQKEwhBdXRobGV0ZTEPMA0GA1UEAwwGcnNhX2NhMB4XDTIyMDcxMTE0MjgwMFoXDTIzMDcxMTE0MjgwMFowUTELMAkGA1UEBhMCYnIxCzAJBgNVBAgTAmVzMRAwDgYDVQQHEwd2aXRvcmlhMREwDwYDVQQKEwhBdXRobGV0ZTEQMA4GA1UEAwwHcnNhX2NsaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL+Mn+vwYxJ6OsiHymHm9WprWamooT3x/qEtx41JQBWYFiEIHJS8fAYQIwqzNlzrn2WJJuH1kdG89hSDi6slSxYCt3ZHwpiNtaD8VqPH1GF0EL31n1IFXKjFECjKUhcvu07ow9WzoJ1ti+G8U/d1edjJOsTgdhrc+ehdhJA0PWUigLfCq639jHkFTAR37B3KXoNqVUROY39gMbx5V/PKCpwh7HoLlyydUnebb0qLtTwWIJgpGCV2vGuNj9CEJpN9NA3xX8pvG3YIZJjuuPCSZWIyps+t2BM+s799emygVu+PUIVG97/2Fh5dhTJ8dJo8eokYIH83tmwNmFCrezFkT4UCAwEAAaOBhTCBgjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRq3YyxPGBl1t94kjg7oBvv+uSCHzALBgNVHQ8EBAMCA7gwEwYDVR0lBAwwCgYIKwYBBQUHAwIwEQYJYIZIAYb4QgEBBAQDAgWgMB4GCWCGSAGG+EIBDQQRFg94Y2EgY2VydGlmaWNhdGUwDQYJKoZIhvcNAQELBQADggIBAIt85Da0F8WvMXiFlaGMew+2vzoXzyZ5GYEvniHPjRIgO9f1urgXEjMKxS1dfn87Zd2TrTTO/UwbkTh6WnMgs5Uuhg9EYeZJ1tbHW3jdrbWOUFzDapImM/JElO4k+Srdcr97m9lN9k8AWPK8IJWGrvvMnwkAQ4rT3gUIUe027CwFw2rL1UsUqpg2ZglzifLm6HcGJoC76eJi86+k+9+9rT02pWPvcvfIq+P3S6ZUjODoIF8OvuLG7SJXlssBMWY5rb/IyGhTvj/1lY0p0A41VbkC4jZLp1Ar69ukorh5Wnzaqtv3HsQ0o+07cxxVCgHdyBXZ5x/1SVPaKvBze2Klwzm+UXwT3miu1HiS26cX6Aa2WymFwtsK1m0NRIUx1H84eT77QvTeDx3IHlQFtOptoC7Mu8UQid7fbCzbk72+eHB5QE2IDAsT3+D/Th76w4fKh2v29/Si+tjT9/MqoQkERxTF/OMvhpriveoJ3p0Oilg15zComFstj6WplC1hjLmLOlaKwsi9BhmqBKTp84hD0GKiDExIezak8Z3yM5cdVi5d+mT+cO495Ispzt9Wgm5WHNldsIG0zsrPFYPC+8YRAw4aDMVqDj6RpB0quijhchyPp6ZcTENi9zQx9Bz8oIZwSTQOly8xxz04an4K/8pMGaVfBsSW7EQoueiR+69mucah"
      ],
      "alg": "RS256",
      "n": "v4yf6_BjEno6yIfKYeb1amtZqaihPfH-oS3HjUlAFZgWIQgclLx8BhAjCrM2XOufZYkm4fWR0bz2FIOLqyVLFgK3dkfCmI21oPxWo8fUYXQQvfWfUgVcqMUQKMpSFy-7TujD1bOgnW2L4bxT93V52Mk6xOB2Gtz56F2EkDQ9ZSKAt8Krrf2MeQVMBHfsHcpeg2pVRE5jf2AxvHlX88oKnCHseguXLJ1Sd5tvSou1PBYgmCkYJXa8a42P0IQmk300DfFfym8bdghkmO648JJlYjKmz63YEz6zv316bKBW749QhUb3v_YWHl2FMnx0mjx6iRggfze2bA2YUKt7MWRPhQ"
    }
  ]
}

EC client:

{
  "keys": [
    {
      "kty": "EC",
      "x5t#S256": "ry5BGq-8SjFGW7qF5CaND5nbfAQtSV8bc07Dw2ajS_k=",
      "use": "sig",
      "x5t": "fyitL1mLbo4qinKoNwSCTDUlkNg=",
      "crv": "P-256",
      "kid": "cli1",
      "x5c": [
        "MIICOzCCAcGgAwIBAgIIWCYugLSRzh0wCgYIKoZIzj0EAwIwTzELMAkGA1UEBhMCYnIxCzAJBgNVBAgTAmVzMRAwDgYDVQQHEwdWaXRvcmlhMREwDwYDVQQKEwhBdXRobGV0ZTEOMAwGA1UEAwwFZWNfY2EwHhcNMjIwNzExMTQyOTAwWhcNMjMwNzExMTQyOTAwWjBQMQswCQYDVQQGEwJicjELMAkGA1UECBMCZXMxEDAOBgNVBAcTB3ZpdG9yaWExETAPBgNVBAoTCEF1dGhsZXRlMQ8wDQYDVQQDDAZlY19jbGkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQHTsEYCM0XqXsO6H1XRHeAZ8vsuJA4PM8JKDU+LH5Pep44CDSysTD+7206awaJEDF0f+HkRU1EOMNWYnNQBaSHo4GFMIGCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFBlcinWHTKgZoD9oqnuzy8jALs40MAsGA1UdDwQEAwIDuDATBgNVHSUEDDAKBggrBgEFBQcDAjARBglghkgBhvhCAQEEBAMCBaAwHgYJYIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0ZTAKBggqhkjOPQQDAgNoADBlAjBExTk22WfzyyseoV78KLZ5QYK9OdMRTxLgXg85sGQok0lsQjnfITXuq08CjXTJfboCMQChAvVvOeDBvMM1572oPEo1PtuF5geFViYWxt2chWb2/FjoiKjJFn3Y1sC1onxs2W0="
      ],
      "x": "B07BGAjNF6l7Duh9V0R3gGfL7LiQODzPCSg1Pix-T3o",
      "y": "njgINLKxMP7vbTprBokQMXR_4eRFTUQ4w1Zic1AFpIc",
      "alg": "ES256"
    }
  ]
}