/* * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.amazonaws.tvm.anonymous; import java.util.logging.Logger; import com.amazonaws.services.securitytoken.model.Credentials; import com.amazonaws.tvm.Configuration; import com.amazonaws.tvm.Utilities; import com.amazonaws.tvm.TokenVendingMachineLogger; import com.amazonaws.tvm.anonymous.DeviceAuthentication.DeviceInfo; import com.amazonaws.tvm.anonymous.exception.DataAccessException; import com.amazonaws.tvm.anonymous.exception.UnauthorizedException; /** * This class implements functions for Anonymous mode. It allows to register new * devices and specify the encryption key to be used for this device in future * communication. This class allows a registered device to make token request. * The request is validated using signature and granted tokens if signature is * valid. The tokens are encrypted using the key corresponding to the device UID * so that it can be decrypted back by the same device only. */ public class AnonymousTokenVendingMachine { public static final Logger log = TokenVendingMachineLogger.getLogger(); private final DeviceAuthentication authenticator; private final TemporaryCredentialManagement credentialManagement; public AnonymousTokenVendingMachine() { authenticator = new DeviceAuthentication(); credentialManagement = new TemporaryCredentialManagement(); } /** * Verify if the given signature is valid. * * @param stringToSign * The string to sign * @param key * The key used in the signature process * @param signature * Base64 encoded HMAC-SHA256 signature derived from key and * string * @return true if computed signature matches with the given signature, * false otherwise */ public boolean validateSignature(String stringToSign, String key, String targetSignature) { String computedSignature = Utilities.sign(stringToSign, key); return Utilities.slowStringComparison(targetSignature, computedSignature); } /** * Verify if the token request is valid. UID is authenticated. The timestamp * is checked to see it falls within the valid timestamp window. The * signature is computed and matched against the given signature. Useful in * Anonymous and Identity modes * * @param uid * Unique device identifier * @param signature * Base64 encoded HMAC-SHA256 signature derived from key and * timestamp * @param timestamp * Timestamp of the request in ISO8601 format * @throws DataAccessException * @throws UnauthorizedException */ public void validateTokenRequest(String uid, String signature, String timestamp) throws DataAccessException, UnauthorizedException { if (!Utilities.isTimestampValid(timestamp)) { throw new UnauthorizedException("Invalid timestamp: " + timestamp); } log.info(String.format("Timestamp [ %s ] is valid", timestamp)); DeviceInfo device = authenticator.getDeviceInfo(uid); if (device == null) { throw new UnauthorizedException("Couldn't find device: " + uid); } if (!validateSignature(timestamp, device.getKey(), signature)) { throw new UnauthorizedException("Invalid signature: " + signature); } log.info("Signature matched!!!"); } /** * Generate tokens for given UID. The tokens are encrypted using the key * corresponding to UID. Encrypted tokens are then wrapped in JSON object * before returning it. Useful in Anonymous and Identity modes * * @param uid * Unique device identifier * @return encrypted tokens as JSON object * @throws DataAccessException * @throws UnauthorizedException */ public String getToken(String uid) throws DataAccessException, UnauthorizedException { DeviceInfo device = authenticator.getDeviceInfo(uid); if (device == null) { throw new UnauthorizedException("Couldn't find device: " + uid); } log.info("Creating temporary credentials"); Credentials sessionCredentials = credentialManagement.getTemporaryCredentials(uid); log.info("Generating session tokens for UID : " + uid); return Utilities.prepareJsonResponseForTokens(sessionCredentials, device.getKey()); } /** * Allows user device (e.g. mobile) to register with Token Vending Machine * (TVM). This function is useful in Anonymous mode * * @param uid * Unique device identifier * @param key * Secret piece of information * @return status code indicating if the registration was successful or not * @throws DataAccessException */ public boolean registerDevice(String uid, String key) throws DataAccessException { return authenticator.registerDevice(uid, key); } }