Skip to content

Commit a25527a

Browse files
committed
feat(api): Add async protocol implementation for token request interceptors (#2870)
1 parent 719d670 commit a25527a

File tree

12 files changed

+151
-31
lines changed

12 files changed

+151
-31
lines changed

Amplify/Categories/API/AuthProvider/APIAuthProviderFactory.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,20 @@ open class APIAuthProviderFactory {
2525
}
2626

2727
public protocol AmplifyAuthTokenProvider {
28+
2829
typealias AuthToken = String
30+
2931
func getLatestAuthToken() -> Result<AuthToken, Error>
32+
33+
func getLatestAuthToken(completion: @escaping (Result<AuthToken, Error>) -> Void)
34+
}
35+
36+
public extension AmplifyAuthTokenProvider {
37+
38+
func getLatestAuthToken(completion: @escaping (Result<AuthToken, Error>) -> Void) {
39+
let result = getLatestAuthToken()
40+
completion(result)
41+
}
3042
}
3143

3244
/// Amplify OIDC Auth Provider

AmplifyPlugins.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Pod::Spec.new do |s|
3636

3737
s.subspec 'AWSAPIPlugin' do |ss|
3838
ss.source_files = 'AmplifyPlugins/API/AWSAPICategoryPlugin/**/*.swift'
39-
ss.dependency 'AppSyncRealTimeClient', "~> 3.0"
39+
ss.dependency 'AppSyncRealTimeClient', "~> 3.1"
4040
end
4141

4242
s.subspec 'AWSCognitoAuthPlugin' do |ss|

AmplifyPlugins/API/AWSAPICategoryPlugin/Interceptor/RequestInterceptor/AuthTokenProviderWrapper.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,19 @@ class AuthTokenProviderWrapper: AuthTokenProvider {
2929
}
3030
}
3131

32+
func getToken(completion: @escaping (Result<String, AuthError>) -> Void) {
33+
wrappedAuthTokenProvider.getLatestAuthToken { result in
34+
switch result {
35+
case .success(let token):
36+
completion(.success(token))
37+
return
38+
case .failure(let error):
39+
completion(.failure(AuthError.service("Unable to get latest auth token",
40+
"",
41+
error)))
42+
return
43+
}
44+
}
45+
}
46+
3247
}

AmplifyPlugins/API/AWSAPICategoryPlugin/Interceptor/SubscriptionInterceptor/AuthenticationTokenAuthInterceptor.swift

Lines changed: 85 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,35 +19,50 @@ class AuthenticationTokenAuthInterceptor: AuthInterceptor {
1919
self.authTokenProvider = authTokenProvider
2020
}
2121

22-
func interceptMessage(_ message: AppSyncMessage, for endpoint: URL) -> AppSyncMessage {
23-
let host = endpoint.host!
24-
guard let authToken = getAuthToken() else {
25-
log.warn("Missing authentication token for subscription")
26-
return message
22+
func interceptMessage(
23+
_ message: AppSyncMessage,
24+
for endpoint: URL,
25+
completion: @escaping (AppSyncMessage) -> Void) {
26+
let host = endpoint.host!
27+
28+
guard case .subscribe = message.messageType else {
29+
completion(message)
30+
return
31+
}
32+
33+
authTokenProvider.getLatestAuthToken { result in
34+
let signedMessage = self.signedMessage(
35+
message,
36+
host: host,
37+
tokenResult: result)
38+
completion(signedMessage)
39+
return
40+
}
2741
}
2842

29-
guard case .subscribe = message.messageType else {
30-
return message
43+
func interceptConnection(
44+
_ request: AppSyncConnectionRequest,
45+
for endpoint: URL,
46+
completion: @escaping (AppSyncConnectionRequest) -> Void) {
47+
let host = endpoint.host!
48+
authTokenProvider.getLatestAuthToken { result in
49+
let signedRequest = self.signedRequest(
50+
request,
51+
for: endpoint,
52+
host: host,
53+
tokenResult: result)
54+
completion(signedRequest)
55+
return
56+
}
3157
}
3258

33-
let authHeader = TokenAuthHeader(token: authToken, host: host)
34-
var payload = message.payload ?? AppSyncMessage.Payload()
35-
payload.authHeader = authHeader
36-
37-
let signedMessage = AppSyncMessage(
38-
id: message.id,
39-
payload: payload,
40-
type: message.messageType
41-
)
42-
return signedMessage
43-
}
44-
45-
func interceptConnection(
59+
private func signedRequest(
4660
_ request: AppSyncConnectionRequest,
47-
for endpoint: URL
61+
for endpoint: URL,
62+
host: String,
63+
tokenResult: Result<String, Error>
4864
) -> AppSyncConnectionRequest {
49-
let host = endpoint.host!
50-
guard let authToken = getAuthToken() else {
65+
guard let authToken = try? tokenResult.get() else {
5166
log.warn("Missing authentication token for subscription request")
5267
return request
5368
}
@@ -71,9 +86,54 @@ class AuthenticationTokenAuthInterceptor: AuthInterceptor {
7186
return signedRequest
7287
}
7388

74-
private func getAuthToken() -> AmplifyAuthTokenProvider.AuthToken? {
75-
try? authTokenProvider.getLatestAuthToken().get()
89+
private func signedMessage(
90+
_ message: AppSyncMessage,
91+
host: String,
92+
tokenResult: Result<String, Error>) -> AppSyncMessage {
93+
94+
guard let authToken = try? tokenResult.get() else {
95+
log.warn("Missing authentication token for subscription")
96+
return message
97+
}
98+
99+
let authHeader = TokenAuthHeader(token: authToken, host: host)
100+
var payload = message.payload ?? AppSyncMessage.Payload()
101+
payload.authHeader = authHeader
102+
103+
let signedMessage = AppSyncMessage(
104+
id: message.id,
105+
payload: payload,
106+
type: message.messageType
107+
)
108+
return signedMessage
109+
}
110+
111+
func interceptMessage(_ message: AppSyncMessage, for endpoint: URL) -> AppSyncMessage {
112+
let host = endpoint.host!
113+
114+
guard case .subscribe = message.messageType else {
115+
return message
116+
}
117+
let signedMessage = self.signedMessage(
118+
message,
119+
host: host,
120+
tokenResult: authTokenProvider.getLatestAuthToken())
121+
return signedMessage
122+
}
123+
124+
func interceptConnection(
125+
_ request: AppSyncConnectionRequest,
126+
for endpoint: URL
127+
) -> AppSyncConnectionRequest {
128+
let host = endpoint.host!
129+
let signedRequest = signedRequest(
130+
request,
131+
for: endpoint,
132+
host: host,
133+
tokenResult: authTokenProvider.getLatestAuthToken())
134+
return signedRequest
76135
}
136+
77137
}
78138

79139
// MARK: AuthorizationTokenAuthInterceptor + DefaultLogger

AmplifyPlugins/API/AWSAPICategoryPlugin/Interceptor/SubscriptionInterceptor/OIDCAuthProviderWrapper.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@ class OIDCAuthProviderWrapper: OIDCAuthProvider {
2020
func getLatestAuthToken() -> Result<String, Error> {
2121
return authTokenProvider.getLatestAuthToken()
2222
}
23+
24+
func getLatestAuthToken(completion: @escaping (Result<String, Error>) -> Void ) {
25+
authTokenProvider.getLatestAuthToken(completion: completion)
26+
}
2327
}

AmplifyPlugins/API/AWSAPICategoryPluginTests/Configuration/AWSAPICategoryPluginConfigurationTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ class AWSAPICategoryPluginConfigurationTests: XCTestCase {
126126
func getToken() -> Result<String, AuthError> {
127127
.success("token")
128128
}
129+
130+
func getToken(completion: @escaping (Result<String, AuthError>) -> Void) {
131+
completion(.success("token"))
132+
}
129133
}
130134

131135
}

AmplifyPlugins/API/AWSAPICategoryPluginTests/Interceptor/AuthTokenURLRequestInterceptorTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,9 @@ extension AuthTokenURLRequestInterceptorTests {
3737
func getToken() -> Result<String, AuthError> {
3838
.success(authorizationToken)
3939
}
40+
41+
func getToken(completion: @escaping (Result<String, AuthError>) -> Void) {
42+
completion(.success(authorizationToken))
43+
}
4044
}
4145
}

AmplifyPlugins/API/Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ include_build_tools!
88
target 'AWSAPICategoryPlugin' do
99
pod 'Amplify', :path => '../../'
1010
pod 'AWSPluginsCore', :path => '../../'
11-
pod "AppSyncRealTimeClient", "~> 3.0"
11+
pod "AppSyncRealTimeClient", "~> 3.1"
1212

1313
target "AWSAPICategoryPluginTests" do
1414
inherit! :complete

AmplifyPlugins/API/Podfile.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ DEPENDENCIES:
5454
- Amplify (from `../../`)
5555
- AmplifyPlugins/AWSCognitoAuthPlugin (from `../../`)
5656
- AmplifyTestCommon (from `../../`)
57-
- AppSyncRealTimeClient (~> 3.0)
57+
- AppSyncRealTimeClient (~> 3.1)
5858
- AWSPluginsCore (from `../../`)
5959
- CwlCatchException (= 2.1.1)
6060
- CwlPreconditionTesting (from `https://github.com/mattgallagher/CwlPreconditionTesting.git`, tag `2.1.0`)
@@ -115,6 +115,6 @@ SPEC CHECKSUMS:
115115
SwiftFormat: 3b5caa6389b2b9adbc00e133b3ccc8c6e687a6a4
116116
SwiftLint: 32ee33ded0636d0905ef6911b2b67bbaeeedafa5
117117

118-
PODFILE CHECKSUM: 5170578806036f2ba018abb8868d56e448fb0ada
118+
PODFILE CHECKSUM: f542a7a3bf7a7e882e6ea4799c9722d5b6495208
119119

120-
COCOAPODS: 1.11.3
120+
COCOAPODS: 1.12.0

AmplifyPlugins/Core/AWSPluginsCore/Auth/Provider/AuthTokenProvider.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,18 @@ import Foundation
99
import Amplify
1010

1111
public protocol AuthTokenProvider {
12+
1213
func getToken() -> Result<String, AuthError>
14+
15+
func getToken(completion: @escaping (Result<String, AuthError>) -> Void)
16+
}
17+
18+
public extension AuthTokenProvider {
19+
20+
func getToken(completion: @escaping (Result<String, AuthError>) -> Void) {
21+
let result = getToken()
22+
completion(result)
23+
}
1324
}
1425

1526
public struct BasicUserPoolTokenProvider: AuthTokenProvider {
@@ -23,4 +34,8 @@ public struct BasicUserPoolTokenProvider: AuthTokenProvider {
2334
public func getToken() -> Result<String, AuthError> {
2435
return authService.getToken()
2536
}
37+
38+
public func getToken(completion: @escaping (Result<String, AuthError>) -> Void) {
39+
authService.getUserPoolAccessToken(completion: completion)
40+
}
2641
}

0 commit comments

Comments
 (0)