Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -346,146 +346,11 @@ let authorizer = AuthTokenAuthorizer(fetchLatestAuthToken: getUserPoolAccessToke

#### AWS IAM

If you are using Amplify Auth, you can use the following class to implement SigV4 signing logic:

```swift
import Foundation
import Amplify
import AWSPluginsCore
import AwsCommonRuntimeKit
import AWSSDKHTTPAuth
import Smithy
import SmithyHTTPAPI
import SmithyHTTPAuth
import SmithyHTTPAuthAPI
import SmithyIdentity

class AppSyncEventsSigner {

public static func createAppSyncSigner(region: String) -> ((URLRequest) async throws -> URLRequest) {
return { request in
try await signAppSyncRequest(request,
region: region)
}
}

private static var signer = {
return AWSSigV4Signer()
}()

static func signAppSyncRequest(_ urlRequest: URLRequest,
region: Swift.String,
signingName: Swift.String = "appsync",
date: Date = Date()) async throws -> URLRequest {
CommonRuntimeKit.initialize()

// Convert URLRequest to SDK's HTTPRequest
guard let requestBuilder = try createAppSyncSdkHttpRequestBuilder(
urlRequest: urlRequest) else {
return urlRequest
}

// Retrieve the credentials from credentials provider
let credentials: AWSCredentialIdentity
let authSession = try await Amplify.Auth.fetchAuthSession()
if let awsCredentialsProvider = authSession as? AuthAWSCredentialsProvider {
let awsCredentials = try awsCredentialsProvider.getAWSCredentials().get()
credentials = try awsCredentials.toAWSSDKCredentials()
} else {
let error = AuthError.unknown("Auth session does not include AWS credentials information")
throw error
}

// Prepare signing
let flags = SigningFlags(useDoubleURIEncode: true,
shouldNormalizeURIPath: true,
omitSessionToken: false)
let signedBodyHeader: AWSSignedBodyHeader = .none
let signedBodyValue: AWSSignedBodyValue = .empty
let signingConfig = AWSSigningConfig(credentials: credentials,
signedBodyHeader: signedBodyHeader,
signedBodyValue: signedBodyValue,
flags: flags,
date: date,
service: signingName,
region: region,
signatureType: .requestHeaders,
signingAlgorithm: .sigv4)

// Sign request
guard let httpRequest = await signer.sigV4SignedRequest(
requestBuilder: requestBuilder,
signingConfig: signingConfig
) else {
return urlRequest
}

// Update original request with new headers
return setHeaders(from: httpRequest, to: urlRequest)
}

static func setHeaders(from sdkRequest: SmithyHTTPAPI.HTTPRequest, to urlRequest: URLRequest) -> URLRequest {
var urlRequest = urlRequest
for header in sdkRequest.headers.headers {
urlRequest.setValue(header.value.joined(separator: ","), forHTTPHeaderField: header.name)
}
return urlRequest
}

static func createAppSyncSdkHttpRequestBuilder(urlRequest: URLRequest) throws -> HTTPRequestBuilder? {

guard let url = urlRequest.url,
let host = url.host else {
return nil
}

let headers = urlRequest.allHTTPHeaderFields ?? [:]
let httpMethod = (urlRequest.httpMethod?.uppercased())
.flatMap(HTTPMethodType.init(rawValue:)) ?? .get

let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?
.map { URIQueryItem(name: $0.name, value: $0.value)} ?? []

let requestBuilder = HTTPRequestBuilder()
.withHost(host)
.withPath(url.path)
.withQueryItems(queryItems)
.withMethod(httpMethod)
.withPort(443)
.withProtocol(.https)
.withHeaders(.init(headers))
.withBody(.data(urlRequest.httpBody))

return requestBuilder
}
}

extension AWSPluginsCore.AWSCredentials {

func toAWSSDKCredentials() throws -> AWSCredentialIdentity {
if let tempCredentials = self as? AWSTemporaryCredentials {
return AWSCredentialIdentity(
accessKey: tempCredentials.accessKeyId,
secret: tempCredentials.secretAccessKey,
expiration: tempCredentials.expiration,
sessionToken: tempCredentials.sessionToken
)
} else {
return AWSCredentialIdentity(
accessKey: accessKeyId,
secret: secretAccessKey,
expiration: nil
)
}
}
}
```

Then, create an `IAMAuthorizer` with this helper class.
If you are using Amplify Auth, you can initialize `IAMAuthorizer` with a helper method from `AWSCognitoAuthPlugin` like below:

```swift
let authorizer = IAMAuthorizer(
signRequest: AppSyncEventsSigner.createAppSyncSigner(region: "region")
signRequest: AWSCognitoAuthPlugin.createAppSyncSigner(region: "region")
)
```

Expand Down