Skip to content

Commit 70a49c1

Browse files
authored
fix(Auth): Adding missing Authorization header when a Client Secret is defined. (#2807)
1 parent fa770b1 commit 70a49c1

File tree

3 files changed

+131
-1
lines changed

3 files changed

+131
-1
lines changed

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Helpers/ConfigurationHelper.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ struct ConfigurationHelper {
9494
scopes: scopesArray,
9595
signInRedirectURI: signInRedirectURI,
9696
signOutRedirectURI: signOutRedirectURI)
97-
return HostedUIConfigurationData(clientId: appClientId, oauth: oauth, clientSecret: nil)
97+
var clientSecret: String?
98+
if case .string(let appClientSecret) = configuration?.value(at: "AppClientSecret") {
99+
clientSecret = appClientSecret
100+
}
101+
return HostedUIConfigurationData(clientId: appClientId, oauth: oauth, clientSecret: clientSecret)
98102
}
99103

100104
static func parseIdentityPoolData(_ config: JSONValue) -> IdentityPoolConfigurationData? {

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/HostedUI/HostedUIRequestHelper.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ struct HostedUIRequestHelper {
116116
var urlRequest = URLRequest(url: url)
117117
urlRequest.httpMethod = "POST"
118118
urlRequest.httpBody = body.data(using: .utf8)
119+
urlRequest.addHeaders(using: configuration)
119120
return urlRequest
120121
}
121122

@@ -145,6 +146,7 @@ struct HostedUIRequestHelper {
145146
var urlRequest = URLRequest(url: url)
146147
urlRequest.httpMethod = "POST"
147148
urlRequest.httpBody = body.data(using: .utf8)
149+
urlRequest.addHeaders(using: configuration)
148150
return urlRequest
149151
}
150152

@@ -154,3 +156,14 @@ struct HostedUIRequestHelper {
154156
.replacingOccurrences(of: "=", with: "")
155157
}
156158
}
159+
160+
private extension URLRequest {
161+
mutating func addHeaders(using configuration: HostedUIConfigurationData) {
162+
guard let clientSecret = configuration.clientSecret,
163+
let value = "\(configuration.clientId):\(clientSecret)".data(using: .utf8) else {
164+
return
165+
}
166+
167+
setValue("Basic \(value.base64EncodedString())", forHTTPHeaderField: "Authorization")
168+
}
169+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Foundation
9+
10+
@testable import AWSCognitoAuthPlugin
11+
import Amplify
12+
import XCTest
13+
14+
class HostedUIRequestHelperTests: XCTestCase {
15+
private var configuration: HostedUIConfigurationData!
16+
private let result = HostedUIResult(
17+
code: "code",
18+
state: "state",
19+
codeVerifier: "codeVerifier",
20+
options: .init(
21+
scopes: [],
22+
providerInfo: .init(
23+
authProvider: nil,
24+
idpIdentifier: nil
25+
),
26+
presentationAnchor: nil,
27+
preferPrivateSession: false)
28+
)
29+
30+
override func setUp() {
31+
createConfiguration()
32+
}
33+
34+
override func tearDown() {
35+
configuration = nil
36+
}
37+
38+
private var encodedSecret: String? {
39+
guard let clientSecret = configuration.clientSecret,
40+
let value = "\(configuration.clientId):\(clientSecret)".data(using: .utf8) else {
41+
return nil
42+
}
43+
44+
return value.base64EncodedString()
45+
}
46+
47+
private func createConfiguration(clientSecret: String? = nil) {
48+
configuration = .init(
49+
clientId: "clientId",
50+
oauth: .init(
51+
domain: "domain",
52+
scopes: [],
53+
signInRedirectURI: "app://",
54+
signOutRedirectURI: "app://"
55+
),
56+
clientSecret: clientSecret
57+
)
58+
}
59+
60+
/// Given: A HostedUI configuration without a client secret
61+
/// When: HostedUIRequestHelper.createTokenRequest is invoked with said configuration
62+
/// Then: A request is generated that does not include an Authorization header
63+
func testCreateTokenRequest_withoutClientSecret_shouldNotAddAuthorizationHeader() throws {
64+
let request = try HostedUIRequestHelper.createTokenRequest(
65+
configuration: configuration,
66+
result: result
67+
)
68+
69+
XCTAssertNil(request.value(forHTTPHeaderField: "Authorization"))
70+
}
71+
72+
/// Given: A HostedUI configuration that defines a client secret
73+
/// When: HostedUIRequestHelper.createTokenRequest is invoked with said configuration
74+
/// Then: A request is generated that includes an Authorization header and its value has an encoded version of the secret
75+
func testCreateTokenRequest_withClientSecret_shouldEncodeSecretAndAddAuthorizationHeader() throws {
76+
createConfiguration(clientSecret: "clientSecret")
77+
let request = try HostedUIRequestHelper.createTokenRequest(
78+
configuration: configuration,
79+
result: result
80+
)
81+
82+
let header = try XCTUnwrap(request.value(forHTTPHeaderField: "Authorization"))
83+
let encodedSecret = try XCTUnwrap(encodedSecret)
84+
XCTAssertEqual("Basic \(encodedSecret)", header)
85+
}
86+
87+
/// Given: A HostedUI configuration without a client secret
88+
/// When: HostedUIRequestHelper.createRefreshTokenRequest is invoked with said configuration
89+
/// Then: A request is generated that does not include an Authorization header
90+
func testCreateRefreshTokenRequest_withoutClientSecret_shouldNotAddAuthorizationHeader() throws {
91+
let request = try HostedUIRequestHelper.createRefreshTokenRequest(
92+
refreshToken: "refreshToken",
93+
configuration: configuration
94+
)
95+
96+
XCTAssertNil(request.value(forHTTPHeaderField: "Authorization"))
97+
}
98+
99+
/// Given: A HostedUI configuration that defines a client secret
100+
/// When: HostedUIRequestHelper.createRefreshTokenRequest is invoked with said configuration
101+
/// Then: A request is generated that includes an Authorization header and its value has an encoded version of the secret
102+
func testCreateRefreshTokenRequest_withClientSecret_shouldEncodeSecretAndAddAuthorizationHeader() throws {
103+
createConfiguration(clientSecret: "clientSecret")
104+
let request = try HostedUIRequestHelper.createRefreshTokenRequest(
105+
refreshToken: "refreshToken",
106+
configuration: configuration
107+
)
108+
109+
let header = try XCTUnwrap(request.value(forHTTPHeaderField: "Authorization"))
110+
let encodedSecret = try XCTUnwrap(encodedSecret)
111+
XCTAssertEqual("Basic \(encodedSecret)", header)
112+
}
113+
}

0 commit comments

Comments
 (0)