7.2. Getting a Nonce
Before sending a POST request to the server, an ACME client needs to have a fresh anti-replay nonce to put in the "nonce" header of the JWS. In most cases, the client will have gotten a nonce from a previous request. However, the client might sometimes need to get a new nonce, e.g., on its first request to the server or if an existing nonce is no longer valid. To get a fresh nonce, the client sends a HEAD request to the newNonce resource on the server. The server's response MUST include a Replay- Nonce header field containing a fresh nonce and SHOULD have status code 200 (OK). The server MUST also respond to GET requests for this resource, returning an empty body (while still providing a Replay- Nonce header) with a status code of 204 (No Content). HEAD /acme/new-nonce HTTP/1.1 Host: example.com HTTP/1.1 200 OK Replay-Nonce: oFvnlFP1wIhRlYS2jTaXbA Cache-Control: no-store Link: <https://example.com/acme/directory>;rel="index" Proxy caching of responses from the newNonce resource can cause clients to receive the same nonce repeatedly, leading to "badNonce" errors. The server MUST include a Cache-Control header field with the "no-store" directive in responses for the newNonce resource, in order to prevent caching of this resource.7.3. Account Management
In this section, we describe how an ACME client can create an account on an ACME server and perform some modifications to the account after it has been created. A client creates a new account with the server by sending a POST request to the server's newAccount URL. The body of the request is a stub account object containing some subset of the following fields: contact (optional, array of string): Same meaning as the corresponding server field defined in Section 7.1.2. termsOfServiceAgreed (optional, boolean): Same meaning as the corresponding server field defined in Section 7.1.2.
onlyReturnExisting (optional, boolean): If this field is present with the value "true", then the server MUST NOT create a new account if one does not already exist. This allows a client to look up an account URL based on an account key (see Section 7.3.1). externalAccountBinding (optional, object): Same meaning as the corresponding server field defined in Section 7.1.2 POST /acme/new-account HTTP/1.1 Host: example.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "jwk": {...}, "nonce": "6S8IqOGY7eL2lsGoTZYifg", "url": "https://example.com/acme/new-account" }), "payload": base64url({ "termsOfServiceAgreed": true, "contact": [ "mailto:cert-admin@example.org", "mailto:admin@example.org" ] }), "signature": "RZPOnYoPs1PhjszF...-nh6X1qtOFPB519I" } The server MUST ignore any values provided in the "orders" fields in account objects sent by the client, as well as any other fields that it does not recognize. If new fields are specified in the future, the specification of those fields MUST describe whether they can be provided by the client. The server MUST NOT reflect the "onlyReturnExisting" field or any unrecognized fields in the resulting account object. This allows clients to detect when servers do not support an extension field. The server SHOULD validate that the contact URLs in the "contact" field are valid and supported by the server. If the server validates contact URLs, it MUST support the "mailto" scheme. Clients MUST NOT provide a "mailto" URL in the "contact" field that contains "hfields" [RFC6068] or more than one "addr-spec" in the "to" component. If a server encounters a "mailto" contact URL that does not meet these criteria, then it SHOULD reject it as invalid.
If the server rejects a contact URL for using an unsupported scheme, it MUST return an error of type "unsupportedContact", with a description of the error and what types of contact URLs the server considers acceptable. If the server rejects a contact URL for using a supported scheme but an invalid value, then the server MUST return an error of type "invalidContact". If the server wishes to require the client to agree to terms under which the ACME service is to be used, it MUST indicate the URL where such terms can be accessed in the "termsOfService" subfield of the "meta" field in the directory object, and the server MUST reject newAccount requests that do not have the "termsOfServiceAgreed" field set to "true". Clients SHOULD NOT automatically agree to terms by default. Rather, they SHOULD require some user interaction for agreement to terms. The server creates an account and stores the public key used to verify the JWS (i.e., the "jwk" element of the JWS header) to authenticate future requests from the account. The server returns this account object in a 201 (Created) response, with the account URL in a Location header field. The account URL is used as the "kid" value in the JWS authenticating subsequent requests by this account (see Section 6.2). The account URL is also used for requests for management actions on this account, as described below. HTTP/1.1 201 Created Content-Type: application/json Replay-Nonce: D8s4D2mLs8Vn-goWuPQeKA Link: <https://example.com/acme/directory>;rel="index" Location: https://example.com/acme/acct/evOfKhNU60wg { "status": "valid", "contact": [ "mailto:cert-admin@example.org", "mailto:admin@example.org" ], "orders": "https://example.com/acme/acct/evOfKhNU60wg/orders" }7.3.1. Finding an Account URL Given a Key
If the server receives a newAccount request signed with a key for which it already has an account registered with the provided account key, then it MUST return a response with status code 200 (OK) and provide the URL of that account in the Location header field. The
body of this response represents the account object as it existed on the server before this request; any fields in the request object MUST be ignored. This allows a client that has an account key but not the corresponding account URL to recover the account URL. If a client wishes to find the URL for an existing account and does not want an account to be created if one does not already exist, then it SHOULD do so by sending a POST request to the newAccount URL with a JWS whose payload has an "onlyReturnExisting" field set to "true" ({"onlyReturnExisting": true}). If a client sends such a request and an account does not exist, then the server MUST return an error response with status code 400 (Bad Request) and type "urn:ietf:params:acme:error:accountDoesNotExist".7.3.2. Account Update
If the client wishes to update this information in the future, it sends a POST request with updated information to the account URL. The server MUST ignore any updates to the "orders" field, "termsOfServiceAgreed" field (see Section 7.3.3), the "status" field (except as allowed by Section 7.3.6), or any other fields it does not recognize. If the server accepts the update, it MUST return a response with a 200 (OK) status code and the resulting account object. For example, to update the contact information in the above account, the client could send the following request: POST /acme/acct/evOfKhNU60wg HTTP/1.1 Host: example.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://example.com/acme/acct/evOfKhNU60wg", "nonce": "ax5RnthDqp_Yf4_HZnFLmA", "url": "https://example.com/acme/acct/evOfKhNU60wg" }), "payload": base64url({ "contact": [ "mailto:certificates@example.org", "mailto:admin@example.org" ] }), "signature": "hDXzvcj8T6fbFbmn...rDzXzzvzpRy64N0o" }
7.3.3. Changes of Terms of Service
As described above, a client can indicate its agreement with the CA's terms of service by setting the "termsOfServiceAgreed" field in its account object to "true". If the server has changed its terms of service since a client initially agreed, and the server is unwilling to process a request without explicit agreement to the new terms, then it MUST return an error response with status code 403 (Forbidden) and type "urn:ietf:params:acme:error:userActionRequired". This response MUST include a Link header field with link relation "terms-of-service" and the latest terms-of-service URL. The problem document returned with the error MUST also include an "instance" field, indicating a URL that the client should direct a human user to visit in order for instructions on how to agree to the terms. HTTP/1.1 403 Forbidden Replay-Nonce: T81bdZroZ2ITWSondpTmAw Link: <https://example.com/acme/directory>;rel="index" Link: <https://example.com/acme/terms/2017-6-02>;rel="terms-of-service" Content-Type: application/problem+json Content-Language: en { "type": "urn:ietf:params:acme:error:userActionRequired", "detail": "Terms of service have changed", "instance": "https://example.com/acme/agreement/?token=W8Ih3PswD-8" }7.3.4. External Account Binding
The server MAY require a value for the "externalAccountBinding" field to be present in "newAccount" requests. This can be used to associate an ACME account with an existing account in a non-ACME system, such as a CA customer database. To enable ACME account binding, the CA operating the ACME server needs to provide the ACME client with a MAC key and a key identifier, using some mechanism outside of ACME. The key identifier MUST be an ASCII string. The MAC key SHOULD be provided in base64url-encoded form, to maximize compatibility between non-ACME provisioning systems and ACME clients.
The ACME client then computes a binding JWS to indicate the external account holder's approval of the ACME account key. The payload of this JWS is the ACME account key being registered, in JWK form. The protected header of the JWS MUST meet the following criteria: o The "alg" field MUST indicate a MAC-based algorithm o The "kid" field MUST contain the key identifier provided by the CA o The "nonce" field MUST NOT be present o The "url" field MUST be set to the same value as the outer JWS The "signature" field of the JWS will contain the MAC value computed with the MAC key provided by the CA. POST /acme/new-account HTTP/1.1 Host: example.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "jwk": /* account key */, "nonce": "K60BWPrMQG9SDxBDS_xtSw", "url": "https://example.com/acme/new-account" }), "payload": base64url({ "contact": [ "mailto:cert-admin@example.org", "mailto:admin@example.org" ], "termsOfServiceAgreed": true, "externalAccountBinding": { "protected": base64url({ "alg": "HS256", "kid": /* key identifier from CA */, "url": "https://example.com/acme/new-account" }), "payload": base64url(/* same as in "jwk" above */), "signature": /* MAC using MAC key from CA */ } }), "signature": "5TWiqIYQfIDfALQv...x9C2mg8JGPxl5bI4" }
If such a CA requires that newAccount requests contain an "externalAccountBinding" field, then it MUST provide the value "true" in the "externalAccountRequired" subfield of the "meta" field in the directory object. If the CA receives a newAccount request without an "externalAccountBinding" field, then it SHOULD reply with an error of type "externalAccountRequired". When a CA receives a newAccount request containing an "externalAccountBinding" field, it decides whether or not to verify the binding. If the CA does not verify the binding, then it MUST NOT reflect the "externalAccountBinding" field in the resulting account object (if any). To verify the account binding, the CA MUST take the following steps: 1. Verify that the value of the field is a well-formed JWS 2. Verify that the JWS protected field meets the above criteria 3. Retrieve the MAC key corresponding to the key identifier in the "kid" field 4. Verify that the MAC on the JWS verifies using that MAC key 5. Verify that the payload of the JWS represents the same key as was used to verify the outer JWS (i.e., the "jwk" field of the outer JWS) If all of these checks pass and the CA creates a new account, then the CA may consider the new account associated with the external account corresponding to the MAC key. The account object the CA returns MUST include an "externalAccountBinding" field with the same value as the field in the request. If any of these checks fail, then the CA MUST reject the newAccount request.7.3.5. Account Key Rollover
A client may wish to change the public key that is associated with an account in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise. To change the key associated with an account, the client sends a request to the server containing signatures by both the old and new keys. The signature by the new key covers the account URL and the old key, signifying a request by the new key holder to take over the account from the old key holder. The signature by the old key covers this request and its signature, and indicates the old key holder's assent to the rollover request.
To create this request object, the client first constructs a keyChange object describing the account to be updated and its account key: account (required, string): The URL for the account being modified. The content of this field MUST be the exact string provided in the Location header field in response to the newAccount request that created the account. oldKey (required, JWK): The JWK representation of the old key. The client then encapsulates the keyChange object in an "inner" JWS, signed with the requested new account key. This "inner" JWS becomes the payload for the "outer" JWS that is the body of the ACME request. The outer JWS MUST meet the normal requirements for an ACME JWS request body (see Section 6.2). The inner JWS MUST meet the normal requirements, with the following differences: o The inner JWS MUST have a "jwk" header parameter, containing the public key of the new key pair. o The inner JWS MUST have the same "url" header parameter as the outer JWS. o The inner JWS MUST omit the "nonce" header parameter. This transaction has signatures from both the old and new keys so that the server can verify that the holders of the two keys both agree to the change. The signatures are nested to preserve the property that all signatures on POST messages are signed by exactly one key. The "inner" JWS effectively represents a request by the holder of the new key to take over the account form the holder of the old key. The "outer" JWS represents the current account holder's assent to this request.
POST /acme/key-change HTTP/1.1 Host: example.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://example.com/acme/acct/evOfKhNU60wg", "nonce": "S9XaOcxP5McpnTcWPIhYuB", "url": "https://example.com/acme/key-change" }), "payload": base64url({ "protected": base64url({ "alg": "ES256", "jwk": /* new key */, "url": "https://example.com/acme/key-change" }), "payload": base64url({ "account": "https://example.com/acme/acct/evOfKhNU60wg", "oldKey": /* old key */ }), "signature": "Xe8B94RD30Azj2ea...8BmZIRtcSKPSd8gU" }), "signature": "5TWiqIYQfIDfALQv...x9C2mg8JGPxl5bI4" } On receiving a keyChange request, the server MUST perform the following steps in addition to the typical JWS validation: 1. Validate the POST request belongs to a currently active account, as described in Section 6. 2. Check that the payload of the JWS is a well-formed JWS object (the "inner JWS"). 3. Check that the JWS protected header of the inner JWS has a "jwk" field. 4. Check that the inner JWS verifies using the key in its "jwk" field. 5. Check that the payload of the inner JWS is a well-formed keyChange object (as described above). 6. Check that the "url" parameters of the inner and outer JWSs are the same.
7. Check that the "account" field of the keyChange object contains the URL for the account matching the old key (i.e., the "kid" field in the outer JWS). 8. Check that the "oldKey" field of the keyChange object is the same as the account key for the account in question. 9. Check that no account exists whose account key is the same as the key in the "jwk" header parameter of the inner JWS. If all of these checks pass, then the server updates the corresponding account by replacing the old account key with the new public key and returns status code 200 (OK). Otherwise, the server responds with an error status code and a problem document describing the error. If there is an existing account with the new key provided, then the server SHOULD use status code 409 (Conflict) and provide the URL of that account in the Location header field. Note that changing the account key for an account SHOULD NOT have any other impact on the account. For example, the server MUST NOT invalidate pending orders or authorization transactions based on a change of account key.7.3.6. Account Deactivation
A client can deactivate an account by posting a signed update to the account URL with a status field of "deactivated". Clients may wish to do this when the account key is compromised or decommissioned. A deactivated account can no longer request certificate issuance or access resources related to the account, such as orders or authorizations. If a server receives a POST or POST-as-GET from a deactivated account, it MUST return an error response with status code 401 (Unauthorized) and type "urn:ietf:params:acme:error:unauthorized".
POST /acme/acct/evOfKhNU60wg HTTP/1.1 Host: example.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://example.com/acme/acct/evOfKhNU60wg", "nonce": "ntuJWWSic4WVNSqeUmshgg", "url": "https://example.com/acme/acct/evOfKhNU60wg" }), "payload": base64url({ "status": "deactivated" }), "signature": "earzVLd3m5M4xJzR...bVTqn7R08AKOVf3Y" } The server MUST verify that the request is signed by the account key. If the server accepts the deactivation request, it replies with a 200 (OK) status code and the current contents of the account object. Once an account is deactivated, the server MUST NOT accept further requests authorized by that account's key. The server SHOULD cancel any pending operations authorized by the account's key, such as certificate orders. A server may take a variety of actions in response to an account deactivation, e.g., deleting data related to that account or sending mail to the account's contacts. Servers SHOULD NOT revoke certificates issued by the deactivated account, since this could cause operational disruption for servers using these certificates. ACME does not provide a way to reactivate a deactivated account.7.4. Applying for Certificate Issuance
The client begins the certificate issuance process by sending a POST request to the server's newOrder resource. The body of the POST is a JWS object whose JSON payload is a subset of the order object defined in Section 7.1.3, containing the fields that describe the certificate to be issued: identifiers (required, array of object): An array of identifier objects that the client wishes to submit an order for. type (required, string): The type of identifier. value (required, string): The identifier itself.
notBefore (optional, string): The requested value of the notBefore field in the certificate, in the date format defined in [RFC3339]. notAfter (optional, string): The requested value of the notAfter field in the certificate, in the date format defined in [RFC3339]. POST /acme/new-order HTTP/1.1 Host: example.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://example.com/acme/acct/evOfKhNU60wg", "nonce": "5XJ1L3lEkMG7tR6pA00clA", "url": "https://example.com/acme/new-order" }), "payload": base64url({ "identifiers": [ { "type": "dns", "value": "www.example.org" }, { "type": "dns", "value": "example.org" } ], "notBefore": "2016-01-01T00:04:00+04:00", "notAfter": "2016-01-08T00:04:00+04:00" }), "signature": "H6ZXtGjTZyUnPeKn...wEA4TklBdh3e454g" } The server MUST return an error if it cannot fulfill the request as specified, and it MUST NOT issue a certificate with contents other than those requested. If the server requires the request to be modified in a certain way, it should indicate the required changes using an appropriate error type and description. If the server is willing to issue the requested certificate, it responds with a 201 (Created) response. The body of this response is an order object reflecting the client's request and any authorizations the client must complete before the certificate will be issued.
HTTP/1.1 201 Created Replay-Nonce: MYAuvOpaoIiywTezizk5vw Link: <https://example.com/acme/directory>;rel="index" Location: https://example.com/acme/order/TOlocE8rfgo { "status": "pending", "expires": "2016-01-05T14:09:07.99Z", "notBefore": "2016-01-01T00:00:00Z", "notAfter": "2016-01-08T00:00:00Z", "identifiers": [ { "type": "dns", "value": "www.example.org" }, { "type": "dns", "value": "example.org" } ], "authorizations": [ "https://example.com/acme/authz/PAniVnsZcis", "https://example.com/acme/authz/r4HqLzrSrpI" ], "finalize": "https://example.com/acme/order/TOlocE8rfgo/finalize" } The order object returned by the server represents a promise that if the client fulfills the server's requirements before the "expires" time, then the server will be willing to finalize the order upon request and issue the requested certificate. In the order object, any authorization referenced in the "authorizations" array whose status is "pending" represents an authorization transaction that the client must complete before the server will issue the certificate (see Section 7.5). If the client fails to complete the required actions before the "expires" time, then the server SHOULD change the status of the order to "invalid" and MAY delete the order resource. Clients MUST NOT make any assumptions about the sort order of "identifiers" or "authorizations" elements in the returned order object.
Once the client believes it has fulfilled the server's requirements, it should send a POST request to the order resource's finalize URL. The POST body MUST include a CSR: csr (required, string): A CSR encoding the parameters for the certificate being requested [RFC2986]. The CSR is sent in the base64url-encoded version of the DER format. (Note: Because this field uses base64url, and does not include headers, it is different from PEM.) POST /acme/order/TOlocE8rfgo/finalize HTTP/1.1 Host: example.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://example.com/acme/acct/evOfKhNU60wg", "nonce": "MSF2j2nawWHPxxkE3ZJtKQ", "url": "https://example.com/acme/order/TOlocE8rfgo/finalize" }), "payload": base64url({ "csr": "MIIBPTCBxAIBADBFMQ...FS6aKdZeGsysoCo4H9P", }), "signature": "uOrUfIIk5RyQ...nw62Ay1cl6AB" } The CSR encodes the client's requests with regard to the content of the certificate to be issued. The CSR MUST indicate the exact same set of requested identifiers as the initial newOrder request. Identifiers of type "dns" MUST appear either in the commonName portion of the requested subject name or in an extensionRequest attribute [RFC2985] requesting a subjectAltName extension, or both. (These identifiers may appear in any sort order.) Specifications that define new identifier types must specify where in the certificate signing request these identifiers can appear. A request to finalize an order will result in an error if the CA is unwilling to issue a certificate corresponding to the submitted CSR. For example: o If the CSR and order identifiers differ o If the account is not authorized for the identifiers indicated in the CSR o If the CSR requests extensions that the CA is not willing to include
In such cases, the problem document returned by the server SHOULD use error code "badCSR" and describe specific reasons the CSR was rejected in its "detail" field. After returning such an error, the server SHOULD leave the order in the "ready" state, to allow the client to submit a new finalize request with an amended CSR. A request to finalize an order will result in error if the order is not in the "ready" state. In such cases, the server MUST return a 403 (Forbidden) error with a problem document of type "orderNotReady". The client should then send a POST-as-GET request to the order resource to obtain its current state. The status of the order will indicate what action the client should take (see below). If a request to finalize an order is successful, the server will return a 200 (OK) with an updated order object. The status of the order will indicate what action the client should take: o "invalid": The certificate will not be issued. Consider this order process abandoned. o "pending": The server does not believe that the client has fulfilled the requirements. Check the "authorizations" array for entries that are still pending. o "ready": The server agrees that the requirements have been fulfilled, and is awaiting finalization. Submit a finalization request. o "processing": The certificate is being issued. Send a POST-as-GET request after the time given in the Retry-After header field of the response, if any. o "valid": The server has issued the certificate and provisioned its URL to the "certificate" field of the order. Download the certificate.
HTTP/1.1 200 OK Replay-Nonce: CGf81JWBsq8QyIgPCi9Q9X Link: <https://example.com/acme/directory>;rel="index" Location: https://example.com/acme/order/TOlocE8rfgo { "status": "valid", "expires": "2016-01-20T14:09:07.99Z", "notBefore": "2016-01-01T00:00:00Z", "notAfter": "2016-01-08T00:00:00Z", "identifiers": [ { "type": "dns", "value": "www.example.org" }, { "type": "dns", "value": "example.org" } ], "authorizations": [ "https://example.com/acme/authz/PAniVnsZcis", "https://example.com/acme/authz/r4HqLzrSrpI" ], "finalize": "https://example.com/acme/order/TOlocE8rfgo/finalize", "certificate": "https://example.com/acme/cert/mAt3xBGaobw" }7.4.1. Pre-authorization
The order process described above presumes that authorization objects are created reactively, in response to a certificate order. Some servers may also wish to enable clients to obtain authorization for an identifier proactively, outside of the context of a specific issuance. For example, a client hosting virtual servers for a collection of names might wish to obtain authorization before any virtual servers are created and only create a certificate when a virtual server starts up. In some cases, a CA running an ACME server might have a completely external, non-ACME process for authorizing a client to issue certificates for an identifier. In these cases, the CA should provision its ACME server with authorization objects corresponding to these authorizations and reflect them as already valid in any orders submitted by the client. If a CA wishes to allow pre-authorization within ACME, it can offer a "new authorization" resource in its directory by adding the field "newAuthz" with a URL for the newAuthz resource.
To request authorization for an identifier, the client sends a POST request to the newAuthz resource specifying the identifier for which authorization is being requested. identifier (required, object): The identifier to appear in the resulting authorization object (see Section 7.1.4). type (required, string): The type of identifier. value (required, string): The identifier itself. POST /acme/new-authz HTTP/1.1 Host: example.com Content-Type: application/jose+json { "protected": base64url({ "alg": "ES256", "kid": "https://example.com/acme/acct/evOfKhNU60wg", "nonce": "uQpSjlRb4vQVCjVYAyyUWg", "url": "https://example.com/acme/new-authz" }), "payload": base64url({ "identifier": { "type": "dns", "value": "example.org" } }), "signature": "nuSDISbWG8mMgE7H...QyVUL68yzf3Zawps" } Note that because the identifier in a pre-authorization request is the exact identifier to be included in the authorization object, pre- authorization cannot be used to authorize issuance of certificates containing wildcard domain names. Before processing the authorization request, the server SHOULD determine whether it is willing to issue certificates for the identifier. For example, the server should check that the identifier is of a supported type. Servers might also check names against a blacklist of known high-value identifiers. If the server is unwilling to issue for the identifier, it SHOULD return an error with status code 403 (Forbidden), with a problem document describing the reason for the rejection.
If the server is willing to proceed, it builds a pending authorization object from the inputs submitted by the client: o "identifier" the identifier submitted by the client o "status" MUST be "pending" unless the server has out-of-band information about the client's authorization status o "challenges" as selected by the server's policy for this identifier The server allocates a new URL for this authorization and returns a 201 (Created) response with the authorization URL in the Location header field and the JSON authorization object in the body. The client then follows the process described in Section 7.5 to complete the authorization process.7.4.2. Downloading the Certificate
To download the issued certificate, the client simply sends a POST- as-GET request to the certificate URL. The default format of the certificate is application/pem-certificate- chain (see Section 9). The server MAY provide one or more link relation header fields [RFC8288] with relation "alternate". Each such field SHOULD express an alternative certificate chain starting with the same end-entity certificate. This can be used to express paths to various trust anchors. Clients can fetch these alternates and use their own heuristics to decide which is optimal.
POST /acme/cert/mAt3xBGaobw HTTP/1.1 Host: example.com Content-Type: application/jose+json Accept: application/pem-certificate-chain { "protected": base64url({ "alg": "ES256", "kid": "https://example.com/acme/acct/evOfKhNU60wg", "nonce": "uQpSjlRb4vQVCjVYAyyUWg", "url": "https://example.com/acme/cert/mAt3xBGaobw" }), "payload": "", "signature": "nuSDISbWG8mMgE7H...QyVUL68yzf3Zawps" } HTTP/1.1 200 OK Content-Type: application/pem-certificate-chain Link: <https://example.com/acme/directory>;rel="index" -----BEGIN CERTIFICATE----- [End-entity certificate contents] -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- [Issuer certificate contents] -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- [Other certificate contents] -----END CERTIFICATE----- A certificate resource represents a single, immutable certificate. If the client wishes to obtain a renewed certificate, the client initiates a new order process to request one. Because certificate resources are immutable once issuance is complete, the server MAY enable the caching of the resource by adding Expires and Cache-Control header fields specifying a point in time in the distant future. These header fields have no relation to the certificate's period of validity. The ACME client MAY request other formats by including an Accept header field [RFC7231] in its request. For example, the client could use the media type "application/pkix-cert" [RFC2585] or "application/ pkcs7-mime" [RFC5751] to request the end-entity certificate in DER format. Server support for alternate formats is OPTIONAL. For formats that can only express a single certificate, the server SHOULD
provide one or more "Link: rel="up"" header fields pointing to an issuer or issuers so that ACME clients can build a certificate chain as defined in TLS (see Section 4.4.2 of [RFC8446]).