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 6, 2023
1 parent 070a273 commit 84f727d
Show file tree
Hide file tree
Showing 4 changed files with 444 additions and 24 deletions.
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
@@ -0,0 +1,283 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Amplify
@testable import AWSCognitoAuthPlugin
import AWSCognitoIdentityProvider
import AWSPluginsCore
import XCTest

class RefreshHostedUITokensTests: XCTestCase {
var mockHostedUIResult: Result<[URLQueryItem], HostedUIError>!
var mockTokenResult = ["id_token": AWSCognitoUserPoolTokens.testData.idToken,
"access_token": AWSCognitoUserPoolTokens.testData.accessToken,
"refresh_token": AWSCognitoUserPoolTokens.testData.refreshToken,
"expires_in": 10] as [String: Any]
var mockState = "someState"
var mockProof = "someProof"
var mockJson: Data!

override func setUp() {
mockJson = try! JSONSerialization.data(withJSONObject: mockTokenResult)
MockURLProtocol.requestHandler = { _ in
return (HTTPURLResponse(), self.mockJson)
}
}

func testValidSuccessfulResponse() async {
let expectation = expectation(description: "refreshHostedUITokens")
let action = RefreshHostedUITokens(existingSignedIndata: .testData)
action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? RefreshSessionEvent,
case .refreshIdentityInfo(let data, _) = event.eventType else {
XCTFail("Failed to refresh tokens")
expectation.fulfill()
return
}

XCTAssertEqual(data.cognitoUserPoolTokens.idToken, self.mockTokenResult["id_token"] as? String)
XCTAssertEqual(data.cognitoUserPoolTokens.accessToken, self.mockTokenResult["access_token"] as? String)
XCTAssertEqual(data.cognitoUserPoolTokens.refreshToken, self.mockTokenResult["refresh_token"] as? String)
expectation.fulfill()
},
environment: Defaults.makeDefaultAuthEnvironment(
userPoolFactory: identityProviderFactory,
hostedUIEnvironment: hostedUIEnvironment
)
)

await fulfillment(of: [expectation], timeout: 1)
}

func testServiceError() async {
let expectedError = HostedUIError.serviceMessage("Something went wrong")
MockURLProtocol.requestHandler = { _ in
throw expectedError
}

let expectation = expectation(description: "refreshHostedUITokens")
let action = RefreshHostedUITokens(existingSignedIndata: .testData)
action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? RefreshSessionEvent,
case let .throwError(error) = event.eventType else {
XCTFail("Expected failure due to Service Error")
expectation.fulfill()
return
}

XCTAssertEqual(error, .service(expectedError))
expectation.fulfill()
},
environment: Defaults.makeDefaultAuthEnvironment(
userPoolFactory: identityProviderFactory,
hostedUIEnvironment: hostedUIEnvironment
)
)

await fulfillment(of: [expectation], timeout: 1)
}

func testEmptyData() async {
MockURLProtocol.requestHandler = { _ in
return (HTTPURLResponse(), Data())
}

let expectation = expectation(description: "refreshHostedUITokens")
let action = RefreshHostedUITokens(existingSignedIndata: .testData)
action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? RefreshSessionEvent,
case let .throwError(error) = event.eventType else {
XCTFail("Expected failure due to Invalid Tokens")
expectation.fulfill()
return
}

guard case .service(let serviceError) = error else {
XCTFail("Expected FetchSessionError.service, got \(error)")
expectation.fulfill()
return
}


XCTAssertEqual((serviceError as NSError).code, NSPropertyListReadCorruptError)
expectation.fulfill()
},
environment: Defaults.makeDefaultAuthEnvironment(
userPoolFactory: identityProviderFactory,
hostedUIEnvironment: hostedUIEnvironment
)
)

await fulfillment(of: [expectation], timeout: 1)
}

func testInvalidTokens() async {
let result: [String: Any] = [
"key": "value"
]
MockURLProtocol.requestHandler = { _ in
return (HTTPURLResponse(), try! JSONSerialization.data(withJSONObject: result))
}

let expectation = expectation(description: "refreshHostedUITokens")
let action = RefreshHostedUITokens(existingSignedIndata: .testData)
action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? RefreshSessionEvent,
case let .throwError(error) = event.eventType else {
XCTFail("Expected failure due to Invalid Tokens")
expectation.fulfill()
return
}


XCTAssertEqual(error, .invalidTokens)
expectation.fulfill()
},
environment: Defaults.makeDefaultAuthEnvironment(
userPoolFactory: identityProviderFactory,
hostedUIEnvironment: hostedUIEnvironment
)
)

await fulfillment(of: [expectation], timeout: 1)
}

func testErrorResponse() async {
let result: [String: Any] = [
"error": "Error.",
"error_description": "Something went wrong"
]
MockURLProtocol.requestHandler = { _ in
return (HTTPURLResponse(), try! JSONSerialization.data(withJSONObject: result))
}

let expectation = expectation(description: "refreshHostedUITokens")
let action = RefreshHostedUITokens(existingSignedIndata: .testData)
action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? RefreshSessionEvent,
case let .throwError(error) = event.eventType else {
XCTFail("Expected failure due to Invalid Tokens")
expectation.fulfill()
return
}

guard case .service(let serviceError) = error,
case .serviceMessage(let errorMessage) = serviceError as? HostedUIError else {
XCTFail("Expected HostedUIError.serviceMessage, got \(error)")
expectation.fulfill()
return
}


XCTAssertEqual(errorMessage, "Error. Something went wrong")
expectation.fulfill()
},
environment: Defaults.makeDefaultAuthEnvironment(
userPoolFactory: identityProviderFactory,
hostedUIEnvironment: hostedUIEnvironment
)
)

await fulfillment(of: [expectation], timeout: 1)
}

func testNoHostedUIEnvironment() async {
let expectation = expectation(description: "noHostedUIEnvironment")
let action = RefreshHostedUITokens(existingSignedIndata: .testData)
action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? RefreshSessionEvent,
case let .throwError(error) = event.eventType else {
XCTFail("Expected failure due to no HostedUIEnvironment")
expectation.fulfill()
return
}

XCTAssertEqual(error, .noUserPool)
expectation.fulfill()
},
environment: Defaults.makeDefaultAuthEnvironment(
userPoolFactory: identityProviderFactory,
hostedUIEnvironment: nil
)
)

await fulfillment(of: [expectation], timeout: 1)
}

func testNoUserPoolEnvironment() async {
let expectation = expectation(description: "noUserPoolEnvironment")
let action = RefreshHostedUITokens(existingSignedIndata: .testData)
action.execute(
withDispatcher: MockDispatcher { event in
guard let event = event as? RefreshSessionEvent,
case let .throwError(error) = event.eventType else {
XCTFail("Expected failure due to no UserPoolEnvironment")
expectation.fulfill()
return
}

XCTAssertNotNil(error)
XCTAssertEqual(error, .noUserPool)
expectation.fulfill()
},
environment: MockInvalidEnvironment()
)

await fulfillment(of: [expectation], timeout: 1)
}

private var hostedUIEnvironment: HostedUIEnvironment {
BasicHostedUIEnvironment(
configuration: .init(
clientId: "clientId",
oauth: .init(
domain: "cognitodomain",
scopes: ["name"],
signInRedirectURI: "myapp://",
signOutRedirectURI: "myapp://"
)
),
hostedUISessionFactory: sessionFactory,
urlSessionFactory: urlSessionMock,
randomStringFactory: mockRandomString
)
}

private func identityProviderFactory() throws -> CognitoUserPoolBehavior {
return MockIdentityProvider(
mockInitiateAuthResponse: { _ in
return InitiateAuthOutputResponse(
authenticationResult: .init(
accessToken: "accessTokenNew",
expiresIn: 100,
idToken: "idTokenNew",
refreshToken: "refreshTokenNew")
)
}
)
}

private func urlSessionMock() -> URLSession {
let configuration = URLSessionConfiguration.ephemeral
configuration.protocolClasses = [MockURLProtocol.self]
return URLSession(configuration: configuration)
}

private func sessionFactory() -> HostedUISessionBehavior {
MockHostedUISession(result: mockHostedUIResult)
}

private func mockRandomString() -> RandomStringBehavior {
return MockRandomStringGenerator(mockString: mockState, mockUUID: mockState)
}
}
Loading

0 comments on commit 84f727d

Please sign in to comment.