Add full documentation

pull/17/merge
Richard Körber 2015-12-19 14:06:09 +01:00
parent afaf286a49
commit 9bcd5a2dd4
34 changed files with 505 additions and 67 deletions

View File

@ -1,15 +1,14 @@
# ACME Java Client ![build status](http://jenkins.shredzone.net/buildStatus/icon?job=acme4j)
This is a Java client for the [ACME](https://tools.ietf.org/html/draft-ietf-acme-acme-01) protocol.
This is a Java client for the [Automatic Certificate Management Environment (ACME)](https://tools.ietf.org/html/draft-ietf-acme-acme-01) protocol.
ACME is a protocol that a certificate authority (CA) and an applicant can use to automate the process of verification and certificate issuance.
This Java client helps connecting to an ACME server, and performing all necessary steps to manage certificates.
It is an independent open source implementation that is not affiliated with or endorsed by _Let's Encrypt_. The source code can be found at [GitHub](https://github.com/shred/acme4j) and is distributed under the terms of [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
It is an independent open source implementation that is not affiliated with or endorsed by _Let's Encrypt_.
Alpha Release!
--------------
## Alpha Release!
Please note that even though _acme4j_ is already usable, it is currently in an early alpha state. This means that:
@ -17,33 +16,29 @@ Please note that even though _acme4j_ is already usable, it is currently in an e
* The API is not stable. It may change in a manner not compatible to previous versions and without prior notice.
* _acme4j_ is not thoroughly tested yet, and may still have major bugs.
Features
--------
## Features
* Easy to use Java API
* Requires JRE 7 or higher
* Built with maven (package will be made available at Maven Central as soon as beta state is reached)
* Small, only requires [jose4j](https://bitbucket.org/b_c/jose4j/wiki/Home) and [slf4j](http://www.slf4j.org/) as dependencies. [Bouncy Castle](https://www.bouncycastle.org/java.html) is recommended, but not required.
* Small, only requires [jose4j](https://bitbucket.org/b_c/jose4j/wiki/Home) and [slf4j](http://www.slf4j.org/) as dependencies
* Extensive unit tests
How to Use
----------
## Usage
_acme4j_ consists of a few modules:
See the [online documentation](http://www.shredzone.org/maven/acme4j/) for how to use _acme4j_. Or just have a look at [the source code of an example](https://github.com/shred/acme4j/blob/master/acme4j-example/src/main/java/org/shredzone/acme4j/ClientTest.java).
* _acme4j-client_: This is the main module. It contains the ACME client and everything needed for communication with an ACME server.
* _acme4j-utils_: Some utility classes that may be helpful for creating key pairs, certificates, and certificate signing requests. Requires [Bouncy Castle](https://www.bouncycastle.org/java.html).
* _acme4j-example_: An example tool that performs all steps for registering a new account at _Let's Encrypt_ and getting a certificate for a set of domain names. This is a good starting point to find out how _acme4j_ is used.
Missing
-------
## Missing
The following features are planned to be completed for the first beta release, but are still missing:
* Support of account recovery and certificate revocation.
* `proofOfPossession-01` and `tls-sni-01` challenge support.
* Extensive unit tests.
* Better error handling.
* Some hardening (like plausibility checks).
* Full documentation.
_acme4j_ is open source software. Feel free to send in pull requests!
## License
_acme4j_ is open source software. The source code can be found at [GitHub](https://github.com/shred/acme4j) and is distributed under the terms of [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Feel free to send in pull requests!

View File

@ -25,7 +25,7 @@
<artifactId>acme4j-client</artifactId>
<name>acme4j client</name>
<name>acme4j Client</name>
<description>ACME client for Java</description>
<dependencies>

View File

@ -1 +0,0 @@
This is the client part of the Java ACME client.

View File

@ -0,0 +1,17 @@
acme4j Client
=============
This is the main part of _acme4j_.
How to Use
----------
_acme4j_ is availabe at Maven Central. Just add this snippet to your `pom.xml`:
```xml
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</dependency>
```

View File

@ -1,6 +0,0 @@
a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover {
background: none;
padding-right: 0;
}

View File

@ -20,8 +20,8 @@
<version position="right"/>
<body>
<links>
<item name="Home" href="index.html"/>
<item name="Project Management" href="http://acme4j.shredzone.org"/>
<item name="API javadoc" href="./apidocs/index.html"/>
<item name="GitHub" href="https://github.com/shred/acme4j"/>
</links>
<breadcrumbs>
<item name="shredzone.org" href="http://www.shredzone.org"/>
@ -29,10 +29,15 @@
<item name="acme4j-client" href="index.html"/>
</breadcrumbs>
<menu name="Main">
<item name="Introduction" href="index.html"/>
<item name="Project Management" href="http://acme4j.shredzone.org"/>
<item name="Description" href="index.html"/>
</menu>
<menu ref="modules"/>
<menu ref="reports"/>
</body>
<skin>
<groupId>org.apache.maven.skins</groupId>
<artifactId>maven-fluido-skin</artifactId>
<version>1.4</version>
</skin>
</project>

View File

@ -25,7 +25,7 @@
<artifactId>acme4j-example</artifactId>
<name>acme4j example</name>
<name>acme4j Example</name>
<description>Example for using acme4j</description>
<build>

View File

@ -1 +0,0 @@
An example about how to use the Java ACME client.

View File

@ -0,0 +1,19 @@
acme4j Example
==============
An example tool that uses _acme4j_, and a good starting point to find out how _acme4j_ is used.
This tool registers a new account with the _Let's Encrypt_ staging server, and fetches a certificate for a set of domains.
How to Use
----------
Run the `org.shredzone.acme4j.ClientTest` class with the domains to be registered as parameters.
You can also invoke the example tool via maven:
```
mvn exec:java -Dexec.args="example.com example.org"
```
Or just have a look at [the source code](https://github.com/shred/acme4j/blob/master/acme4j-example/src/main/java/org/shredzone/acme4j/ClientTest.java).

View File

@ -1,6 +0,0 @@
a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover {
background: none;
padding-right: 0;
}

View File

@ -20,8 +20,7 @@
<version position="right"/>
<body>
<links>
<item name="Home" href="index.html"/>
<item name="Project Management" href="http://acme4j.shredzone.org"/>
<item name="GitHub" href="https://github.com/shred/acme4j"/>
</links>
<breadcrumbs>
<item name="shredzone.org" href="http://www.shredzone.org"/>
@ -29,10 +28,15 @@
<item name="acme4j-example" href="index.html"/>
</breadcrumbs>
<menu name="Main">
<item name="Introduction" href="index.html"/>
<item name="Project Management" href="http://acme4j.shredzone.org"/>
<item name="Description" href="index.html"/>
</menu>
<menu ref="modules"/>
<menu ref="reports"/>
</body>
<skin>
<groupId>org.apache.maven.skins</groupId>
<artifactId>maven-fluido-skin</artifactId>
<version>1.4</version>
</skin>
</project>

View File

@ -25,7 +25,7 @@
<artifactId>acme4j-utils</artifactId>
<name>acme4j utils</name>
<name>acme4j Utils</name>
<description>acme4j utilities</description>
<dependencies>

View File

@ -1 +0,0 @@
Some utility classes for using the Java ACME client.

View File

@ -0,0 +1,19 @@
acme4j Utils
============
Some utility classes to be used with _acme4j_. They will help generating and processing keys and signatures.
Note that (unlike `acme4j-client`) this module requires [Bouncy Castle](https://www.bouncycastle.org/java.html).
How to Use
----------
Just add this snippet to your `pom.xml`:
```xml
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</dependency>
```

View File

@ -1,6 +0,0 @@
a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover {
background: none;
padding-right: 0;
}

View File

@ -20,8 +20,8 @@
<version position="right"/>
<body>
<links>
<item name="Home" href="index.html"/>
<item name="Project Management" href="http://acme4j.shredzone.org"/>
<item name="API javadoc" href="./apidocs/index.html"/>
<item name="GitHub" href="https://github.com/shred/acme4j"/>
</links>
<breadcrumbs>
<item name="shredzone.org" href="http://www.shredzone.org"/>
@ -29,10 +29,15 @@
<item name="acme4j-utils" href="index.html"/>
</breadcrumbs>
<menu name="Main">
<item name="Introduction" href="index.html"/>
<item name="Project Management" href="http://acme4j.shredzone.org"/>
<item name="Description" href="index.html"/>
</menu>
<menu ref="modules"/>
<menu ref="reports"/>
</body>
<skin>
<groupId>org.apache.maven.skins</groupId>
<artifactId>maven-fluido-skin</artifactId>
<version>1.4</version>
</skin>
</project>

View File

@ -97,10 +97,17 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.3</version>
<version>3.4</version>
<configuration>
<outputEncoding>UTF-8</outputEncoding>
</configuration>
<dependencies>
<dependency>
<groupId>org.apache.maven.doxia</groupId>
<artifactId>doxia-module-markdown</artifactId>
<version>1.6</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -1 +0,0 @@
This is a Java ACME client.

View File

@ -0,0 +1,25 @@
# Certificate Authorities
_acme4j_ should support any CA providing an ACME server.
It is always possible to connect to an ACME server by passing in the CA's resource directory URI:
```java
AcmeClient client =
AcmeClientFactory.connect("https://acme-staging.api.letsencrypt.org/directory");
```
For some CAs there are also more specific ACME providers available via `acme` schemed URIs:
```java
AcmeClient client =
AcmeClientFactory.connect("acme://letsencrypt.org/staging");
```
Connecting via `acme` URI should always be preferred over using the directory URL.
## Available Providers
In _acme4j_ these providers are available:
* [Let's Encrypt](./letsencrypt.html)

View File

@ -0,0 +1,21 @@
# Let's Encrypt
Web site: [Let's Encrypt](https://letsencrypt.org)
## Connection URIs
* `acme://letsencrypt.org` - Production server
* `acme://letsencrypt.org/staging` - Testing server
* `acme://letsencrypt.org/v01` - Production server, pinned to API v01
## Features
* Connection to the ACME server is pinned to the Let's Encrypt certificate
## Intermediate Certificates
The _Let's Encrypt_ intermediate certificates are available [here](https://letsencrypt.org/certificates/).
## Renewal
Just download the renewed certificate from the certificate URL that was provided by `requestCertificate()`.

View File

@ -0,0 +1,14 @@
# DNS Challenge
After authorizing the challenge, `DnsChallenge` provides a digest string:
```java
DnsChallenge challenge = auth.findChallenge(DnsChallenge.TYPE);
challenge.authorize(account);
String digest = challenge.getDigest();
```
The CA expects a TXT record at `_acme-challenge.${domain}` with the `digest` string as value.
The challenge is completed when the CA was able to fetch the TXT record and got the correct `digest` returned.

View File

@ -0,0 +1,21 @@
# HTTP Challenge
After authorizing the challenge, `HttpChallenge` provides two strings:
```java
HttpChallenge challenge = auth.findChallenge(HttpChallenge.TYPE);
challenge.authorize(account);
String token = challenge.getToken();
String content = challenge.getAuthorization();
```
`token` is the name of the file that will be requested by the CA server. It must contain the `content` string, without any leading or trailing white spaces or line breaks. The `Content-Type` header must be either `text/plain` or absent.
The expected path is (assuming that `${domain}` is your domain and `${token}` is the token):
```
http://${domain}/.well-known/acme-challenge/${token}
```
The challenge is completed when the CA was able to download that file and found `content` in it.

View File

@ -0,0 +1,14 @@
# Challenges
Challenges are used to prove ownership of a domain.
There are different kind of challenges. The most simple is maybe the HTTP challenge, where a file must be made available at the domain that is to be validated. It is assumed that you control the domain if you are able to publish a given file under a given path.
The CA offers one or more sets of challenges. At least one set has to be completed in order to prove ownership.
The ACME specifications define four standard challenges:
* [HTTP](./http.html)
* [DNS](./dns.html)
* [TLS-SNI](./tls-sni.html)
* [Proof of Possession](./proof-of-possession.html)

View File

@ -0,0 +1,3 @@
# Proof of Possession
This challenge is not yet implemented in _acme4j_.

View File

@ -0,0 +1,3 @@
# TLS-SNI
This challenge is not yet implemented in _acme4j_.

View File

@ -0,0 +1,37 @@
acme4j
======
A Java client for the [Automatic Certificate Management Environment (ACME)](https://tools.ietf.org/html/draft-ietf-acme-acme-01) protocol.
ACME is a protocol that a certificate authority (CA) and an applicant can use to automate the process of verification and certificate issuance.
This Java client helps connecting to an ACME server, and performing all necessary steps to manage certificates.
It is an independent open source implementation that is not affiliated with or endorsed by _Let's Encrypt_.
The source code can be found at [GitHub](https://github.com/shred/acme4j) and is distributed under the terms of [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Quick Start
-----------
_acme4j_ is available at Maven Central. Just add this snippet to your `pom.xml`:
```xml
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}-client</artifactId>
<version>${project.version}</version>
</dependency>
```
There is also an optional utility module that will help you handling key pairs and certificates (but requires [Bouncy Castle](https://www.bouncycastle.org/java.html)):
```xml
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}-utils</artifactId>
<version>${project.version}</version>
</dependency>
```
Now just have a look at [this source code](https://github.com/shred/acme4j/blob/master/acme4j-example/src/main/java/org/shredzone/acme4j/ClientTest.java) to see an example usage.

View File

@ -0,0 +1,54 @@
# ACME Client Provider
Basically, it is possible to connect to any kind of ACME server just by connecting to the URI of its directory resource:
```java
AcmeClient client =
AcmeClientFactory.connect("https://acme-v01.api.letsencrypt.org/directory");
```
ACME client providers are "plug-ins" to _acme4j_ that are specialized on a single CA. For example, the _Let's Encrypt_ client provider offers connection URIs that are much easier to remember. Opening a connection like in the example above looks like this:
```java
AcmeClient client = AcmeClientFactory.connect("acme://letsencrypt.org");
```
## Writing an own Client Provider
Every CA that provides an ACME server should also have an own Client Provider, and if it is just for the sake of a pretty `acme:` URI.
However, it is also possible to adapt the behavior of wide parts of _acme4j_ to special characteristics of the CA, just by overriding methods and extending classes.
A client provider implements the [`AcmeClientProvider`](./apidocs/org/shredzone/acme4j/provider/AcmeClientProvider.html) interface, but usually it is easier to extend [`AbstractAcmeClientProvider`](./apidocs/org/shredzone/acme4j/provider/AbstractAcmeClientProvider.html) and implement only these two methods:
* `accepts(URI)` checks if the client provider is accepting the provided URI. Usually it would be an URI like `acme://example.com`. Note that the `http` and `https` schemes are reserved for the generic provider and cannot be used by client providers.
* `resolve(URI)` parses that URI and returns the corresponding URI of the directory service.
The `AcmeClientProvider` implementation needs to be registered with Java's `ServiceLoader`. In the `META-INF/services` path of your project, create a file `org.shredzone.acme4j.provider.AcmeClientProvider` and write the fully qualified class name of your implementation into that file.
When _acme4j_ tries to connect to an acme URI, it first invokes the `accepts(URI)` method of all registered `AcmeClientProvider`s. Only one of the providers must return `true` for a successful connection. _acme4j_ then invokes the `resolve(URI)` method of that provider, and connects to the directory URI that is returned.
The connection fails if none or more than one `AcmeClientProvider` implementations `accept` the acme URI.
## Certificate Pinning
Client providers may verify the HTTPS certificate provided by the ACME server.
To do so, override the `createHttpConnector()` method of `AbstractAcmeClientProvider` and return a subclassed `HttpConnector` class that modifies the `HttpURLConnection` as required.
The source code of the [_Let's Encrypt_ provider](./apidocs/org/shredzone/acme4j/provider/letsencrypt/package-summary.html) gives an example of how to do that.
## Individual Challenges
If your ACME server provides challenges that are not specified in the ACME protocol, there should be an own `Challenge` implementation for each of your challenge, by either implementing the [`Challenge`](./apidocs/org/shredzone/acme4j/challenge/Challenge.html)
interface or (more conveniently) extending the [`GenericChallenge`](./apidocs/org/shredzone/acme4j/challenge/GenericChallenge.html) class.
In your `AcmeClientProvider` implementation, override the `createChallenge(String)` method so it returns a new instance of your `Challenge` implementation when your individual challenge type is requested. All other types should be delegated to the super method.
## No directory service
An ACME server may not provide a directory service, for example when fixed URIs are to be used.
In this case, extend `GenericAcmeClient` and override the `resourceUri(Resource)` method. It should return the URI of the given resource.
Your `AcmeClientProvider`'s `connect(URI)` method would then return a new instance of your `GenericAcmeClient` class. Just use `null` as your directory URI.

View File

@ -0,0 +1,64 @@
# Authorize your Domains
Once you have your account set up, you need to associate your domain with it. This is done by using an `Authorization` data transfer object:
```java
Authorization auth = new Authorization();
auth.setDomain("example.org");
client.newAuthorization(account, auth);
```
When `newAuthorization()` returns successfully, the `Authorization` instance contains further details about how you can prove ownership of your domain. An ACME server offers combinations of different authorization methods, called `Challenge`s.
`Authorization` methods help you find the `Challenge` that fits best to your possibilities. Just pass all the challenge types that your software is able to accept to `findCombination()`, and it returns the shortest possible combination of `Challenge`s you have to perform.
In the following example, your software would be able to either perform a HTTP or DNS challenge, or both:
```java
Collection<Challenge> combination = auth.findCombination(
HttpChallenge.TYPE, DnsChallenge.TYPE);
```
The returned `combination` contains a single combination of challenges you would have to perform. If the combination consists of more than one challenge, you would have to perform _all of them_ in order to successfully authorize your domain. If `null` is returned, it means that none of your offered challenge types are acceptable to the CA.
If your software only implements a single challenge type, `findChallenge()` may be a little easier to use:
```java
HttpChallenge challenge = auth.findChallenge(HttpChallenge.TYPE);
```
It returns a properly casted `Challenge` object, or `null` if your challenge type was not acceptable.
After you have found a challenge, you need to sign it first:
```java
challenge.authorize(account);
```
After signing the challenge, it provides the necessary data for a successful response to the challenge. The kind of response depends on the challenge type (see the [documentation of challenges](../challenge/index.html)). Some types may also require more data for authorizing the challenge.
After you have performed the necessary steps to set up the response to the challenge, the ACME server is told to test your response:
```java
client.triggerChallenge(account, challenge);
```
Again, the call completes the `Challenge` transfer object with server side data like the current challenge status and a challenge URI.
Now you have to wait for the server to test your response and set the challenge status to `VALID`. The easiest way is to poll the status:
```java
while (challenge.getStatus() != Challenge.Status.VALID) {
Thread.sleep(3000L);
client.updateChallenge(account, challenge);
}
```
This is a very simple example. You should limit the number of loop iterations, and abort the loop when the status should turn to `INVALID`. If you know when the CA server actually requested your response (e.g. when you notice a HTTP request on the response file), you should start polling after that event.
As soon as the challenge is `VALID`, you have successfully associated the domain with your account.
If your final certificate contains further domains or subdomains, repeat the authorization run with each of them.
Note that wildcard certificates are not currently supported.

View File

@ -0,0 +1,38 @@
# Request a Certificate
Once you completed all the previous steps, it's time to request the signed certificate.
To do so, prepare a PKCS#10 CSR file. A single domain may be set as _Common Name_. Multiple domains must be provided as _Subject Alternative Name_. Other properties (_Organization_, _Organization Unit_ etc.) depend on the CA. Some may require these properties to be set, while others may ignore them when generating the certificate.
CSR files can be generated with command line tools like `openssl`. Unfortunately the standard Java does not offer classes for that, so you'd have to resort to [Bouncy Castle](http://www.bouncycastle.org/java.html) if you want to create a CSR programmatically. In the `acme4j-utils` module, there is also a [`CSRBuilder`](../apidocs/org/shredzone/acme4j/util/CSRBuilder.html) for your convenience:
```java
KeyPair domainKeyPair = ... // KeyPair to be used for HTTPS encryption
CSRBuilder csrb = new CSRBuilder();
csrb.addDomain("example.org");
csrb.addDomain("www.example.org");
csrb.setOrganization("The Example Organization")
csrb.sign(domainKeyPair);
byte[] csr = csrb.getEncoded();
```
Now all you need to do is to pass in a binary representation of the CSR and request the certificate:
```java
byte[] csr = ... // your CSR
URI certUri = client.requestCertificate(account, csr);
```
`certUri` contains an URI where the signed certificate can be downloaded from. You can either download it from there yourself (e.g. with `curl`), or just use the `AcmeClient`:
```java
X509Certificate cert = client.downloadCertificate(certUri);
```
Congratulations! You have just created your first certificate via _acme4j_.
## Renewal
Renewing your certificate depends on the CA. Some may require you to go through the authorization process again, while others may just provide an updated certificate for download at the `certUri` above.

View File

@ -0,0 +1,20 @@
# Connect to an ACME server
[`AcmeClientFactory.connect()`](../apidocs/org/shredzone/acme4j/AcmeClientFactory.html) creates an [`AcmeClient`](../apidocs/org/shredzone/acme4j/AcmeClient.html) and connects it to an ACME server.
The `connect()` method expects the URI of the ACME server's directory service, as it is documented by the CA. For example, this is how to connect to the _Let's Encrypt_ staging server:
```java
AcmeClient client =
AcmeClientFactory.connect("https://acme-staging.api.letsencrypt.org/directory");
```
However, such an URI is hard to remember and might even change in the future. Java also does not accept the certificate used by the _Let's Encrypt_ server, so calls to the `AcmeClient` are likely to throw a certificate exception.
For this reason, special ACME URIs should be preferred:
```java
AcmeClient client = AcmeClientFactory.connect("acme://letsencrypt.org/staging");
```
Instead of a generic provider, this call uses a special _Let's Encrypt_ provider that also accepts the _Let's Encrypt_ certificate.

View File

@ -0,0 +1,21 @@
# How to Use _acme4j_
_acme4j_ is a client library that helps connecting to ACME servers without worrying about specification details.
Central part of the communication is an [`Account`](../apidocs/org/shredzone/acme4j/Account.html) object, which contains a key pair. The ACME server identifies your account by the public key, and verifies that your requests are signed with your private key. For this reason, you should keep the key pair in a safe place. If you should lose it, you would need to recover access to your account.
The first step is to create a Java `KeyPair`, save it somewhere, and then pass it to the constructor of `Account`:
```java
KeyPair keypair = ... // your key pair
Account account = new Account(keypair);
```
You need this `Account` instance as identifier for almost all API calls.
To get a certificate, these steps need to be performed:
* [Connect to an ACME server](./connect.html)
* [Register and Create an Account](./register.html)
* [Authorize your Domains](./authorization.html)
* [Request and Download a Certificate](./certificate.html)

View File

@ -0,0 +1,39 @@
# Register an Account
The first thing to do is to register your `Account` with the CA.
You need a `Registration` instance that serves as a data transfer object, and fill the object with details of your account. The `AcmeClient.newRegistration()` call then completes the data transfer object with server side account data.
This code fragment registers your account with the CA. Optionally you can add contact URIs (like email addresses or phone numbers) to the registration, which will help the CA getting in contact with you.
```java
Registration reg = new Registration();
reg.getContacts().add("mailto:acme@example.com"); // optional
client.newRegistration(account, reg);
URI accountLocationUri = reg.getLocation(); // your account's server URI
```
After invocating `newRegistration()`, the `location` property contains the URI of your newly created account on server side.
`newRegistration()` may fail and throw an `AcmeException` for various reasons. When your public key was already registered with the CA, an `AcmeConflictException` is thrown, but the `location` property will still hold your account URI after the call. This may be helpful if you forgot your account URI and need to recover it.
## Update an Account
At some point, you may want to update your account. For example your contact address might have changed, or you were asked by the CA to accept the current terms and conditions.
To do so, create a `Registration` object again, and set the `location` property to the URI that you previously got via `newRegistration()`. Also set whatever you like to change to your account.
The following example accepts the terms and conditions by explicitly setting the URL to the agreement document.
```java
URI accountLocationUri = ... // your account's URI
URI agreementUri = ... // TAC link provided by the CA
Registration reg = new Registration();
reg.setLocation(accountLocationUri);
reg.setAgreement(agreementUri);
client.updateRegistration(account, reg);
```

View File

@ -1,6 +0,0 @@
a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover {
background: none;
padding-right: 0;
}

View File

@ -20,18 +20,39 @@
<version position="right"/>
<body>
<links>
<item name="Home" href="index.html"/>
<item name="Project Management" href="http://acme4j.shredzone.org"/>
<item name="API javadoc" href="./apidocs/index.html"/>
<item name="GitHub" href="https://github.com/shred/acme4j"/>
</links>
<breadcrumbs>
<item name="shredzone.org" href="http://www.shredzone.org"/>
<item name="acme4j" href="index.html"/>
</breadcrumbs>
<menu name="Main">
<menu name="Documentation">
<item name="Introduction" href="index.html"/>
<item name="Project Management" href="http://acme4j.shredzone.org"/>
<item name="How to Use" href="usage/index.html">
<item name="Connection" href="usage/connect.html"/>
<item name="Account" href="usage/register.html"/>
<item name="Authorization" href="usage/authorization.html"/>
<item name="Certificate" href="usage/certificate.html"/>
</item>
<item name="Challenges" href="challenge/index.html">
<item name="HTTP" href="challenge/http.html"/>
<item name="DNS" href="challenge/dns.html"/>
<item name="tls-sni" href="challenge/tls-sni.html"/>
<item name="Proof of Possession" href="challenge/proof-of-possession.html"/>
</item>
<item name="CAs" href="ca/index.html">
<item name="Let's Encrypt" href="ca/letsencrypt.html"/>
</item>
<item name="ACME Client Provider" href="provider.html"/>
</menu>
<menu ref="modules"/>
<menu ref="reports"/>
</body>
<skin>
<groupId>org.apache.maven.skins</groupId>
<artifactId>maven-fluido-skin</artifactId>
<version>1.4</version>
</skin>
</project>