Can I use AWS Signature Version 4 to authenticate and authorize requests?

148    Asked by KaylaShinn in AWS , Asked on Jun 14, 2024

I am currently engaged in a particular task that is related to developing a new application that needs to interact with the various AWS services by using the AWS SDK. How can I go about ensuring that my requests for the application are properly authenticated and authorized by using the AWS signature version 4( AWS4-HMAC-SHA256) for secure communications with the AWS services? 

Answered by Julie Baber

In the context of AWS, here are the steps given for how you can do so:-

1. Generate a canonical request

Firstly, try to convert the HTTP request into a canonical format which should be based on the AWS rules. You should try to include the HTTP method, URI, query parameters, headers, and payload hash in it.

   2. Creating a string to sign

Now you can construct a string that contains metadata about the requested, including the algorithm, request, date, region, Service, etc.

Calculate the signature

Now you should derive a signing key based on your secret access keys, date, region, and the name of the service.

You can use the lightning keys to calculate the signature using HAMC-SHA256.

Add Authorization header

You should include the generated AWS access key Is, Signed headers, algorithms, and signature in the authorization header of your HTTP request.

Here is the Python-based example given below:-

Import boto3

From botocore.exceptions import NoCredentialsError
# AWS credentials and region
Aws_access_key_id = ‘YOUR_ACCESS_KEY_ID’
Aws_secret_access_key = ‘YOUR_SECRET_ACCESS_KEY’
Region_name = ‘YOUR_REGION’
# Create an S3 client with Signature Version 4
S3 = boto3.client(‘s3’,
                  Aws_access_key_id=aws_access_key_id,
                  Aws_secret_access_key=aws_secret_access_key,
                  Region_name=region_name,
                  Config=boto3.session.Config(signature_version=’s3v4’))
# Example: List objects in an S3 bucket
Try:
    Response = s3.list_objects_v2(Bucket=’YOUR_BUCKET_NAME’)
    For obj in response.get(‘Contents’, []):
        Print(obj[‘Key’])
Except NoCredentialsError:
    Print(“Credentials not available.”)
Here is the java based example given below:-
Import java.io.IOException;
Import java.net.URI;
Import java.net.URISyntaxException;
Import java.time.LocalDateTime;
Import java.time.format.DateTimeFormatter;
Import java.util.HashMap;
Import java.util.Map;
Import java.util.stream.Collectors;
Import javax.crypto.Mac;
Import javax.crypto.spec.SecretKeySpec;
Import org.apache.commons.codec.binary.Hex;
Import org.apache.http.HttpEntity;
Import org.apache.http.HttpHeaders;
Import org.apache.http.HttpResponse;
Import org.apache.http.client.methods.HttpGet;
Import org.apache.http.impl.client.CloseableHttpClient;
Import org.apache.http.impl.client.HttpClients;
Import org.apache.http.util.EntityUtils;
Public class AWSSignatureV4Example {
    Private static final String AWS_ACCESS_KEY = “YOUR_AWS_ACCESS_KEY”;
    Private static final String AWS_SECRET_KEY = “YOUR_AWS_SECRET_KEY”;
    Private static final String AWS_REGION = “YOUR_AWS_REGION”;
    Private static final String S3_BUCKET_NAME = “YOUR_S3_BUCKET_NAME”;
    Public static void main(String[] args) {
        Try {
            // Get the current time in UTC format
            LocalDateTime now = LocalDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(“yyyyMMdd’T’HHmmss’Z’”);
            String amzDate = now.format(formatter);
            // Create a canonical URI for the S3 service
            URI uri = new URI(https://s3. + AWS_REGION + “.amazonaws.com/” + S3_BUCKET_NAME);
            String canonicalUri = uri.getPath();
            // Generate a canonical query string (empty for this example)
            String canonicalQueryString = “”;
            // Generate the canonical headers
            Map headers = new HashMap<>();
            Headers.put(“host”, uri.getHost());
            Headers.put(“x-amz-content-sha256”, “UNSIGNED-PAYLOAD”);
            Headers.put(“x-amz-date”, amzDate);
            String canonicalHeaders = headers.entrySet().stream()
                    .map(e -> e.getKey().toLowerCase() + “:” + e.getValue().trim() + “
”)
                    .collect(Collectors.joining());
            // Generate the signed headers
            String signedHeaders = headers.keySet().stream()
                    .map(String::toLowerCase)
                    .collect(Collectors.joining(“;”));
            // Generate the canonical request
            String canonicalRequest = “GET
” + canonicalUri + “
” + canonicalQueryString + “

                    + canonicalHeaders + “
” + signedHeaders + “
UNSIGNED-PAYLOAD”;
            // Generate the string to sign
            String credentialScope = now.format(DateTimeFormatter.ofPattern(“yyyyMMdd”)) + “/”
                    + AWS_REGION + “/s3/aws4_request”;
            String stringToSign = “AWS4-HMAC-SHA256
” + amzDate + “
” + credentialScope + “

                    + Hex.encodeHexString(hash(canonicalRequest));
            // Generate the signing key
            Byte[] signingKey = getSignatureKey(AWS_SECRET_KEY, now.format(DateTimeFormatter.ofPattern(“yyyyMMdd”)), AWS_REGION, “s3”);
            // Calculate the signature
            String signature = Hex.encodeHexString(hmacSHA256(signingKey, stringToSign));
            // Add the authorization header
            String authorizationHeader = “AWS4-HMAC-SHA256 Credential=” + AWS_ACCESS_KEY + “/”
                    + credentialScope + “, SignedHeaders=” + signedHeaders + “, Signature=” + signature;
            // Make the HTTP request
            String url = uri.toString() + “?” + canonicalQueryString;
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader(HttpHeaders.AUTHORIZATION, authorizationHeader);
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpResponse response = httpClient.execute(httpGet);
            // Print the response
            HttpEntity entity = response.getEntity();
            String responseBody = EntityUtils.toString(entity);
            System.out.println(“Response Status Code: “ + response.getStatusLine().getStatusCode());
            System.out.println(“Response Body: “ + responseBody);
            // Close resources
            EntityUtils.consume(entity);
            httpClient.close();
        } catch (IOException | URISyntaxException e) {
            e.printStackTrace();
        }
    }
    Private static byte[] hmacSHA256(byte[] key, String data) throws IOException {
        Try {
            Mac mac = Mac.getInstance(“HmacSHA256”);
            SecretKeySpec secretKey = new SecretKeySpec(key, “HmacSHA256”);
            Mac.init(secretKey);
            Return mac.doFinal(data.getBytes());
        } catch (Exception e) {
            Throw new IOException(“Error computing HMAC-SHA256”, e);
        }
    }
    Private static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws IOException {
        Byte[] kSecret = (“AWS4” + key).getBytes();
        Byte[] kDate = hmacSHA256(kSecret, dateStamp);
        Byte[] kRegion = hmacSHA256(kDate, regionName);
        Byte[] kService = hmacSHA256(kRegion, serviceName);
        Return hmacSHA256(kService, “aws4_request”);
    }
    Private static byte[] hash(String data) throws IOException {
        Try {
            Java.security.MessageDigest md = java.security.MessageDigest.getInstance(“SHA-256”);
            Return md.digest(data.getBytes());
        } catch (java.security.NoSuchAlgorithmException e) {
            Throw new IOException(“Error hashing data with SHA-256”, e);
        }
    }
}


Your Answer

Interviews

Parent Categories