Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion JWTDecode/JWTDecode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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] {
Expand Down
12 changes: 6 additions & 6 deletions JWTDecode/JWTDecodeError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
}
Expand Down
16 changes: 16 additions & 0 deletions JWTDecodeTests/JWTDecodeSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand Down
Loading