291 lines
11 KiB
Swift
291 lines
11 KiB
Swift
//
|
|
// Copyright Amazon.com Inc. or its affiliates.
|
|
// All Rights Reserved.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
import Foundation
|
|
|
|
import XCTest
|
|
import AWSCognitoIdentity
|
|
@testable import Amplify
|
|
@testable import AWSCognitoAuthPlugin
|
|
@testable import AWSPluginsTestCommon
|
|
import AWSCognitoIdentityProvider
|
|
|
|
class ClientSecretConfigurationTests: XCTestCase {
|
|
|
|
let networkTimeout = TimeInterval(2)
|
|
var mockIdentityProvider: CognitoUserPoolBehavior!
|
|
var plugin: AWSCognitoAuthPlugin!
|
|
|
|
var initialState: AuthState {
|
|
AuthState.configured(
|
|
AuthenticationState.signedIn(
|
|
SignedInData(
|
|
signedInDate: Date(),
|
|
signInMethod: .apiBased(.userSRP),
|
|
cognitoUserPoolTokens: AWSCognitoUserPoolTokens.testData)),
|
|
AuthorizationState.sessionEstablished(AmplifyCredentials.testData))
|
|
}
|
|
|
|
override func setUp() {
|
|
plugin = AWSCognitoAuthPlugin()
|
|
|
|
let getId: MockIdentity.MockGetIdResponse = { _ in
|
|
return .init(identityId: "mockIdentityId")
|
|
}
|
|
|
|
let getCredentials: MockIdentity.MockGetCredentialsResponse = { _ in
|
|
let credentials = CognitoIdentityClientTypes.Credentials(accessKeyId: "accessKey",
|
|
expiration: Date(),
|
|
secretKey: "secret",
|
|
sessionToken: "session")
|
|
return .init(credentials: credentials, identityId: "responseIdentityID")
|
|
}
|
|
|
|
let mockIdentity = MockIdentity(
|
|
mockGetIdResponse: getId,
|
|
mockGetCredentialsResponse: getCredentials)
|
|
|
|
let environment = Defaults.makeDefaultAuthEnvironment(
|
|
identityPoolFactory: { mockIdentity },
|
|
userPoolFactory: { self.mockIdentityProvider })
|
|
|
|
let statemachine = Defaults.makeDefaultAuthStateMachine(
|
|
initialState: initialState,
|
|
identityPoolFactory: { mockIdentity },
|
|
userPoolFactory: { self.mockIdentityProvider })
|
|
|
|
plugin?.configure(
|
|
authConfiguration: Defaults.makeDefaultAuthConfigData(),
|
|
authEnvironment: environment,
|
|
authStateMachine: statemachine,
|
|
credentialStoreStateMachine: Defaults.makeDefaultCredentialStateMachine(),
|
|
hubEventHandler: MockAuthHubEventBehavior(),
|
|
analyticsHandler: MockAnalyticsHandler())
|
|
}
|
|
|
|
|
|
|
|
/// Test if client secret is used for reset password api
|
|
///
|
|
/// - Given: Given auth plugin with client secret present in the configuration
|
|
/// - When:
|
|
/// - Invoke reset password api
|
|
/// - Then:
|
|
/// - Plugin should pass the secret hash created with client secret
|
|
///
|
|
func testClientSecretWithResetPassword() async throws {
|
|
let codeDeliveryDetails = CognitoIdentityProviderClientTypes.CodeDeliveryDetailsType(
|
|
attributeName: "attribute",
|
|
deliveryMedium: .email,
|
|
destination: "Amplify@amazon.com"
|
|
)
|
|
mockIdentityProvider = MockIdentityProvider(
|
|
mockForgotPasswordOutputResponse: { request in
|
|
XCTAssertNotNil(request.secretHash)
|
|
return ForgotPasswordOutputResponse(codeDeliveryDetails: codeDeliveryDetails)
|
|
}
|
|
)
|
|
_ = try await plugin.resetPassword(for: "user", options: nil)
|
|
}
|
|
|
|
/// Test if client secret is used for confirmResetPassword api
|
|
///
|
|
/// - Given: Given auth plugin with client secret present in the configuration
|
|
/// - When:
|
|
/// - Invoke confirmResetPassword api
|
|
/// - Then:
|
|
/// - Plugin should pass the secret hash created with client secret
|
|
///
|
|
func testClientSecretWithConfirmResetPassword() async throws {
|
|
mockIdentityProvider = MockIdentityProvider(
|
|
mockConfirmForgotPasswordOutputResponse: { request in
|
|
XCTAssertNotNil(request.secretHash)
|
|
return try ConfirmForgotPasswordOutputResponse(httpResponse: MockHttpResponse.ok)
|
|
}
|
|
)
|
|
try await plugin.confirmResetPassword(
|
|
for: "username",
|
|
with: "newpassword",
|
|
confirmationCode: "code",
|
|
options: nil
|
|
)
|
|
}
|
|
|
|
/// Test if client secret is used for resendSignUpCode api
|
|
///
|
|
/// - Given: Given auth plugin with client secret present in the configuration
|
|
/// - When:
|
|
/// - Invoke resendSignUpCode api
|
|
/// - Then:
|
|
/// - Plugin should pass the secret hash created with client secret
|
|
///
|
|
func testClientSecretWithResendSignupCode() async throws {
|
|
|
|
let codeDeliveryDetails = CognitoIdentityProviderClientTypes.CodeDeliveryDetailsType(
|
|
attributeName: nil,
|
|
deliveryMedium: .email,
|
|
destination: nil
|
|
)
|
|
mockIdentityProvider = MockIdentityProvider(
|
|
mockResendConfirmationCodeOutputResponse: { request in
|
|
XCTAssertNotNil(request.secretHash)
|
|
return ResendConfirmationCodeOutputResponse(
|
|
codeDeliveryDetails: codeDeliveryDetails
|
|
)
|
|
}
|
|
)
|
|
|
|
let authCodeDeliveryDetails = try await plugin.resendSignUpCode(for: "username", options: nil)
|
|
guard case .email = authCodeDeliveryDetails.destination else {
|
|
XCTFail("Result should be .email for the destination of AuthCodeDeliveryDetails")
|
|
return
|
|
}
|
|
}
|
|
|
|
/// Test if client secret is used for signUp api
|
|
///
|
|
/// - Given: Given auth plugin with client secret present in the configuration
|
|
/// - When:
|
|
/// - Invoke signUp api
|
|
/// - Then:
|
|
/// - Plugin should pass the secret hash created with client secret
|
|
///
|
|
func testClientSecretWithSignUp() async throws {
|
|
|
|
self.mockIdentityProvider = MockIdentityProvider(
|
|
mockSignUpResponse: { request in
|
|
XCTAssertNotNil(request.secretHash)
|
|
return .init(
|
|
codeDeliveryDetails: .init(
|
|
attributeName: "some attribute",
|
|
deliveryMedium: .email,
|
|
destination: "random@random.com"),
|
|
userConfirmed: false,
|
|
userSub: "userId")
|
|
}
|
|
)
|
|
|
|
let result = try await self.plugin.signUp(
|
|
username: "jeffb",
|
|
password: "Valid&99",
|
|
options: nil)
|
|
|
|
guard case .confirmUser = result.nextStep else {
|
|
XCTFail("Result should be .confirmUser for next step")
|
|
return
|
|
}
|
|
}
|
|
|
|
/// Test if client secret is used for confirmSignUp api
|
|
///
|
|
/// - Given: Given auth plugin with client secret present in the configuration
|
|
/// - When:
|
|
/// - Invoke confirmSignUp api
|
|
/// - Then:
|
|
/// - Plugin should pass the secret hash created with client secret
|
|
///
|
|
func testClientSecretWithConfirmSignUp() async throws {
|
|
|
|
self.mockIdentityProvider = MockIdentityProvider(
|
|
mockConfirmSignUpResponse: { request in
|
|
XCTAssertNotNil(request.secretHash)
|
|
return .init()
|
|
}
|
|
)
|
|
|
|
_ = try await self.plugin.confirmSignUp(
|
|
for: "someuser",
|
|
confirmationCode: "code",
|
|
options: nil
|
|
)
|
|
}
|
|
|
|
/// Test if client secret is used for revokeToken api
|
|
///
|
|
/// - Given: Given auth plugin with client secret present in the configuration
|
|
/// - When:
|
|
/// - Invoke signOut api
|
|
/// - Then:
|
|
/// - Plugin should pass the secret hash created with client secret
|
|
///
|
|
func testClientSecretWithRevokeToken() async {
|
|
self.mockIdentityProvider = MockIdentityProvider(
|
|
mockRevokeTokenResponse: { request in
|
|
XCTAssertNotNil(request.clientSecret)
|
|
return .testData
|
|
}, mockGlobalSignOutResponse: { _ in
|
|
return .testData
|
|
})
|
|
guard let result = await plugin.signOut() as? AWSCognitoSignOutResult,
|
|
case .complete = result else {
|
|
XCTFail("Did not return complete signOut")
|
|
return
|
|
}
|
|
}
|
|
|
|
/// Test if client secret is used for initiateAuth, respondToAuthChallenge api
|
|
///
|
|
/// - Given: Given auth plugin with client secret present in the configuration
|
|
/// - When:
|
|
/// - Invoke signOut api
|
|
/// - Then:
|
|
/// - Plugin should pass the secret hash created with client secret
|
|
///
|
|
func testClientSecretWithInitiateAuth() async {
|
|
|
|
self.mockIdentityProvider = MockIdentityProvider(
|
|
mockRevokeTokenResponse: { request in
|
|
XCTAssertNotNil(request.clientSecret)
|
|
return .testData
|
|
}, mockInitiateAuthResponse: { request in
|
|
XCTAssertNotNil(request.authParameters?["SECRET_HASH"])
|
|
return InitiateAuthOutputResponse(
|
|
authenticationResult: .none,
|
|
challengeName: .passwordVerifier,
|
|
challengeParameters: InitiateAuthOutputResponse.validChalengeParams,
|
|
session: "someSession")
|
|
|
|
}, mockGlobalSignOutResponse: { _ in
|
|
return .testData
|
|
|
|
}, mockRespondToAuthChallengeResponse: { request in
|
|
XCTAssertNotNil(request.challengeResponses?["SECRET_HASH"])
|
|
return RespondToAuthChallengeOutputResponse(
|
|
authenticationResult: .init(
|
|
accessToken: Defaults.validAccessToken,
|
|
expiresIn: 300,
|
|
idToken: "idToken",
|
|
newDeviceMetadata: nil,
|
|
refreshToken: "refreshToken",
|
|
tokenType: ""),
|
|
challengeName: .none,
|
|
challengeParameters: [:],
|
|
session: "session")
|
|
})
|
|
|
|
_ = await plugin.signOut()
|
|
|
|
let pluginOptions = AWSAuthSignInOptions(validationData: ["somekey": "somevalue"],
|
|
metadata: ["somekey": "somevalue"])
|
|
let options = AuthSignInRequest.Options(pluginOptions: pluginOptions)
|
|
|
|
do {
|
|
let result = try await plugin.signIn(
|
|
username: "username",
|
|
password: "password",
|
|
options: options)
|
|
guard case .done = result.nextStep else {
|
|
XCTFail("Result should be .done for next step")
|
|
return
|
|
}
|
|
XCTAssertTrue(result.isSignedIn, "Signin result should be complete")
|
|
} catch {
|
|
XCTFail("Received failure with error \(error)")
|
|
}
|
|
}
|
|
}
|