/** * Create a signature given the set of request credentials and a secret key. * * @param credentials the credentials specified on the request * @param secretKey the secret key that will be used to generate the signature * @return the signature */ private String createSignature(Credentials credentials, String secretKey) { return new SignatureGenerator() .generate( secretKey, credentials.getMethod(), credentials.getTimestamp(), credentials.getPath(), credentials.getContent()); }
@Override public Principal authenticate(Credentials credentials) { // Make sure the timestamp has not expired - this is to protect against replay attacks if (!validateTimestamp(credentials.getTimestamp())) { LOG.info("Invalid timestamp"); return null; } // Get the principal identified by the credentials Principal principal = getPrincipal(credentials); if (principal == null) { LOG.info("Could not get principal"); return null; } // Get the secret key and use it to validate the request signature String secretKey = getSecretKeyFromPrincipal(principal); if (!validateSignature(credentials, secretKey)) { LOG.info("Invalid signature"); return null; } return principal; }
/** * Validate the signature on the request by generating a new signature here and making sure they * match. The only way for them to match is if both signature are generated using the same secret * key. If they match, this means that the requester has a valid secret key and can be a trusted * source. * * @param credentials the credentials specified on the request * @param secretKey the secret key that will be used to generate the signature * @return true if the signature is valid */ private boolean validateSignature(Credentials credentials, String secretKey) { String clientSignature = credentials.getSignature(); String serverSignature = createSignature(credentials, secretKey); return MessageDigest.isEqual(clientSignature.getBytes(), serverSignature.getBytes()); }