diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index 3562610..f1e8625 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -12,6 +12,8 @@ 271E10821F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; 271E10831F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; 271E10851F90274A00B5033C /* JOSEHeaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10841F90274A00B5033C /* JOSEHeaderTests.swift */; }; + 271E10891F90334B00B5033C /* CompactJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */; }; + 271E108B1F9034B100B5033C /* CompactJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */; }; 273010FF1F33EABA00219C35 /* HMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273010FE1F33EABA00219C35 /* HMAC.swift */; }; 273011001F33EABA00219C35 /* HMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273010FE1F33EABA00219C35 /* HMAC.swift */; }; 273011011F33EABA00219C35 /* HMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273010FE1F33EABA00219C35 /* HMAC.swift */; }; @@ -69,6 +71,8 @@ /* Begin PBXFileReference section */ 271E107F1F90253300B5033C /* JWA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWA.swift; sourceTree = ""; }; 271E10841F90274A00B5033C /* JOSEHeaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JOSEHeaderTests.swift; sourceTree = ""; }; + 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactJSONEncoder.swift; sourceTree = ""; }; + 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactJSONDecoder.swift; sourceTree = ""; }; 273010FE1F33EABA00219C35 /* HMAC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HMAC.swift; sourceTree = ""; }; 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HMACCommonCrypto.swift; sourceTree = ""; }; 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HMACCryptoSwift.swift; sourceTree = ""; }; @@ -138,6 +142,8 @@ children = ( 277794041DF221F800573F3E /* ClaimSet.swift */, 2777940A1DF22BE400573F3E /* JOSEHeader.swift */, + 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */, + 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */, 520A71131C469F010005C709 /* Base64.swift */, 520A71141C469F010005C709 /* Claims.swift */, 520A71151C469F010005C709 /* Decode.swift */, @@ -445,12 +451,14 @@ 271E10801F90253300B5033C /* JWA.swift in Sources */, 273011161F34029900219C35 /* HMACCommonCrypto.swift in Sources */, 520A71181C469F010005C709 /* Claims.swift in Sources */, + 271E10891F90334B00B5033C /* CompactJSONEncoder.swift in Sources */, 520A711A1C469F010005C709 /* JWT.swift in Sources */, 520A71191C469F010005C709 /* Decode.swift in Sources */, 277794101DF22D0D00573F3E /* Encode.swift in Sources */, 2777940B1DF22BE400573F3E /* JOSEHeader.swift in Sources */, 277794051DF221F800573F3E /* ClaimSet.swift in Sources */, 273010FF1F33EABA00219C35 /* HMAC.swift in Sources */, + 271E108B1F9034B100B5033C /* CompactJSONDecoder.swift in Sources */, 520A71171C469F010005C709 /* Base64.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Sources/JWT/Base64.swift b/Sources/JWT/Base64.swift index c85719b..f6bb78e 100644 --- a/Sources/JWT/Base64.swift +++ b/Sources/JWT/Base64.swift @@ -12,7 +12,7 @@ func base64encode(_ input: Data) -> String { /// URI Safe base64 decode func base64decode(_ input: String) -> Data? { - let rem = input.characters.count % 4 + let rem = input.count % 4 var ending = "" if rem > 0 { diff --git a/Sources/JWT/CompactJSONDecoder.swift b/Sources/JWT/CompactJSONDecoder.swift new file mode 100644 index 0000000..1d29309 --- /dev/null +++ b/Sources/JWT/CompactJSONDecoder.swift @@ -0,0 +1,9 @@ +class CompactJSONDecoder: JSONDecoder { + override func decode(_ type: T.Type, from data: Data) throws -> T where T : Decodable { + guard let string = String(data: data, encoding: .ascii) else { + fatalError() + } + + return try super.decode(type, from: base64decode(string)!) + } +} diff --git a/Sources/JWT/CompactJSONEncoder.swift b/Sources/JWT/CompactJSONEncoder.swift new file mode 100644 index 0000000..c3e454f --- /dev/null +++ b/Sources/JWT/CompactJSONEncoder.swift @@ -0,0 +1,9 @@ +class CompactJSONEncoder: JSONEncoder { + override func encode(_ value: T) throws -> Data { + return try encodeString(value).data(using: .ascii) ?? Data() + } + + func encodeString(_ value: T) throws -> String { + return base64encode(try super.encode(value)) + } +} diff --git a/Sources/JWT/Encode.swift b/Sources/JWT/Encode.swift index fa716d1..3c5bb68 100644 --- a/Sources/JWT/Encode.swift +++ b/Sources/JWT/Encode.swift @@ -6,6 +6,8 @@ import Foundation - returns: The JSON web token as a String */ public func encode(claims: ClaimSet, algorithm: Algorithm, headers: [String: String]? = nil) -> String { + let encoder = CompactJSONEncoder() + func encodeJSON(_ payload: [String: Any]) -> String? { if let data = try? JSONSerialization.data(withJSONObject: payload) { return base64encode(data) @@ -20,7 +22,7 @@ public func encode(claims: ClaimSet, algorithm: Algorithm, headers: [String: Str } headers["alg"] = algorithm.description - let header = encodeJSON(headers)! + let header = try! encoder.encodeString(headers) let payload = encodeJSON(claims.claims)! let signingInput = "\(header).\(payload)" let signature = algorithm.sign(signingInput)