Skip to content

Commit

Permalink
chore(tests): Adding more AWSCognitoAuthPlugin tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ruisebas committed Sep 7, 2023
1 parent 070a273 commit 85b2842
Show file tree
Hide file tree
Showing 13 changed files with 1,456 additions and 182 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@
BlueprintName = "AWSCognitoAuthPluginUnitTests"
ReferencedContainer = "container:">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "EscapeHatchTests">
</Test>
</SkippedTests>
</TestableReference>
<TestableReference
skipped = "NO">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,24 +76,6 @@ public struct AWSAuthCognitoSession: AuthSession,

}

/// Internal Helpers for managing session tokens
internal extension AWSAuthCognitoSession {
func areTokensExpiring(in seconds: TimeInterval? = nil) -> Bool {

guard let tokens = try? userPoolTokensResult.get(),
let idTokenClaims = try? AWSAuthService().getTokenClaims(tokenString: tokens.idToken).get(),
let accessTokenClaims = try? AWSAuthService().getTokenClaims(tokenString: tokens.idToken).get(),
let idTokenExpiration = idTokenClaims["exp"]?.doubleValue,
let accessTokenExpiration = accessTokenClaims["exp"]?.doubleValue else {
return true
}

// If the session expires < X minutes return it
return (Date(timeIntervalSince1970: idTokenExpiration).compare(Date(timeIntervalSinceNow: seconds ?? 0)) == .orderedDescending &&
Date(timeIntervalSince1970: accessTokenExpiration).compare(Date(timeIntervalSinceNow: seconds ?? 0)) == .orderedDescending)
}
}

extension AWSAuthCognitoSession: Equatable {
public static func == (lhs: AWSAuthCognitoSession, rhs: AWSAuthCognitoSession) -> Bool {
switch (lhs.getCognitoTokens(), rhs.getCognitoTokens()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ public struct AWSCognitoUserPoolTokens: AuthCognitoTokens {
case (.some(let idTokenValue), .none):
expirationDoubleValue = idTokenValue
case (.none, .none):
expirationDoubleValue = 0
expirationDoubleValue = Date().timeIntervalSince1970
}

self.expiration = Date().addingTimeInterval(TimeInterval((expirationDoubleValue ?? 0)))
self.expiration = Date(timeIntervalSince1970: TimeInterval(expirationDoubleValue))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,6 @@ struct AuthCognitoSignedOutSessionHelper {
return authSession
}

/// Guest/SignedOut session with any unhandled error
///
/// The unhandled error is passed as identityId and aws credentials result. UserSub and Cognito Tokens will still
/// have signOut error.
///
/// - Parameter error: Unhandled error
/// - Returns: Session will have isSignedIn = false
private static func makeSignedOutSession(withUnhandledError error: AuthError) -> AWSAuthCognitoSession {

let identityIdError = error
let awsCredentialsError = error

let tokensError = makeCognitoTokensSignedOutError()

let authSession = AWSAuthCognitoSession(isSignedIn: false,
identityIdResult: .failure(identityIdError),
awsCredentialsResult: .failure(awsCredentialsError),
cognitoTokensResult: .failure(tokensError))
return authSession
}

/// Guest/SignOut session when the guest access is not enabled.
/// - Returns: Session with isSignedIn = false
static func makeSessionWithNoGuestAccess() -> AWSAuthCognitoSession {
Expand All @@ -68,26 +47,6 @@ struct AuthCognitoSignedOutSessionHelper {
return authSession
}

private static func makeOfflineSignedOutSession() -> AWSAuthCognitoSession {
let identityIdError = AuthError.service(
AuthPluginErrorConstants.identityIdOfflineError.errorDescription,
AuthPluginErrorConstants.identityIdOfflineError.recoverySuggestion,
AWSCognitoAuthError.network)

let awsCredentialsError = AuthError.service(
AuthPluginErrorConstants.awsCredentialsOfflineError.errorDescription,
AuthPluginErrorConstants.awsCredentialsOfflineError.recoverySuggestion,
AWSCognitoAuthError.network)

let tokensError = makeCognitoTokensSignedOutError()

let authSession = AWSAuthCognitoSession(isSignedIn: false,
identityIdResult: .failure(identityIdError),
awsCredentialsResult: .failure(awsCredentialsError),
cognitoTokensResult: .failure(tokensError))
return authSession
}

/// Guest/SignedOut session with couldnot retreive either aws credentials or identity id.
/// - Returns: Session will have isSignedIn = false
private static func makeSignedOutSessionWithServiceIssue() -> AWSAuthCognitoSession {
Expand All @@ -109,13 +68,6 @@ struct AuthCognitoSignedOutSessionHelper {
return authSession
}

private static func makeUserSubSignedOutError() -> AuthError {
let userSubError = AuthError.signedOut(
AuthPluginErrorConstants.userSubSignOutError.errorDescription,
AuthPluginErrorConstants.userSubSignOutError.recoverySuggestion)
return userSubError
}

private static func makeCognitoTokensSignedOutError() -> AuthError {
let tokensError = AuthError.signedOut(
AuthPluginErrorConstants.cognitoTokensSignOutError.errorDescription,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class HostedUIASWebAuthenticationSession: NSObject, HostedUISessionBehavior {
callback: @escaping (Result<[URLQueryItem], HostedUIError>) -> Void) {
#if os(iOS) || os(macOS)
self.webPresentation = presentationAnchor
let aswebAuthenticationSession = ASWebAuthenticationSession(
let aswebAuthenticationSession = createAuthenticationSession(
url: url,
callbackURLScheme: callbackScheme,
completionHandler: { url, error in
Expand Down Expand Up @@ -58,6 +58,16 @@ class HostedUIASWebAuthenticationSession: NSObject, HostedUISessionBehavior {
}

#if os(iOS) || os(macOS)
var authenticationSessionFactory = ASWebAuthenticationSession.init(url:callbackURLScheme:completionHandler:)

private func createAuthenticationSession(
url: URL,
callbackURLScheme: String?,
completionHandler: @escaping ASWebAuthenticationSession.CompletionHandler
) -> ASWebAuthenticationSession {
return authenticationSessionFactory(url, callbackURLScheme, completionHandler)
}

private func convertHostedUIError(_ error: Error) -> HostedUIError {
if let asWebAuthError = error as? ASWebAuthenticationSessionError {
switch asWebAuthError.code {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class MigrateLegacyCredentialStoreTests: XCTestCase {
let action = MigrateLegacyCredentialStore()
await action.execute(withDispatcher: MockDispatcher { _ in }, environment: environment)

await waitForExpectations(timeout: 0.1)
await fulfillment(of: [saveCredentialHandlerInvoked], timeout: 0.1)
}

/// Test is responsible for making sure that the legacy credential store clearing up is getting called for user pool and identity pool
Expand Down Expand Up @@ -115,8 +115,109 @@ class MigrateLegacyCredentialStoreTests: XCTestCase {
let action = MigrateLegacyCredentialStore()
await action.execute(withDispatcher: MockDispatcher { _ in }, environment: environment)

await waitForExpectations(timeout: 0.1)

await fulfillment(of: [migrationCompletionInvoked], timeout: 0.1)
}

func testInvalidEnvironment() async {
let expectation = expectation(description: "noEnvironment")
let action = MigrateLegacyCredentialStore()
await action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? CredentialStoreEvent,
case let .throwError(error) = event.eventType else {
XCTFail("Expected failure due to no CredentialEnvironment")
expectation.fulfill()
return
}

XCTAssertEqual(error, .configuration(message: AuthPluginErrorConstants.configurationError))
expectation.fulfill()
},
environment: MockInvalidEnvironment()
)
await fulfillment(of: [expectation], timeout: 1)
}

func testNoUserPoolWithoutLoginsTokens() async {
let expectation = expectation(description: "noUserPoolTokens")
let action = MigrateLegacyCredentialStore()
await action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? CredentialStoreEvent,
case .loadCredentialStore(let type) = event.eventType else {
XCTFail("Expected .loadCredentialStore")
expectation.fulfill()
return
}
XCTAssertEqual(type, .amplifyCredentials)
expectation.fulfill()
},
environment: CredentialEnvironment(
authConfiguration: .identityPools(.testData),
credentialStoreEnvironment: BasicCredentialStoreEnvironment(
amplifyCredentialStoreFactory: {
MockAmplifyCredentialStoreBehavior(
saveCredentialHandler: { codableCredentials in
guard let amplifyCredentials = codableCredentials as? AmplifyCredentials,
case .identityPoolOnly(_, let credentials) = amplifyCredentials else {
XCTFail("Expected .identityPoolOnly")
return
}
XCTAssertFalse(credentials.sessionToken.isEmpty)
}
)
},
legacyKeychainStoreFactory: { _ in
MockKeychainStoreBehavior(data: "hostedUI")
}),
logger: MigrateLegacyCredentialStore.log
)
)
await fulfillment(of: [expectation], timeout: 1)
}

func testNoUserPoolWithLoginsTokens() async {
let expectation = expectation(description: "noUserPoolTokens")
let action = MigrateLegacyCredentialStore()
await action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? CredentialStoreEvent,
case .loadCredentialStore(let type) = event.eventType else {
XCTFail("Expected .loadCredentialStore")
expectation.fulfill()
return
}
XCTAssertEqual(type, .amplifyCredentials)
expectation.fulfill()
},
environment: CredentialEnvironment(
authConfiguration: .identityPools(.testData),
credentialStoreEnvironment: BasicCredentialStoreEnvironment(
amplifyCredentialStoreFactory: {
MockAmplifyCredentialStoreBehavior(
saveCredentialHandler: { codableCredentials in
guard let amplifyCredentials = codableCredentials as? AmplifyCredentials,
case .identityPoolWithFederation(let token, _, _) = amplifyCredentials else {
XCTFail("Expected .identityPoolWithFederation")
return
}

XCTAssertEqual(token.token, "token")
XCTAssertEqual(token.provider.userPoolProviderName, "provider")
}
)
},
legacyKeychainStoreFactory: { _ in
let data = try! JSONEncoder().encode([
"provider": "token"
])
return MockKeychainStoreBehavior(
data: String(decoding: data, as: UTF8.self)
)
}),
logger: action.log
)
)
await fulfillment(of: [expectation], timeout: 1)
}
}
Loading

0 comments on commit 85b2842

Please sign in to comment.