forked from aws-amplify/aws-sdk-ios
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AWSLexSignature.m
139 lines (109 loc) · 6.16 KB
/
AWSLexSignature.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//
// Copyright 2010-2017 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.
//
#import "AWSLexSignature.h"
static NSString *const AWSLexSignatureScope = @"lex";
@interface AWSLexSignature()
@property (nonatomic, strong) AWSEndpoint *endpoint;
@end
@implementation AWSLexSignature
- (instancetype)initWithCredentialsProvider:(id<AWSCredentialsProvider>)credentialsProvider
endpoint:(AWSEndpoint *)endpoint{
if (self = [super init]) {
_credentialsProvider = credentialsProvider;
_endpoint = endpoint;
}
return self;
}
- (AWSTask *)interceptRequest:(NSMutableURLRequest *)request {
[request addValue:request.URL.host forHTTPHeaderField:@"Host"];
return [[self.credentialsProvider credentials] continueWithSuccessBlock:^id _Nullable(AWSTask<AWSCredentials *> * _Nonnull task) {
AWSCredentials *credentials = task.result;
// clear authorization header if set
[request setValue:nil forHTTPHeaderField:@"Authorization"];
if (credentials) {
NSString *authorization;
[request setValue:credentials.sessionKey forHTTPHeaderField:@"X-Amz-Security-Token"];
authorization = [self signRequest:request
credentials:credentials];
if (authorization) {
[request setValue:authorization forHTTPHeaderField:@"Authorization"];
}
}
return nil;
}];
}
- (NSString *)signRequest:(NSMutableURLRequest *)request credentials:(AWSCredentials *)credentials{
NSString *absoluteString = [[request.URL absoluteString] stringByRemovingPercentEncoding];
if ([absoluteString hasSuffix:@"/"]) {
absoluteString = [absoluteString substringToIndex:[absoluteString length] - 1];
}
request.URL = [NSURL URLWithString:absoluteString];
NSDate *xAmzDate = [NSDate aws_dateFromString:[request valueForHTTPHeaderField:@"X-Amz-Date"]
format:AWSDateISO8601DateFormat2];
NSString *dateStamp = [xAmzDate aws_stringValue:AWSDateShortDateFormat1];
NSString *cfPath = (NSString *)CFBridgingRelease(CFURLCopyPath((CFURLRef)request.URL));
NSString *path = [cfPath aws_stringWithURLEncodingPath];
if (path.length == 0) {
path = [NSString stringWithFormat:@"/"];
}
NSString *query = request.URL.query;
if (query == nil) {
query = [NSString stringWithFormat:@""];
}
NSString *contentSha256;
//for streaming api the payload is unsigned.
if([path hasSuffix:@"/content"]) {
contentSha256 = @"UNSIGNED-PAYLOAD";
[request setValue:contentSha256 forHTTPHeaderField:@"x-amz-content-sha256"];
}else{
contentSha256 = [AWSSignatureSignerUtility hexEncode:[[NSString alloc] initWithData:[AWSSignatureSignerUtility hash:request.HTTPBody] encoding:NSASCIIStringEncoding]];
}
NSString *canonicalRequest = [AWSSignatureV4Signer getCanonicalizedRequest:request.HTTPMethod
path:path
query:query
headers:request.allHTTPHeaderFields
contentSha256:contentSha256];
AWSDDLogVerbose(@"AWS4 Canonical Request: [%@]", canonicalRequest);
NSString *scope = [NSString stringWithFormat:@"%@/%@/%@/%@",
dateStamp,
self.endpoint.regionName,
AWSLexSignatureScope,
AWSSignatureV4Terminator];
NSString *signingCredentials = [NSString stringWithFormat:@"%@/%@",
credentials.accessKey,
scope];
NSString *stringToSign = [NSString stringWithFormat:@"%@\n%@\n%@\n%@",
AWSSignatureV4Algorithm,
[request valueForHTTPHeaderField:@"X-Amz-Date"],
scope,
[AWSSignatureSignerUtility hexEncode:[AWSSignatureSignerUtility hashString:canonicalRequest]]];
AWSDDLogVerbose(@"AWS4 String to Sign: [%@]", stringToSign);
NSData *kSigning = [AWSSignatureV4Signer getV4DerivedKey:credentials.secretKey
date:dateStamp
region:self.endpoint.regionName
service:AWSLexSignatureScope];
NSData *signature = [AWSSignatureSignerUtility sha256HMacWithData:[stringToSign dataUsingEncoding:NSUTF8StringEncoding]
withKey:kSigning];
NSString *credentialsAuthorizationHeader = [NSString stringWithFormat:@"Credential=%@", signingCredentials];
NSString *signedHeadersAuthorizationHeader = [NSString stringWithFormat:@"SignedHeaders=%@", [AWSSignatureV4Signer getSignedHeadersString:request.allHTTPHeaderFields]];
NSString *signatureAuthorizationHeader = [NSString stringWithFormat:@"Signature=%@", [AWSSignatureSignerUtility hexEncode:[[NSString alloc] initWithData:signature encoding:NSASCIIStringEncoding]]];
NSString *authorization = [NSString stringWithFormat:@"%@ %@, %@, %@",
AWSSignatureV4Algorithm,
credentialsAuthorizationHeader,
signedHeadersAuthorizationHeader,
signatureAuthorizationHeader];
return authorization;
}
@end