diff --git a/JWTDecode/JWTDecode.swift b/JWTDecode/JWTDecode.swift index e9aceee..b4b0f24 100644 --- a/JWTDecode/JWTDecode.swift +++ b/JWTDecode/JWTDecode.swift @@ -201,7 +201,7 @@ private func base64UrlDecode(_ value: String) -> Data? { let padding = "".padding(toLength: Int(paddingLength), withPad: "=", startingAt: 0) base64 += padding } - return Data(base64Encoded: base64, options: .ignoreUnknownCharacters) + return Data(base64Encoded: base64) } private func decodeJWTPart(_ value: String) throws -> [String: any Sendable] { diff --git a/JWTDecode/JWTDecodeError.swift b/JWTDecode/JWTDecodeError.swift index d66a6b2..f08aa3a 100644 --- a/JWTDecode/JWTDecodeError.swift +++ b/JWTDecode/JWTDecodeError.swift @@ -29,12 +29,12 @@ public enum JWTDecodeError: LocalizedError, CustomDebugStringConvertible, Sendab /// - Important: You should avoid displaying the error description to the user, it's meant for **debugging** only. public var debugDescription: String { switch self { - case .invalidJSON(let value): - return "Failed to parse JSON from Base64URL value \(value)." - case .invalidPartCount(let jwt, let parts): - return "The JWT \(jwt) has \(parts) parts when it should have 3 parts." - case .invalidBase64URL(let value): - return "Failed to decode Base64URL value \(value)." + case .invalidJSON: + return "Failed to parse JSON from a Base64URL JWT part." + case .invalidPartCount(_, let parts): + return "The JWT has \(parts) parts when it should have 3 parts." + case .invalidBase64URL: + return "Failed to decode a Base64URL JWT part." case .claimDecodingFailed(let message): return "Failed to decode claim: \(message)" } diff --git a/JWTDecodeTests/JWTDecodeSpec.swift b/JWTDecodeTests/JWTDecodeSpec.swift index 14fa03c..4e19cd9 100644 --- a/JWTDecodeTests/JWTDecodeSpec.swift +++ b/JWTDecodeTests/JWTDecodeSpec.swift @@ -66,6 +66,13 @@ class JWTDecodeSpec: XCTestCase { } } + func testInvalidBase64WithIgnoredCharactersIsRejected() { + let jwtString = "eyJhbGciOiJIUzI1NiJ%.e30.SIGNATURE" + XCTAssertThrowsError(try decode(jwt: jwtString)) { error in + XCTAssertEqual(error as? JWTDecodeError, .invalidBase64URL("eyJhbGciOiJIUzI1NiJ%")) + } + } + func testRaiseExceptionWithInvalidJSONInJWT() { let jwtString = "HEADER.BODY.SIGNATURE" XCTAssertThrowsError(try decode(jwt: jwtString)) { error in @@ -80,6 +87,15 @@ class JWTDecodeSpec: XCTestCase { } } + func testErrorDescriptionsDoNotExposeJWTContents() { + let jwtString = "header.payload.signature" + let encodedPart = "eyJzdWIiOiJzZWNyZXQifQ" + + XCTAssertFalse(JWTDecodeError.invalidPartCount(jwtString, 3).localizedDescription.contains(jwtString)) + XCTAssertFalse(JWTDecodeError.invalidJSON(encodedPart).localizedDescription.contains(encodedPart)) + XCTAssertFalse(JWTDecodeError.invalidBase64URL(encodedPart).localizedDescription.contains(encodedPart)) + } + func testReturnHeader() { let jwtString = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWIifQ.xXcD7WOvUDHJ94E6aVHYgXdsJHLl2oW7Z" + "Xm4QpVvXnY"