Stabilize iOS/watchOS/tvOS apps and add cross-platform audit remediation
This commit is contained in:
65
SharedCore/Tests/SharedCoreiOSTests/TokenSecurityTests.swift
Normal file
65
SharedCore/Tests/SharedCoreiOSTests/TokenSecurityTests.swift
Normal file
@@ -0,0 +1,65 @@
|
||||
import XCTest
|
||||
@testable import SharedCore
|
||||
|
||||
final class TokenSecurityTests: XCTestCase {
|
||||
func testSanitizeTokenRejectsEmptyAndRedactedValues() {
|
||||
XCTAssertNil(TokenSecurity.sanitizeToken(nil))
|
||||
XCTAssertNil(TokenSecurity.sanitizeToken(" "))
|
||||
XCTAssertNil(TokenSecurity.sanitizeToken("REDACTED_TOKEN"))
|
||||
XCTAssertEqual(TokenSecurity.sanitizeToken(" abc123 "), "abc123")
|
||||
}
|
||||
|
||||
func testSanitizeTokenNormalizesAuthorizationPrefixes() {
|
||||
XCTAssertEqual(TokenSecurity.sanitizeToken("Token abc123"), "abc123")
|
||||
XCTAssertEqual(TokenSecurity.sanitizeToken("bearer xyz789"), "xyz789")
|
||||
XCTAssertNil(TokenSecurity.sanitizeToken("Token "))
|
||||
}
|
||||
|
||||
func testContainsPotentialHardcodedTokenDetectsLongHexBlob() {
|
||||
let content = "private let token = \"0123456789abcdef0123456789abcdef\""
|
||||
XCTAssertTrue(TokenSecurity.containsPotentialHardcodedToken(in: content))
|
||||
}
|
||||
|
||||
func testJWTExpirationAndRotationWindow() throws {
|
||||
let now = Date(timeIntervalSince1970: 1_700_000_000)
|
||||
let expiration = now.addingTimeInterval(30 * 60)
|
||||
|
||||
let token = try makeJWT(exp: expiration)
|
||||
|
||||
XCTAssertEqual(TokenSecurity.jwtExpiration(token), expiration)
|
||||
XCTAssertFalse(TokenSecurity.isExpired(token, now: now))
|
||||
XCTAssertTrue(TokenSecurity.shouldRotate(token, now: now, rotationWindow: 60 * 60))
|
||||
}
|
||||
|
||||
func testExpiredJWTReturnsExpired() throws {
|
||||
let now = Date(timeIntervalSince1970: 1_700_000_000)
|
||||
let expiration = now.addingTimeInterval(-10)
|
||||
let token = try makeJWT(exp: expiration)
|
||||
|
||||
XCTAssertTrue(TokenSecurity.isExpired(token, now: now))
|
||||
}
|
||||
|
||||
func testMalformedTokenDoesNotCrashAndDoesNotTriggerRotation() {
|
||||
let malformed = "not-a-jwt"
|
||||
XCTAssertNil(TokenSecurity.jwtExpiration(malformed))
|
||||
XCTAssertFalse(TokenSecurity.isExpired(malformed))
|
||||
XCTAssertFalse(TokenSecurity.shouldRotate(malformed))
|
||||
}
|
||||
|
||||
private func makeJWT(exp: Date) throws -> String {
|
||||
let header = ["alg": "HS256", "typ": "JWT"]
|
||||
let payload = ["exp": Int(exp.timeIntervalSince1970)]
|
||||
|
||||
let headerData = try JSONSerialization.data(withJSONObject: header)
|
||||
let payloadData = try JSONSerialization.data(withJSONObject: payload)
|
||||
|
||||
return "\(base64URL(headerData)).\(base64URL(payloadData)).signature"
|
||||
}
|
||||
|
||||
private func base64URL(_ data: Data) -> String {
|
||||
data.base64EncodedString()
|
||||
.replacingOccurrences(of: "+", with: "-")
|
||||
.replacingOccurrences(of: "/", with: "_")
|
||||
.replacingOccurrences(of: "=", with: "")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user