mirror of https://github.com/shred/acme4j
				
				
				
			Remove account recovery. Closes issue #1.
							parent
							
								
									19787f4c00
								
							
						
					
					
						commit
						92b3076031
					
				| 
						 | 
				
			
			@ -61,16 +61,6 @@ public interface AcmeClient {
 | 
			
		|||
    void changeRegistrationKey(Registration registration, KeyPair newKeyPair)
 | 
			
		||||
                throws AcmeException;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Recovers an account by contact-based recovery. The server starts an out-of-band
 | 
			
		||||
     * recovery process by using one of the contact addresses given at account creation.
 | 
			
		||||
     *
 | 
			
		||||
     * @param registration
 | 
			
		||||
     *            {@link Registration}, with the new key pair and the account location URI
 | 
			
		||||
     *            set
 | 
			
		||||
     */
 | 
			
		||||
    void recoverRegistration(Registration registration) throws AcmeException;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Deletes an account. Related certificates may still be valid after account deletion,
 | 
			
		||||
     * and need to be revoked separately if neccessary.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,8 +23,7 @@ public enum Resource {
 | 
			
		|||
    NEW_REG("new-reg"),
 | 
			
		||||
    NEW_AUTHZ("new-authz"),
 | 
			
		||||
    NEW_CERT("new-cert"),
 | 
			
		||||
    REVOKE_CERT("revoke-cert"),
 | 
			
		||||
    RECOVER_REG("recover-reg");
 | 
			
		||||
    REVOKE_CERT("revoke-cert");
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Parses the string and returns a matching {@link Resource} instance.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -223,41 +223,6 @@ public abstract class AbstractAcmeClient implements AcmeClient {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void recoverRegistration(Registration registration) throws AcmeException {
 | 
			
		||||
        if (registration == null) {
 | 
			
		||||
            throw new NullPointerException("registration must not be null");
 | 
			
		||||
        }
 | 
			
		||||
        if (registration.getLocation() == null) {
 | 
			
		||||
            throw new IllegalArgumentException("registration location must not be null");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        LOG.debug("recoverRegistration");
 | 
			
		||||
        try (Connection conn = createConnection()) {
 | 
			
		||||
            ClaimBuilder claims = new ClaimBuilder();
 | 
			
		||||
            claims.putResource(Resource.RECOVER_REG);
 | 
			
		||||
            claims.put("method", "contact");
 | 
			
		||||
            claims.put("base", registration.getLocation());
 | 
			
		||||
            if (!registration.getContacts().isEmpty()) {
 | 
			
		||||
                claims.put("contact", registration.getContacts());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int rc = conn.sendSignedRequest(resourceUri(Resource.RECOVER_REG), claims, session, registration);
 | 
			
		||||
            if (rc != HttpURLConnection.HTTP_CREATED) {
 | 
			
		||||
                conn.throwAcmeException();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            registration.setLocation(conn.getLocation());
 | 
			
		||||
 | 
			
		||||
            URI tos = conn.getLink("terms-of-service");
 | 
			
		||||
            if (tos != null) {
 | 
			
		||||
                registration.setAgreement(tos);
 | 
			
		||||
            }
 | 
			
		||||
        } catch (IOException ex) {
 | 
			
		||||
            throw new AcmeNetworkException(ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteRegistration(Registration registration) throws AcmeException {
 | 
			
		||||
        if (registration == null) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,10 +34,9 @@ public class ResourceTest {
 | 
			
		|||
        assertThat(Resource.NEW_CERT.path(), is("new-cert"));
 | 
			
		||||
        assertThat(Resource.NEW_REG.path(), is("new-reg"));
 | 
			
		||||
        assertThat(Resource.REVOKE_CERT.path(), is("revoke-cert"));
 | 
			
		||||
        assertThat(Resource.RECOVER_REG.path(), is("recover-reg"));
 | 
			
		||||
 | 
			
		||||
        // fails if there are untested future Resource values
 | 
			
		||||
        assertThat(Resource.values().length, is(5));
 | 
			
		||||
        assertThat(Resource.values().length, is(4));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,6 @@ public class AbstractAcmeClientTest {
 | 
			
		|||
 | 
			
		||||
    private URI resourceUri;
 | 
			
		||||
    private URI locationUri;
 | 
			
		||||
    private URI anotherLocationUri;
 | 
			
		||||
    private URI agreementUri;
 | 
			
		||||
    private KeyPair accountKeyPair;
 | 
			
		||||
    private Registration testRegistration;
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +64,6 @@ public class AbstractAcmeClientTest {
 | 
			
		|||
    public void setup() throws IOException, URISyntaxException {
 | 
			
		||||
        resourceUri = new URI("https://example.com/acme/some-resource");
 | 
			
		||||
        locationUri = new URI("https://example.com/acme/some-location");
 | 
			
		||||
        anotherLocationUri = new URI("https://example.com/acme/another-location");
 | 
			
		||||
        agreementUri = new URI("http://example.com/agreement.pdf");
 | 
			
		||||
        accountKeyPair = TestUtils.createKeyPair();
 | 
			
		||||
        testRegistration = new Registration(accountKeyPair);
 | 
			
		||||
| 
						 | 
				
			
			@ -220,46 +218,6 @@ public class AbstractAcmeClientTest {
 | 
			
		|||
        client.changeRegistrationKey(registration, registration.getKeyPair());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Test that a {@link Registration} can be recovered by contact-based recovery.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testRecoverRegistration() throws AcmeException {
 | 
			
		||||
        Registration registration = new Registration(accountKeyPair);
 | 
			
		||||
        registration.addContact("mailto:foo@example.com");
 | 
			
		||||
        registration.setLocation(locationUri);
 | 
			
		||||
 | 
			
		||||
        Connection connection = new DummyConnection() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session, Registration registration) {
 | 
			
		||||
                assertThat(session, is(notNullValue()));
 | 
			
		||||
                assertThat(registration.getKeyPair(), is(sameInstance(accountKeyPair)));
 | 
			
		||||
                return HttpURLConnection.HTTP_CREATED;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public URI getLocation() {
 | 
			
		||||
                return anotherLocationUri;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public URI getLink(String relation) {
 | 
			
		||||
                switch(relation) {
 | 
			
		||||
                    case "terms-of-service": return agreementUri;
 | 
			
		||||
                    default: return null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        TestableAbstractAcmeClient client = new TestableAbstractAcmeClient(connection);
 | 
			
		||||
        client.putTestResource(Resource.RECOVER_REG, resourceUri);
 | 
			
		||||
 | 
			
		||||
        client.recoverRegistration(registration);
 | 
			
		||||
 | 
			
		||||
        assertThat(registration.getLocation(), is(anotherLocationUri));
 | 
			
		||||
        assertThat(registration.getAgreement(), is(agreementUri));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Test that a {@link Registration} can be deleted.
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,29 +0,0 @@
 | 
			
		|||
# Account Recovery
 | 
			
		||||
 | 
			
		||||
The ACME server identifies your account by the public key that you provided on registration. If you lose your key pair, you will be unable to access your account.
 | 
			
		||||
 | 
			
		||||
ACME offers a contact-based way of recovering access to your authorizations and certificates in case you have lost your key pair. However, it involves creating a new account, and transfering your data to it. You will not be able to regain access to your old account.
 | 
			
		||||
 | 
			
		||||
Individual CAs may offer further ways of recovery, which are not part of this documentation.
 | 
			
		||||
 | 
			
		||||
## Contact-Based Recovery
 | 
			
		||||
 | 
			
		||||
> **CAUTION**: Contact-Based Recovery is [currently not supported by _Let's Encrypt_](https://github.com/letsencrypt/boulder/issues/432). If you should lose your key pair, you are stuck.
 | 
			
		||||
 | 
			
		||||
On this recovery method, the CA contacts the account owner via one of the contact addresses given on account creation. The owner is asked to take some action (e.g. clicking on a link in an email). If it was successful, the account data is transferred to the new account.
 | 
			
		||||
 | 
			
		||||
To initiate contact-based recovery, you first need to create a new account key pair. Then create a `Registration` object by passing the _new_ key pair and location URI of your _old_ account to the constructor. Finally, start the recovery process by invoking `recoverRegistration()`:
 | 
			
		||||
 | 
			
		||||
```java
 | 
			
		||||
KeyPair newKeyPair = ... // your new account KeyPair
 | 
			
		||||
URI oldAccountUri = ... // location of your old account
 | 
			
		||||
 | 
			
		||||
Registration reg = new Registration(newKeyPair, oldAccountUri);
 | 
			
		||||
client.recoverRegistration(reg);
 | 
			
		||||
 | 
			
		||||
URI newAccountUri = reg.getLocation();
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`newAccountUri` is the location URI of your _new_ account. Store it and use it in connection with your new key pair.
 | 
			
		||||
 | 
			
		||||
The old location URI is now invalid and can be deleted.
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +34,6 @@
 | 
			
		|||
        <item name="Registration" href="usage/register.html"/>
 | 
			
		||||
        <item name="Authorization" href="usage/authorization.html"/>
 | 
			
		||||
        <item name="Certificate" href="usage/certificate.html"/>
 | 
			
		||||
        <item name="Recovery" href="usage/recovery.html"/>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item name="Challenges" href="challenge/index.html">
 | 
			
		||||
        <item name="http-01" href="challenge/http-01.html"/>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue