public String getSignedUrl()

in aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/util/AwsIotWebSocketUrlSigner.java [224:301]


    public String getSignedUrl(final Date signingDate) throws AWSIotException {
        CredentialsProvider provider = null;
        synchronized (this) {
            provider = credentialsProvider;
        }

        if (provider == null) {
            throw new AWSIotException("No credentials provider available for signing");
        }

        Credentials credentials = provider.getCredentials();
        if (credentials == null) {
            throw new AWSIotException("Could not source AWS credentials from provider");
        }

        String awsAccessKeyId = credentials.getAccessKeyId();

        Date dateToUse = signingDate;
        if (dateToUse == null) {
            dateToUse = new Date();
        }

        // SigV4 canonical string uses time in two formats
        String amzDate = getAmzDate(dateToUse);
        String dateStamp = getDateStamp(dateToUse);
        // Credential scoped to date and region
        String credentialScope = dateStamp + "/" + regionName + "/" + ServiceName + "/aws4_request";
        // Now build the canonical string
        StringBuilder canonicalQueryStringBuilder = new StringBuilder();
        canonicalQueryStringBuilder.append("X-Amz-Algorithm=").append(ALGORITHM);
        canonicalQueryStringBuilder.append("&X-Amz-Credential=");
        try {
            canonicalQueryStringBuilder.append(URLEncoder.encode(awsAccessKeyId + "/" + credentialScope, UTF8));
        } catch (UnsupportedEncodingException e) {
            throw new AWSIotException("Error encoding URL when building WebSocket URL");
        }
        canonicalQueryStringBuilder.append("&X-Amz-Date=").append(amzDate);
        canonicalQueryStringBuilder.append("&X-Amz-SignedHeaders=host");

        // headers and payload for the signing request
        // not used in an WebSocket URL, but encoded into the signature string
        String canonicalHeaders = "host:" + endpoint + "\n";
        String payloadHash = stringToHex(hash(""));

        // The request to sign includes the HTTP method, path, query string,
        // headers and payload
        String canonicalRequest = METHOD + "\n" + CANONICAL_URI + "\n" + canonicalQueryStringBuilder.toString() + "\n"
                + canonicalHeaders + "\nhost\n" + payloadHash;

        // Create a string to sign, generate a signing key...
        String stringToSign = ALGORITHM + "\n" + amzDate + "\n" + credentialScope + "\n"
                + stringToHex(hash(canonicalRequest));
        byte[] signingKey = getSigningKey(credentials, dateStamp);
        // ...and sign the string.
        byte[] signatureBytes = sign(stringToSign, signingKey);
        String signature = stringToHex(signatureBytes);

        // Add the signature to the query string.
        canonicalQueryStringBuilder.append("&X-Amz-Signature=");
        canonicalQueryStringBuilder.append(signature);

        // Now build the URL.
        String requestUrl = "wss://" + endpoint + CANONICAL_URI + "?" + canonicalQueryStringBuilder.toString();

        // If there are session credentials (from an STS server, AssumeRole, or
        // Amazon Cognito),
        // append the session token to the end of the URL string after signing.
        String sessionToken = credentials.getSessionToken();
        if (sessionToken != null) {
            try {
                requestUrl += "&X-Amz-Security-Token=" + URLEncoder.encode(sessionToken, UTF8);
            } catch (UnsupportedEncodingException e) {
                throw new AWSIotException(e);
            }
        }

        return requestUrl;
    }