From 066c04104a0b474f4e8a5ce6d068d6cd0e24edfe Mon Sep 17 00:00:00 2001 From: Sergey Chuvashev Date: Tue, 28 May 2019 12:10:47 +0400 Subject: [PATCH 1/3] Update sig_v4.dart --- lib/sig_v4.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/sig_v4.dart b/lib/sig_v4.dart index 12dfc1b..705b2c0 100644 --- a/lib/sig_v4.dart +++ b/lib/sig_v4.dart @@ -218,7 +218,7 @@ class SigV4 { String path, Map queryParams, Map headers, - String payload) { + String payload, [bool hasPayload = true]) { List canonicalRequest = [ method, buildCanonicalUri(path), @@ -226,6 +226,7 @@ class SigV4 { buildCanonicalHeaders(headers), buildCanonicalSignedHeaders(headers), hexEncode(hash(utf8.encode(payload))), + if (hasPayload) hexEncode(hash(utf8.encode(payload))) else payload, ]; return canonicalRequest.join('\n'); } From 54d28de48cc755c3a7c2fa6cd17820fddc328f24 Mon Sep 17 00:00:00 2001 From: Sergey Chuvashev Date: Tue, 28 May 2019 12:32:44 +0400 Subject: [PATCH 2/3] Update sig_v4.dart --- lib/sig_v4.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/sig_v4.dart b/lib/sig_v4.dart index 705b2c0..d9b2088 100644 --- a/lib/sig_v4.dart +++ b/lib/sig_v4.dart @@ -225,7 +225,6 @@ class SigV4 { buildCanonicalQueryString(queryParams), buildCanonicalHeaders(headers), buildCanonicalSignedHeaders(headers), - hexEncode(hash(utf8.encode(payload))), if (hasPayload) hexEncode(hash(utf8.encode(payload))) else payload, ]; return canonicalRequest.join('\n'); From 4071ef5d564c89f9124d3d2fd9469c5cd02cec00 Mon Sep 17 00:00:00 2001 From: Sergey Chuvashev Date: Wed, 19 Jun 2019 12:47:50 +0400 Subject: [PATCH 3/3] Added example for case presign url --- README.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/sig_v4.dart | 6 ++-- 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 54428c9..bb3d265 100644 --- a/README.md +++ b/README.md @@ -527,6 +527,98 @@ $payload'''; } ``` +#### For PreSign S3 url + + +```dart +import 'dart:io'; +import 'package:path/path.dart' as path; +import 'package:amazon_cognito_identity_dart/cognito.dart'; +import 'package:amazon_cognito_identity_dart/sig_v4.dart'; +import 'package:http/http.dart' as http; + +void main() { + const _awsUserPoolId = 'ap-southeast-1_xxxxxxxx'; + const _awsClientId = 'xxxxxxxxxxxxxxxxxxxxxxxxxx'; + + const _identityPoolId = + 'ap-southeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'; + final _userPool = CognitoUserPool(_awsUserPoolId, _awsClientId); + + final _cognitoUser = CognitoUser('+60100000000', _userPool); + final authDetails = + AuthenticationDetails(username: '+60100000000', password: 'p@ssW0rd'); + + CognitoUserSession _session; + try { + _session = await _cognitoUser.authenticateUser(authDetails); + } catch (e) { + print(e); + return; + } + + final _credentials = CognitoCredentials(_identityPoolId, _userPool); + await _credentials.getAwsCredentials(_session.getIdToken().getJwtToken()); + + final service = 's3'; + final region = 'ap-southeast-1'; + final bucket = 'bucket-name' + final host = '$bucket.$service.$region.amazonaws.com'; + final headers = {"Host": host}; + final key = 'public/square-cinnamon.jpg'; + + Map params = {}; + + final datetime = SigV4.generateDatetime(); + final credentialScope = SigV4.buildCredentialScope(datetime, region, service); + + params['X-Amz-Security-Token'] = _credentials.sessionToken; + params['X-Amz-Algorithm'] = aws_sha_256; + params['X-Amz-Date'] = datetime; + params['X-Amz-SignedHeaders'] = SigV4.buildCanonicalSignedHeaders(headers); + params['X-Amz-Expires'] = '3599'; + params['X-Amz-Credential'] = '${credentials.accessKeyId}/$credentialScope'; + + final canonicalRequest = SigV4.buildCanonicalRequest( + 'GET', + '/$key', + params, + headers, + 'UNSIGNED-PAYLOAD', false); + + final stringToSign = SigV4.buildStringToSign(datetime, credentialScope, SigV4.hashCanonicalRequest(canonicalRequest)); + + final signingKey = SigV4.calculateSigningKey(_credentials.secretAccessKey, datetime, region, service); + final signature = SigV4.calculateSignature(signingKey, stringToSign); + + params['X-Amz-Signature'] = signature; + + final url = 'https://$host${'/$key'.split('/').map((s) => Uri.encodeComponent(s)).join('/')}?' + + params.keys.map((key) => '$key=${Uri.encodeComponent(params[key])}').join('&'); + + http.Response response; + try { + response = await http.get(url); + } catch (e) { + print(e); + return; + } + + final file = File(path.join( + '/path/to/my/folder', + 'square-cinnamon-downloaded.jpg')); + + try { + await file.writeAsBytes(response.bodyBytes); + } catch (e) { + print(e.toString()); + return; + } + + print('complete!'); +} +``` + #### For AppSync's GraphQL Authenticating Amazon Cognito User Pool using JWT Tokens. diff --git a/lib/sig_v4.dart b/lib/sig_v4.dart index d9b2088..0c03a15 100644 --- a/lib/sig_v4.dart +++ b/lib/sig_v4.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:convert/convert.dart'; import 'package:crypto/crypto.dart'; -const _aws_sha_256 = 'AWS4-HMAC-SHA256'; +const aws_sha_256 = 'AWS4-HMAC-SHA256'; const _aws4_request = 'aws4_request'; const _aws4 = 'AWS4'; const _x_amz_date = 'x-amz-date'; @@ -218,14 +218,14 @@ class SigV4 { String path, Map queryParams, Map headers, - String payload, [bool hasPayload = true]) { + String payload, [bool signPayload = true]) { List canonicalRequest = [ method, buildCanonicalUri(path), buildCanonicalQueryString(queryParams), buildCanonicalHeaders(headers), buildCanonicalSignedHeaders(headers), - if (hasPayload) hexEncode(hash(utf8.encode(payload))) else payload, + if (signPayload) hexEncode(hash(utf8.encode(payload))) else payload, ]; return canonicalRequest.join('\n'); }