amplify-swift/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/ClientSecretConfigurationTe...

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)")
}
}
}