001/* 002 * acme4j - Java ACME client 003 * 004 * Copyright (C) 2015 Richard "Shred" Körber 005 * http://acme4j.shredzone.org 006 * 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 013 */ 014package org.shredzone.acme4j.challenge; 015 016import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode; 017 018import java.security.PublicKey; 019 020import org.jose4j.jwk.PublicJsonWebKey; 021import org.jose4j.lang.JoseException; 022import org.shredzone.acme4j.Session; 023import org.shredzone.acme4j.exception.AcmeProtocolException; 024import org.shredzone.acme4j.toolbox.JSONBuilder; 025 026/** 027 * An extension of {@link Challenge} that handles challenges with a {@code token} and 028 * {@code keyAuthorization}. 029 */ 030public class TokenChallenge extends Challenge { 031 private static final long serialVersionUID = 1634133407432681800L; 032 033 protected static final String KEY_TOKEN = "token"; 034 protected static final String KEY_KEY_AUTHORIZATION = "keyAuthorization"; 035 036 private String authorization; 037 038 /** 039 * Creates a new generic {@link TokenChallenge} object. 040 * 041 * @param session 042 * {@link Session} to bind to. 043 */ 044 public TokenChallenge(Session session) { 045 super(session); 046 } 047 048 @Override 049 protected void respond(JSONBuilder cb) { 050 super.respond(cb); 051 cb.put(KEY_TOKEN, getToken()); 052 cb.put(KEY_KEY_AUTHORIZATION, getAuthorization()); 053 } 054 055 /** 056 * Gets the token. 057 */ 058 protected String getToken() { 059 return getJSON().get(KEY_TOKEN).required().asString(); 060 } 061 062 /** 063 * Gets the authorization. 064 */ 065 protected String getAuthorization() { 066 return authorization; 067 } 068 069 /** 070 * Computes the authorization string. 071 * <p> 072 * The default is {@code token + '.' + base64url(jwkThumbprint)}. Subclasses may 073 * override this method if a different algorithm is used. 074 * 075 * @return Authorization string 076 */ 077 protected String computeAuthorization() { 078 try { 079 PublicKey pk = getSession().getKeyPair().getPublic(); 080 PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(pk); 081 return getToken() 082 + '.' 083 + base64UrlEncode(jwk.calculateThumbprint("SHA-256")); 084 } catch (JoseException ex) { 085 throw new AcmeProtocolException("Cannot compute key thumbprint", ex); 086 } 087 } 088 089 @Override 090 protected void authorize() { 091 super.authorize(); 092 authorization = computeAuthorization(); 093 } 094 095}