From ec727f11324b7d2936aad8c22ff19a0649cb3fe6 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Thu, 3 Aug 2017 18:04:28 -0700 Subject: [PATCH 01/62] feat: Support conditional CommonCrypto --- JSONWebToken.podspec | 1 + JWT.xcodeproj/project.pbxproj | 22 ++++++++++++++++ Package.swift | 3 ++- Sources/HMAC.swift | 7 ++++++ Sources/HMACCommonCrypto.swift | 46 ++++++++++++++++++++++++++++++++++ Sources/HMACCryptoSwift.swift | 28 +++++++++++++++++++++ Sources/JWT.swift | 18 ++++--------- 7 files changed, 111 insertions(+), 14 deletions(-) create mode 100644 Sources/HMAC.swift create mode 100644 Sources/HMACCommonCrypto.swift create mode 100644 Sources/HMACCryptoSwift.swift diff --git a/JSONWebToken.podspec b/JSONWebToken.podspec index 2bf5306..fd86d92 100644 --- a/JSONWebToken.podspec +++ b/JSONWebToken.podspec @@ -14,4 +14,5 @@ Pod::Spec.new do |spec| spec.requires_arc = true spec.dependency 'CryptoSwift', '~> 0.6.1' spec.module_name = 'JWT' + spec.exclude_files = ['Sources/HMACCommonCrypto.swift'] end diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index 4158229..eb97184 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -7,6 +7,14 @@ objects = { /* Begin PBXBuildFile section */ + 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 */; }; + 273011021F33EABA00219C35 /* HMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273010FE1F33EABA00219C35 /* HMAC.swift */; }; + 2730110A1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */; }; + 2730110B1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */; }; + 2730110C1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */; }; + 2730110D1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */; }; 2734C6A81D88001F00BFF9F1 /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66725DAB1C59202E00FC32F4 /* CryptoSwift.framework */; }; 2734C6A91D88002900BFF9F1 /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66725DAB1C59202E00FC32F4 /* CryptoSwift.framework */; }; 2734C6AA1D88003000BFF9F1 /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66725DAB1C59202E00FC32F4 /* CryptoSwift.framework */; }; @@ -79,6 +87,9 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 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 = ""; }; 277794041DF221F800573F3E /* ClaimSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClaimSet.swift; sourceTree = ""; }; 2777940A1DF22BE400573F3E /* JOSEHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JOSEHeader.swift; sourceTree = ""; }; 2777940F1DF22D0D00573F3E /* Encode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Encode.swift; sourceTree = ""; }; @@ -218,6 +229,9 @@ 520A71151C469F010005C709 /* Decode.swift */, 2777940F1DF22D0D00573F3E /* Encode.swift */, 520A71161C469F010005C709 /* JWT.swift */, + 273010FE1F33EABA00219C35 /* HMAC.swift */, + 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */, + 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */, ); path = Sources; sourceTree = ""; @@ -481,7 +495,9 @@ 277794101DF22D0D00573F3E /* Encode.swift in Sources */, 2777940B1DF22BE400573F3E /* JOSEHeader.swift in Sources */, 277794051DF221F800573F3E /* ClaimSet.swift in Sources */, + 273010FF1F33EABA00219C35 /* HMAC.swift in Sources */, 520A71171C469F010005C709 /* Base64.swift in Sources */, + 2730110A1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -503,7 +519,9 @@ 277794111DF22D0D00573F3E /* Encode.swift in Sources */, 2777940C1DF22BE400573F3E /* JOSEHeader.swift in Sources */, 277794061DF221F800573F3E /* ClaimSet.swift in Sources */, + 273011001F33EABA00219C35 /* HMAC.swift in Sources */, CD9B621A1C7753D8005D4844 /* Base64.swift in Sources */, + 2730110B1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -517,7 +535,9 @@ 277794121DF22D0D00573F3E /* Encode.swift in Sources */, 2777940D1DF22BE400573F3E /* JOSEHeader.swift in Sources */, 277794071DF221F800573F3E /* ClaimSet.swift in Sources */, + 273011011F33EABA00219C35 /* HMAC.swift in Sources */, CD9B622C1C7753EC005D4844 /* Base64.swift in Sources */, + 2730110C1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -531,7 +551,9 @@ 277794131DF22D0D00573F3E /* Encode.swift in Sources */, 2777940E1DF22BE400573F3E /* JOSEHeader.swift in Sources */, 277794081DF221F800573F3E /* ClaimSet.swift in Sources */, + 273011021F33EABA00219C35 /* HMAC.swift in Sources */, CD9B623E1C7753FB005D4844 /* Base64.swift in Sources */, + 2730110D1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Package.swift b/Package.swift index f90189c..e6f794a 100644 --- a/Package.swift +++ b/Package.swift @@ -4,5 +4,6 @@ let package = Package( name: "JWT", dependencies: [ .Package(url: "https://github.com/krzyzanowskim/CryptoSwift", versions: Version(0, 6, 1) ..< Version(0, 7, 0)), - ] + ], + exclude: ["Sources/HMACCommonCrypto.swift"] ) diff --git a/Sources/HMAC.swift b/Sources/HMAC.swift new file mode 100644 index 0000000..2e9c66a --- /dev/null +++ b/Sources/HMAC.swift @@ -0,0 +1,7 @@ +import Foundation + +enum HMACAlgorithm { + case sha256 + case sha384 + case sha512 +} diff --git a/Sources/HMACCommonCrypto.swift b/Sources/HMACCommonCrypto.swift new file mode 100644 index 0000000..a144ccb --- /dev/null +++ b/Sources/HMACCommonCrypto.swift @@ -0,0 +1,46 @@ +import Foundation +import CommonCrypto + + +extension HMACAlgorithm { + var commonCryptoAlgorithm: CCHmacAlgorithm { + switch self { + case .sha256: + return CCHmacAlgorithm(kCCHmacAlgSHA256) + case .sha384: + return CCHmacAlgorithm(kCCHmacAlgSHA384) + case .sha512: + return CCHmacAlgorithm(kCCHmacAlgSHA512) + } + } + + var commonCryptoDigestLength: Int32 { + switch self { + case .sha256: + return CC_SHA256_DIGEST_LENGTH + case .sha384: + return CC_SHA384_DIGEST_LENGTH + case .sha512: + return CC_SHA512_DIGEST_LENGTH + } + } +} + + +func hmac(algorithm: HMACAlgorithm, key: Data, message: Data) -> Data { + let context = UnsafeMutablePointer.allocate(capacity: 1) + defer { context.deallocate(capacity: 1) } + + key.withUnsafeBytes() { (buffer: UnsafePointer) in + CCHmacInit(context, algorithm.commonCryptoAlgorithm, buffer, size_t(key.count)) + } + + message.withUnsafeBytes { (buffer: UnsafePointer) in + CCHmacUpdate(context, buffer, size_t(message.count)) + } + + var hmac = Array(repeating: 0, count: Int(algorithm.commonCryptoDigestLength)) + CCHmacFinal(context, &hmac) + + return Data(hmac) +} diff --git a/Sources/HMACCryptoSwift.swift b/Sources/HMACCryptoSwift.swift new file mode 100644 index 0000000..401a803 --- /dev/null +++ b/Sources/HMACCryptoSwift.swift @@ -0,0 +1,28 @@ +import Foundation +import CryptoSwift + + +extension HMACAlgorithm { + var cryptoSwiftVariant: HMAC.Variant { + switch self { + case .sha256: + return .sha256 + case .sha384: + return .sha384 + case .sha512: + return .sha512 + } + } +} + + +func hmac(algorithm: HMACAlgorithm, key: Data, message: Data) -> Data { + let mac = HMAC(key: key.bytes, variant: algorithm.cryptoSwiftVariant) + let result: [UInt8] + do { + result = try mac.authenticate(message.bytes) + } catch { + result = [] + } + return Data(bytes: result) +} diff --git a/Sources/JWT.swift b/Sources/JWT.swift index 3b3e4a3..b412da3 100644 --- a/Sources/JWT.swift +++ b/Sources/JWT.swift @@ -1,5 +1,4 @@ import Foundation -import CryptoSwift public typealias Payload = [String: Any] @@ -32,16 +31,9 @@ public enum Algorithm: CustomStringConvertible { /// Sign a message using the algorithm func sign(_ message: String) -> String { - func signHS(_ key: Data, variant: CryptoSwift.HMAC.Variant) -> String { + func signHS(_ key: Data, algorithm: HMACAlgorithm) -> String { let messageData = message.data(using: String.Encoding.utf8, allowLossyConversion: false)! - let mac = HMAC(key: key.bytes, variant: variant) - let result: [UInt8] - do { - result = try mac.authenticate(messageData.bytes) - } catch { - result = [] - } - return base64encode(Data(bytes: result)) + return base64encode(hmac(algorithm: algorithm, key: key, message: messageData)) } switch self { @@ -49,13 +41,13 @@ public enum Algorithm: CustomStringConvertible { return "" case .hs256(let key): - return signHS(key, variant: .sha256) + return signHS(key, algorithm: .sha256) case .hs384(let key): - return signHS(key, variant: .sha384) + return signHS(key, algorithm: .sha384) case .hs512(let key): - return signHS(key, variant: .sha512) + return signHS(key, algorithm: .sha512) } } From 7451fcfaeb4dfc56403570f759e6bf3290db0f7c Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 4 Aug 2017 09:01:50 -0700 Subject: [PATCH 02/62] feat: Use CommonCrypto on Apple platforms for SwiftPM --- Package.swift | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index e6f794a..7e6ad13 100644 --- a/Package.swift +++ b/Package.swift @@ -1,9 +1,24 @@ import PackageDescription + +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) +let package = Package( + name: "JWT", + dependencies: [ + .Package(url: "https://github.com/kylef-archive/CommonCrypto.git", majorVersion: 1), + ], + exclude: [ + "Sources/HMACCryptoSwift.swift", + ] +) +#else let package = Package( name: "JWT", dependencies: [ - .Package(url: "https://github.com/krzyzanowskim/CryptoSwift", versions: Version(0, 6, 1) ..< Version(0, 7, 0)), + .Package(url: "https://github.com/krzyzanowskim/CryptoSwift", majorVersion: 0, minor: 6), ], - exclude: ["Sources/HMACCommonCrypto.swift"] + exclude: [ + "Sources/HMACCommonCrypto.swift", + ] ) +#endif From 558eaf1ca7ac41ae11747c4c3d4057997d93913f Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 4 Aug 2017 10:14:45 -0700 Subject: [PATCH 03/62] fix(Package): Add `.git` extension to CryptoSwift Fixes #63 --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 7e6ad13..eb6f28b 100644 --- a/Package.swift +++ b/Package.swift @@ -15,7 +15,7 @@ let package = Package( let package = Package( name: "JWT", dependencies: [ - .Package(url: "https://github.com/krzyzanowskim/CryptoSwift", majorVersion: 0, minor: 6), + .Package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", majorVersion: 0, minor: 6), ], exclude: [ "Sources/HMACCommonCrypto.swift", From fcf2f1286ff9b59d21995e5940aac5f157b15f27 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 4 Aug 2017 09:18:35 -0700 Subject: [PATCH 04/62] feat: Use CommonCrypto in JWT Pod --- CommonCrypto/module.modulemap | 4 ++++ CommonCrypto/shim.h | 1 + JSONWebToken.podspec | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 CommonCrypto/module.modulemap create mode 100644 CommonCrypto/shim.h diff --git a/CommonCrypto/module.modulemap b/CommonCrypto/module.modulemap new file mode 100644 index 0000000..b70f7d6 --- /dev/null +++ b/CommonCrypto/module.modulemap @@ -0,0 +1,4 @@ +module CommonCrypto [system] { + header "shim.h" + export * +} diff --git a/CommonCrypto/shim.h b/CommonCrypto/shim.h new file mode 100644 index 0000000..c332624 --- /dev/null +++ b/CommonCrypto/shim.h @@ -0,0 +1 @@ +#include diff --git a/JSONWebToken.podspec b/JSONWebToken.podspec index fd86d92..42698f6 100644 --- a/JSONWebToken.podspec +++ b/JSONWebToken.podspec @@ -12,7 +12,18 @@ Pod::Spec.new do |spec| spec.tvos.deployment_target = '9.0' spec.watchos.deployment_target = '2.0' spec.requires_arc = true - spec.dependency 'CryptoSwift', '~> 0.6.1' spec.module_name = 'JWT' - spec.exclude_files = ['Sources/HMACCommonCrypto.swift'] + spec.exclude_files = ['Sources/HMACCryptoSwift.swift'] + + if ARGV.include?('lint') + spec.pod_target_xcconfig = { + 'SWIFT_INCLUDE_PATHS' => Dir.pwd, + } + else + spec.pod_target_xcconfig = { + 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/JSONWebToken/', + } + end + + spec.preserve_paths = 'CommonCrypto/{shim.h,module.modulemap}' end From aee8d905f5b6def05517466289345f8f827be75b Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 4 Aug 2017 09:17:07 -0700 Subject: [PATCH 05/62] feat: Use CommonCrypto in Xcode --- .gitmodules | 3 -- Cartfile | 1 - Cartfile.resolved | 1 - Carthage/Checkouts/CryptoSwift | 1 - JWT.xcodeproj/project.pbxproj | 85 ++++------------------------------ 5 files changed, 8 insertions(+), 83 deletions(-) delete mode 100644 .gitmodules delete mode 100644 Cartfile delete mode 100644 Cartfile.resolved delete mode 160000 Carthage/Checkouts/CryptoSwift diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 761522b..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "Carthage/Checkouts/CryptoSwift"] - path = Carthage/Checkouts/CryptoSwift - url = https://github.com/krzyzanowskim/CryptoSwift.git diff --git a/Cartfile b/Cartfile deleted file mode 100644 index 4f0cac5..0000000 --- a/Cartfile +++ /dev/null @@ -1 +0,0 @@ -github "krzyzanowskim/CryptoSwift" ~> 0.6.1 diff --git a/Cartfile.resolved b/Cartfile.resolved deleted file mode 100644 index 5b562e4..0000000 --- a/Cartfile.resolved +++ /dev/null @@ -1 +0,0 @@ -github "krzyzanowskim/CryptoSwift" "0.6.1" diff --git a/Carthage/Checkouts/CryptoSwift b/Carthage/Checkouts/CryptoSwift deleted file mode 160000 index 5f9bb95..0000000 --- a/Carthage/Checkouts/CryptoSwift +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5f9bb95c6f246c7e19bf4346a6ad1a0c406415f0 diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index eb97184..6fc3a21 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -11,13 +11,10 @@ 273011001F33EABA00219C35 /* HMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273010FE1F33EABA00219C35 /* HMAC.swift */; }; 273011011F33EABA00219C35 /* HMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273010FE1F33EABA00219C35 /* HMAC.swift */; }; 273011021F33EABA00219C35 /* HMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273010FE1F33EABA00219C35 /* HMAC.swift */; }; - 2730110A1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */; }; - 2730110B1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */; }; - 2730110C1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */; }; - 2730110D1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */; }; - 2734C6A81D88001F00BFF9F1 /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66725DAB1C59202E00FC32F4 /* CryptoSwift.framework */; }; - 2734C6A91D88002900BFF9F1 /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66725DAB1C59202E00FC32F4 /* CryptoSwift.framework */; }; - 2734C6AA1D88003000BFF9F1 /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66725DAB1C59202E00FC32F4 /* CryptoSwift.framework */; }; + 273011161F34029900219C35 /* HMACCommonCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */; }; + 273011171F34029900219C35 /* HMACCommonCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */; }; + 273011181F34029A00219C35 /* HMACCommonCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */; }; + 273011191F34029A00219C35 /* HMACCommonCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */; }; 277794051DF221F800573F3E /* ClaimSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277794041DF221F800573F3E /* ClaimSet.swift */; }; 277794061DF221F800573F3E /* ClaimSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277794041DF221F800573F3E /* ClaimSet.swift */; }; 277794071DF221F800573F3E /* ClaimSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277794041DF221F800573F3E /* ClaimSet.swift */; }; @@ -52,7 +49,6 @@ CD9B623D1C7753FB005D4844 /* Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71151C469F010005C709 /* Decode.swift */; }; CD9B623E1C7753FB005D4844 /* Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71131C469F010005C709 /* Base64.swift */; }; CD9B62421C7753FB005D4844 /* JWT.h in Headers */ = {isa = PBXBuildFile; fileRef = 279D63A11AD07FFF0024E2BC /* JWT.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CD9B62891C7758BB005D4844 /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66725DAB1C59202E00FC32F4 /* CryptoSwift.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -63,27 +59,6 @@ remoteGlobalIDString = 279D639B1AD07FFF0024E2BC; remoteInfo = JWT; }; - 66725DAA1C59202E00FC32F4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 66725DA21C59202E00FC32F4 /* CryptoSwift.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 754BE45519693E190098E6F3; - remoteInfo = "CryptoSwift iOS"; - }; - 66725DB21C59202E00FC32F4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 66725DA21C59202E00FC32F4 /* CryptoSwift.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 754BE46019693E190098E6F3; - remoteInfo = CryptoSwiftTests; - }; - CD9B628A1C7758CA005D4844 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 66725DA21C59202E00FC32F4 /* CryptoSwift.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 754BE45419693E190098E6F3; - remoteInfo = "CryptoSwift iOS"; - }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -105,7 +80,6 @@ 520A71161C469F010005C709 /* JWT.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = ""; }; 520A711B1C469F440005C709 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 540942F3614C41E3827F2013 /* Pods_JWT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_JWT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 66725DA21C59202E00FC32F4 /* CryptoSwift.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CryptoSwift.xcodeproj; path = Carthage/Checkouts/CryptoSwift/CryptoSwift.xcodeproj; sourceTree = ""; }; CD9B62231C7753D8005D4844 /* JWT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JWT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CD9B62351C7753EC005D4844 /* JWT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JWT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CD9B62471C7753FB005D4844 /* JWT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JWT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -117,7 +91,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2734C6A81D88001F00BFF9F1 /* CryptoSwift.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -133,7 +106,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CD9B62891C7758BB005D4844 /* CryptoSwift.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -141,7 +113,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2734C6A91D88002900BFF9F1 /* CryptoSwift.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -149,7 +120,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2734C6AA1D88003000BFF9F1 /* CryptoSwift.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -159,7 +129,6 @@ 279D63921AD07FFF0024E2BC = { isa = PBXGroup; children = ( - 66725DA21C59202E00FC32F4 /* CryptoSwift.xcodeproj */, 520A711B1C469F440005C709 /* Package.swift */, 520A71121C469F010005C709 /* Sources */, 279D639E1AD07FFF0024E2BC /* Sources */, @@ -236,15 +205,6 @@ path = Sources; sourceTree = ""; }; - 66725DA31C59202E00FC32F4 /* Products */ = { - isa = PBXGroup; - children = ( - 66725DAB1C59202E00FC32F4 /* CryptoSwift.framework */, - 66725DB31C59202E00FC32F4 /* Tests.xctest */, - ); - name = Products; - sourceTree = ""; - }; AC8AE547FDAF3DD80EB4DB2F /* Frameworks */ = { isa = PBXGroup; children = ( @@ -340,7 +300,6 @@ buildRules = ( ); dependencies = ( - CD9B628B1C7758CA005D4844 /* PBXTargetDependency */, ); name = "JWT-iOS"; productName = JWT; @@ -412,12 +371,6 @@ mainGroup = 279D63921AD07FFF0024E2BC; productRefGroup = 279D639D1AD07FFF0024E2BC /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 66725DA31C59202E00FC32F4 /* Products */; - ProjectRef = 66725DA21C59202E00FC32F4 /* CryptoSwift.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 279D639B1AD07FFF0024E2BC /* JWT-OSX */, @@ -429,23 +382,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 66725DAB1C59202E00FC32F4 /* CryptoSwift.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = CryptoSwift.framework; - remoteRef = 66725DAA1C59202E00FC32F4 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 66725DB31C59202E00FC32F4 /* Tests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = Tests.xctest; - remoteRef = 66725DB21C59202E00FC32F4 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 279D63A51AD07FFF0024E2BC /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -489,6 +425,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 273011161F34029900219C35 /* HMACCommonCrypto.swift in Sources */, 520A71181C469F010005C709 /* Claims.swift in Sources */, 520A711A1C469F010005C709 /* JWT.swift in Sources */, 520A71191C469F010005C709 /* Decode.swift in Sources */, @@ -497,7 +434,6 @@ 277794051DF221F800573F3E /* ClaimSet.swift in Sources */, 273010FF1F33EABA00219C35 /* HMAC.swift in Sources */, 520A71171C469F010005C709 /* Base64.swift in Sources */, - 2730110A1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -513,6 +449,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 273011171F34029900219C35 /* HMACCommonCrypto.swift in Sources */, CD9B62171C7753D8005D4844 /* Claims.swift in Sources */, CD9B62181C7753D8005D4844 /* JWT.swift in Sources */, CD9B62191C7753D8005D4844 /* Decode.swift in Sources */, @@ -521,7 +458,6 @@ 277794061DF221F800573F3E /* ClaimSet.swift in Sources */, 273011001F33EABA00219C35 /* HMAC.swift in Sources */, CD9B621A1C7753D8005D4844 /* Base64.swift in Sources */, - 2730110B1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -529,6 +465,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 273011181F34029A00219C35 /* HMACCommonCrypto.swift in Sources */, CD9B62291C7753EC005D4844 /* Claims.swift in Sources */, CD9B622A1C7753EC005D4844 /* JWT.swift in Sources */, CD9B622B1C7753EC005D4844 /* Decode.swift in Sources */, @@ -537,7 +474,6 @@ 277794071DF221F800573F3E /* ClaimSet.swift in Sources */, 273011011F33EABA00219C35 /* HMAC.swift in Sources */, CD9B622C1C7753EC005D4844 /* Base64.swift in Sources */, - 2730110C1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -545,6 +481,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 273011191F34029A00219C35 /* HMACCommonCrypto.swift in Sources */, CD9B623B1C7753FB005D4844 /* Claims.swift in Sources */, CD9B623C1C7753FB005D4844 /* JWT.swift in Sources */, CD9B623D1C7753FB005D4844 /* Decode.swift in Sources */, @@ -553,7 +490,6 @@ 277794081DF221F800573F3E /* ClaimSet.swift in Sources */, 273011021F33EABA00219C35 /* HMAC.swift in Sources */, CD9B623E1C7753FB005D4844 /* Base64.swift in Sources */, - 2730110D1F33FC9100219C35 /* HMACCryptoSwift.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -565,11 +501,6 @@ target = 279D639B1AD07FFF0024E2BC /* JWT-OSX */; targetProxy = 279D63A91AD07FFF0024E2BC /* PBXContainerItemProxy */; }; - CD9B628B1C7758CA005D4844 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "CryptoSwift iOS"; - targetProxy = CD9B628A1C7758CA005D4844 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ From 9b7463fa6485f2e708049cc058d9571486b51c0a Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 4 Aug 2017 11:41:47 -0700 Subject: [PATCH 06/62] fix: Allow Xcode to find CommonCrypto --- JWT.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index 6fc3a21..b2cc594 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -547,6 +547,7 @@ ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = macosx; + SWIFT_INCLUDE_PATHS = "$(SRCROOT)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; @@ -590,6 +591,7 @@ MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = macosx; + SWIFT_INCLUDE_PATHS = "$(SRCROOT)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; From 716873a23681e84b69833ff79d07f15e78ea0b6c Mon Sep 17 00:00:00 2001 From: Jan Brinker Date: Thu, 7 Sep 2017 16:39:48 +0200 Subject: [PATCH 07/62] Added leeway for date validation issue #54 --- Sources/ClaimSet.swift | 22 +++++++++++----------- Sources/Claims.swift | 6 +++--- Sources/Decode.swift | 8 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Sources/ClaimSet.swift b/Sources/ClaimSet.swift index 7626498..3632bc2 100644 --- a/Sources/ClaimSet.swift +++ b/Sources/ClaimSet.swift @@ -93,7 +93,7 @@ extension ClaimSet { // MARK: Validations extension ClaimSet { - public func validate(audience: String? = nil, issuer: String? = nil) throws { + public func validate(audience: String? = nil, issuer: String? = nil, leeway: TimeInterval = 0) throws { if let issuer = issuer { try validateIssuer(issuer) } @@ -101,10 +101,10 @@ extension ClaimSet { if let audience = audience { try validateAudience(audience) } - - try validateExpiary() - try validateNotBefore() - try validateIssuedAt() + + try validateExpiary(leeway: leeway) + try validateNotBefore(leeway: leeway) + try validateIssuedAt(leeway: leeway) } public func validateAudience(_ audience: String) throws { @@ -131,16 +131,16 @@ extension ClaimSet { } } - public func validateExpiary() throws { - try validateDate(claims, key: "exp", comparison: .orderedAscending, failure: .expiredSignature, decodeError: "Expiration time claim (exp) must be an integer") + public func validateExpiary(leeway: TimeInterval = 0) throws { + try validateDate(claims, key: "exp", comparison: .orderedAscending, leeway: (-1 * leeway), failure: .expiredSignature, decodeError: "Expiration time claim (exp) must be an integer") } - public func validateNotBefore() throws { - try validateDate(claims, key: "nbf", comparison: .orderedDescending, failure: .immatureSignature, decodeError: "Not before claim (nbf) must be an integer") + public func validateNotBefore(leeway: TimeInterval = 0) throws { + try validateDate(claims, key: "nbf", comparison: .orderedDescending, leeway: leeway, failure: .immatureSignature, decodeError: "Not before claim (nbf) must be an integer") } - public func validateIssuedAt() throws { - try validateDate(claims, key: "iat", comparison: .orderedDescending, failure: .invalidIssuedAt, decodeError: "Issued at claim (iat) must be an integer") + public func validateIssuedAt(leeway: TimeInterval = 0) throws { + try validateDate(claims, key: "iat", comparison: .orderedDescending, leeway: leeway, failure: .invalidIssuedAt, decodeError: "Issued at claim (iat) must be an integer") } } diff --git a/Sources/Claims.swift b/Sources/Claims.swift index ad07027..d1df6f4 100644 --- a/Sources/Claims.swift +++ b/Sources/Claims.swift @@ -1,6 +1,6 @@ import Foundation -func validateDate(_ payload: Payload, key: String, comparison: ComparisonResult, failure: InvalidToken, decodeError: String) throws { +func validateDate(_ payload: Payload, key: String, comparison: ComparisonResult, leeway: TimeInterval = 0, failure: InvalidToken, decodeError: String) throws { if payload[key] == nil { return } @@ -8,8 +8,8 @@ func validateDate(_ payload: Payload, key: String, comparison: ComparisonResult, guard let date = extractDate(payload: payload, key: key) else { throw InvalidToken.decodeError(decodeError) } - - if date.compare(Date()) == comparison { + + if date.compare(Date().addingTimeInterval(leeway)) == comparison { throw failure } } diff --git a/Sources/Decode.swift b/Sources/Decode.swift index ce802d7..3e7ca41 100644 --- a/Sources/Decode.swift +++ b/Sources/Decode.swift @@ -47,11 +47,11 @@ public enum InvalidToken: CustomStringConvertible, Error { /// Decode a JWT -public func decode(_ jwt: String, algorithms: [Algorithm], verify: Bool = true, audience: String? = nil, issuer: String? = nil) throws -> ClaimSet { +public func decode(_ jwt: String, algorithms: [Algorithm], verify: Bool = true, audience: String? = nil, issuer: String? = nil, leeway: TimeInterval = 0) throws -> ClaimSet { let (header, claims, signature, signatureInput) = try load(jwt) if verify { - try claims.validate(audience: audience, issuer: issuer) + try claims.validate(audience: audience, issuer: issuer, leeway: leeway) try verifySignature(algorithms, header: header, signingInput: signatureInput, signature: signature) } @@ -59,8 +59,8 @@ public func decode(_ jwt: String, algorithms: [Algorithm], verify: Bool = true, } /// Decode a JWT -public func decode(_ jwt: String, algorithm: Algorithm, verify: Bool = true, audience: String? = nil, issuer: String? = nil) throws -> ClaimSet { - return try decode(jwt, algorithms: [algorithm], verify: verify, audience: audience, issuer: issuer) +public func decode(_ jwt: String, algorithm: Algorithm, verify: Bool = true, audience: String? = nil, issuer: String? = nil, leeway: TimeInterval = 0) throws -> ClaimSet { + return try decode(jwt, algorithms: [algorithm], verify: verify, audience: audience, issuer: issuer, leeway: leeway) } /// Decode a JWT From 803fcea3b1b150b66dc08f7eaea624a7c4b48bed Mon Sep 17 00:00:00 2001 From: Jan Brinker Date: Thu, 7 Sep 2017 16:40:12 +0200 Subject: [PATCH 08/62] Added unit tests for date validation with leeway. --- Tests/JWTTests/JWTTests.swift | 83 +++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/Tests/JWTTests/JWTTests.swift b/Tests/JWTTests/JWTTests.swift index a0e1b8f..2659230 100644 --- a/Tests/JWTTests/JWTTests.swift +++ b/Tests/JWTTests/JWTTests.swift @@ -279,6 +279,89 @@ class DecodeTests: XCTestCase { } } +class ValidationTests: XCTestCase { + func testClaimJustExpiredWithoutLeeway() { + var claims = ClaimSet() + claims.expiration = Date().addingTimeInterval(-1) + + let expectation = XCTestExpectation(description: "Signature should be expired.") + do { + try claims.validateExpiary() + XCTFail("InvalidToken.expiredSignature error should have been thrown.") + } catch InvalidToken.expiredSignature { + expectation.fulfill() + } catch { + XCTFail("Unexpected error while validating exp claim.") + } + self.wait(for: [expectation], timeout: 0.5) + } + + func testClaimJustNotExpiredWithoutLeeway() { + var claims = ClaimSet() + claims.expiration = Date().addingTimeInterval(-1) + + do { + try claims.validateExpiary(leeway: 2) + } catch { + XCTFail("Unexpected error while validating exp claim that should be valid with leeway.") + } + } + + func testNotBeforeIsImmatureSignatureWithoutLeeway() { + var claims = ClaimSet() + claims.notBefore = Date().addingTimeInterval(1) + + let expectation = XCTestExpectation(description: "Signature should be immature.") + do { + try claims.validateNotBefore() + XCTFail("InvalidToken.immatureSignature error should have been thrown.") + } catch InvalidToken.immatureSignature { + expectation.fulfill() + } catch { + XCTFail("Unexpected error while validating nbf claim.") + } + self.wait(for: [expectation], timeout: 0.5) + } + + func testNotBeforeIsValidWithLeeway() { + var claims = ClaimSet() + claims.notBefore = Date().addingTimeInterval(1) + + do { + try claims.validateNotBefore(leeway: 2) + } catch { + XCTFail("Unexpected error while validating nbf claim that should be valid with leeway.") + } + } + + func testIssuedAtIsInFutureWithoutLeeway() { + var claims = ClaimSet() + claims.issuedAt = Date().addingTimeInterval(1) + + let expectation = XCTestExpectation(description: "iat should be in the future.") + do { + try claims.validateIssuedAt() + XCTFail("InvalidToken.invalidIssuedAt error should have been thrown.") + } catch InvalidToken.invalidIssuedAt { + expectation.fulfill() + } catch { + XCTFail("Unexpected error while validating iat claim.") + } + self.wait(for: [expectation], timeout: 0.5) + } + + func testIssuedAtIsValidWithLeeway() { + var claims = ClaimSet() + claims.issuedAt = Date().addingTimeInterval(1) + + do { + try claims.validateIssuedAt(leeway: 2) + } catch { + XCTFail("Unexpected error while validating iat claim that should be valid with leeway.") + } + } +} + // MARK: Helpers func assertSuccess(_ decoder: @autoclosure () throws -> Payload, closure: ((Payload) -> Void)? = nil) { From 78dc2010cf00a7d3c9bfcddacd554bf6096697aa Mon Sep 17 00:00:00 2001 From: Jan Brinker Date: Thu, 7 Sep 2017 16:40:34 +0200 Subject: [PATCH 09/62] Added some integration tests for verification of dates with and without leeway. --- Tests/JWTTests/JWTTests.swift | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Tests/JWTTests/JWTTests.swift b/Tests/JWTTests/JWTTests.swift index 2659230..4c1e8a9 100644 --- a/Tests/JWTTests/JWTTests.swift +++ b/Tests/JWTTests/JWTTests.swift @@ -362,6 +362,46 @@ class ValidationTests: XCTestCase { } } +class IntegrationTests: XCTestCase { + func testVerificationFailureWithoutLeeway() { + let token = JWT.encode(.none) { builder in + builder.issuer = "fuller.li" + builder.audience = "cocoapods" + builder.expiration = Date().addingTimeInterval(-1) // Token expired one second ago + builder.notBefore = Date().addingTimeInterval(1) // Token starts being valid in one second + builder.issuedAt = Date().addingTimeInterval(1) // Token is issued one second in the future + } + + let expectation = XCTestExpectation(description: "Verification should fail.") + do { + let _ = try JWT.decode(token, algorithm: .none) + XCTFail("InvalidToken error should have been thrown.") + } catch is InvalidToken { + expectation.fulfill() + } catch { + XCTFail("Unexpected error type while verifying token.") + } + self.wait(for: [expectation], timeout: 0.5) + } + + func testVerificationSuccessWithLeeway() { + let token = JWT.encode(.none) { builder in + builder.issuer = "fuller.li" + builder.audience = "cocoapods" + builder.expiration = Date().addingTimeInterval(-1) // Token expired one second ago + builder.notBefore = Date().addingTimeInterval(1) // Token starts being valid in one second + builder.issuedAt = Date().addingTimeInterval(1) // Token is issued one second in the future + } + + do { + let _ = try JWT.decode(token, algorithm: .none, leeway: 2) + // Due to leeway no error gets thrown. + } catch { + XCTFail("Unexpected error type while verifying token.") + } + } +} + // MARK: Helpers func assertSuccess(_ decoder: @autoclosure () throws -> Payload, closure: ((Payload) -> Void)? = nil) { From 0a3e73538185a0db5bc52d7ea339134384bc91c1 Mon Sep 17 00:00:00 2001 From: Jan Brinker Date: Thu, 7 Sep 2017 16:46:43 +0200 Subject: [PATCH 10/62] Repaired indentation mix of spaces and tabs. --- Sources/ClaimSet.swift | 4 ++-- Sources/Decode.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/ClaimSet.swift b/Sources/ClaimSet.swift index 3632bc2..7dcf872 100644 --- a/Sources/ClaimSet.swift +++ b/Sources/ClaimSet.swift @@ -131,8 +131,8 @@ extension ClaimSet { } } - public func validateExpiary(leeway: TimeInterval = 0) throws { - try validateDate(claims, key: "exp", comparison: .orderedAscending, leeway: (-1 * leeway), failure: .expiredSignature, decodeError: "Expiration time claim (exp) must be an integer") + public func validateExpiary(leeway: TimeInterval = 0) throws { + try validateDate(claims, key: "exp", comparison: .orderedAscending, leeway: (-1 * leeway), failure: .expiredSignature, decodeError: "Expiration time claim (exp) must be an integer") } public func validateNotBefore(leeway: TimeInterval = 0) throws { diff --git a/Sources/Decode.swift b/Sources/Decode.swift index 3e7ca41..3054160 100644 --- a/Sources/Decode.swift +++ b/Sources/Decode.swift @@ -51,7 +51,7 @@ public func decode(_ jwt: String, algorithms: [Algorithm], verify: Bool = true, let (header, claims, signature, signatureInput) = try load(jwt) if verify { - try claims.validate(audience: audience, issuer: issuer, leeway: leeway) + try claims.validate(audience: audience, issuer: issuer, leeway: leeway) try verifySignature(algorithms, header: header, signingInput: signatureInput, signature: signature) } @@ -60,7 +60,7 @@ public func decode(_ jwt: String, algorithms: [Algorithm], verify: Bool = true, /// Decode a JWT public func decode(_ jwt: String, algorithm: Algorithm, verify: Bool = true, audience: String? = nil, issuer: String? = nil, leeway: TimeInterval = 0) throws -> ClaimSet { - return try decode(jwt, algorithms: [algorithm], verify: verify, audience: audience, issuer: issuer, leeway: leeway) + return try decode(jwt, algorithms: [algorithm], verify: verify, audience: audience, issuer: issuer, leeway: leeway) } /// Decode a JWT From 5f6907e46f097f7726cd4e82a43a87b6817da5b8 Mon Sep 17 00:00:00 2001 From: Jan Brinker Date: Fri, 8 Sep 2017 09:46:26 +0200 Subject: [PATCH 11/62] Fixing unit test build error on Linux. --- Tests/JWTTests/JWTTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/JWTTests/JWTTests.swift b/Tests/JWTTests/JWTTests.swift index 4c1e8a9..337b664 100644 --- a/Tests/JWTTests/JWTTests.swift +++ b/Tests/JWTTests/JWTTests.swift @@ -374,7 +374,7 @@ class IntegrationTests: XCTestCase { let expectation = XCTestExpectation(description: "Verification should fail.") do { - let _ = try JWT.decode(token, algorithm: .none) + let _ = try JWT.decode(token, algorithm: .none, leeway: 0) XCTFail("InvalidToken error should have been thrown.") } catch is InvalidToken { expectation.fulfill() From 6affa9356f1542124f288fedf0186dd35a4dcebc Mon Sep 17 00:00:00 2001 From: Jan Brinker Date: Fri, 8 Sep 2017 12:54:01 +0200 Subject: [PATCH 12/62] Removed XCTestExpectations from validation tests. --- Tests/JWTTests/JWTTests.swift | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/Tests/JWTTests/JWTTests.swift b/Tests/JWTTests/JWTTests.swift index 337b664..b8ffe50 100644 --- a/Tests/JWTTests/JWTTests.swift +++ b/Tests/JWTTests/JWTTests.swift @@ -283,17 +283,15 @@ class ValidationTests: XCTestCase { func testClaimJustExpiredWithoutLeeway() { var claims = ClaimSet() claims.expiration = Date().addingTimeInterval(-1) - - let expectation = XCTestExpectation(description: "Signature should be expired.") + do { try claims.validateExpiary() XCTFail("InvalidToken.expiredSignature error should have been thrown.") } catch InvalidToken.expiredSignature { - expectation.fulfill() + // Correct error thrown } catch { XCTFail("Unexpected error while validating exp claim.") } - self.wait(for: [expectation], timeout: 0.5) } func testClaimJustNotExpiredWithoutLeeway() { @@ -311,16 +309,14 @@ class ValidationTests: XCTestCase { var claims = ClaimSet() claims.notBefore = Date().addingTimeInterval(1) - let expectation = XCTestExpectation(description: "Signature should be immature.") do { try claims.validateNotBefore() XCTFail("InvalidToken.immatureSignature error should have been thrown.") } catch InvalidToken.immatureSignature { - expectation.fulfill() + // Correct error thrown } catch { XCTFail("Unexpected error while validating nbf claim.") } - self.wait(for: [expectation], timeout: 0.5) } func testNotBeforeIsValidWithLeeway() { @@ -337,17 +333,15 @@ class ValidationTests: XCTestCase { func testIssuedAtIsInFutureWithoutLeeway() { var claims = ClaimSet() claims.issuedAt = Date().addingTimeInterval(1) - - let expectation = XCTestExpectation(description: "iat should be in the future.") + do { try claims.validateIssuedAt() XCTFail("InvalidToken.invalidIssuedAt error should have been thrown.") } catch InvalidToken.invalidIssuedAt { - expectation.fulfill() + // Correct error thrown } catch { XCTFail("Unexpected error while validating iat claim.") } - self.wait(for: [expectation], timeout: 0.5) } func testIssuedAtIsValidWithLeeway() { @@ -371,17 +365,15 @@ class IntegrationTests: XCTestCase { builder.notBefore = Date().addingTimeInterval(1) // Token starts being valid in one second builder.issuedAt = Date().addingTimeInterval(1) // Token is issued one second in the future } - - let expectation = XCTestExpectation(description: "Verification should fail.") + do { let _ = try JWT.decode(token, algorithm: .none, leeway: 0) XCTFail("InvalidToken error should have been thrown.") } catch is InvalidToken { - expectation.fulfill() + // Correct error thrown } catch { XCTFail("Unexpected error type while verifying token.") } - self.wait(for: [expectation], timeout: 0.5) } func testVerificationSuccessWithLeeway() { From fef37501a783709a7cc52fb8b4523a46de9844ae Mon Sep 17 00:00:00 2001 From: Jan Brinker Date: Mon, 11 Sep 2017 14:40:54 +0200 Subject: [PATCH 13/62] Added leeway parameter introduction to changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd856eb..9588b8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - Allow passing additional headers when encoding a JWT. +- Allow passing leeway parameter for date checks when verifying a JWT. ## 2.1.0 From a6fa6d8df6b391868710f495684557426cd187db Mon Sep 17 00:00:00 2001 From: Jan Brinker Date: Mon, 11 Sep 2017 14:42:20 +0200 Subject: [PATCH 14/62] Added documentation for leeway parameter for decoding. --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 830f70d..9a6fae2 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,12 @@ try JWT.decode("eyJh...5w", algorithms: [ ]) ``` +You might also want to give your iat, exp and nbf checks some kind of leeway to account for skewed clocks. You can do this by passing a `leeway` parameter like this: + +```swift +try JWT.decode("eyJh...5w", algorithm: .hs256("secret".data(using: .utf8)!), leeway: 10) +``` + #### Supported claims The library supports validating the following claims: From e5745f95a3e60d9ccee4900764ec79b4239c4ef9 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 20 Sep 2017 01:33:34 +0100 Subject: [PATCH 15/62] chore: Release 2.2.0 --- CHANGELOG.md | 3 ++- JSONWebToken.podspec | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9588b8f..2b9686c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ # JSON Web Token Changelog -## Master +## 2.2.0 ### Enhancements +- On Apple platforms, JSONWebToken will use the system CommonCrypto where possible. - Allow passing additional headers when encoding a JWT. - Allow passing leeway parameter for date checks when verifying a JWT. diff --git a/JSONWebToken.podspec b/JSONWebToken.podspec index 42698f6..f17fd79 100644 --- a/JSONWebToken.podspec +++ b/JSONWebToken.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'JSONWebToken' - spec.version = '2.1.1' + spec.version = '2.2.0' spec.summary = 'Swift library for JSON Web Tokens (JWT).' spec.homepage = 'https://github.com/kylef/JSONWebToken.swift' spec.license = { :type => 'BSD', :file => 'LICENSE' } From 3c9b3a62d82050c875147ac51edb7aa2389d7013 Mon Sep 17 00:00:00 2001 From: Graham Chance Date: Tue, 26 Sep 2017 10:55:11 -0400 Subject: [PATCH 16/62] docs: typo in README (#87) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9a6fae2..d864130 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ claims.issuer = "fuller.li" claims.issuedAt = Date() claims["custom"] = "Hi" -JWT.encode(claims: claims, algorithm, algorithm: .hs256("secret".data(using: .utf8))) +JWT.encode(claims: claims, algorithm: .hs256("secret".data(using: .utf8))) ``` #### Building a JWT with the builder pattern From 5c5607b2a68ce8264201296b8bcdb4dccfb77617 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Thu, 28 Sep 2017 10:23:16 +0100 Subject: [PATCH 17/62] chore: Update to Xcode project defaults --- JWT.xcodeproj/project.pbxproj | 18 +++++++++++++++--- .../xcshareddata/xcschemes/JWT-OSX.xcscheme | 4 +++- .../xcshareddata/xcschemes/JWT-iOS.xcscheme | 4 +++- .../xcshareddata/xcschemes/JWT-tvOS.xcscheme | 4 +++- .../xcschemes/JWT-watchOS.xcscheme | 4 +++- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index b2cc594..4d053c4 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -350,7 +350,7 @@ attributes = { LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0910; ORGANIZATIONNAME = Cocode; TargetAttributes = { 279D639B1AD07FFF0024E2BC = { @@ -512,14 +512,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -549,7 +555,7 @@ SDKROOT = macosx; SWIFT_INCLUDE_PATHS = "$(SRCROOT)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -563,14 +569,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -593,7 +605,7 @@ SDKROOT = macosx; SWIFT_INCLUDE_PATHS = "$(SRCROOT)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; diff --git a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-OSX.xcscheme b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-OSX.xcscheme index ff0db9d..dc61530 100644 --- a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-OSX.xcscheme +++ b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-OSX.xcscheme @@ -1,6 +1,6 @@ @@ -36,6 +37,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-tvOS.xcscheme b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-tvOS.xcscheme index 624d99c..46efb5f 100644 --- a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-tvOS.xcscheme +++ b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-tvOS.xcscheme @@ -1,6 +1,6 @@ @@ -36,6 +37,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-watchOS.xcscheme b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-watchOS.xcscheme index 87c365a..c0bf55d 100644 --- a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-watchOS.xcscheme +++ b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-watchOS.xcscheme @@ -1,6 +1,6 @@ @@ -36,6 +37,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" From 81f55d391a41cd7ec8efcc4987dcde2342b53cad Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 3 Oct 2017 22:44:35 +0100 Subject: [PATCH 18/62] docs: Update recommended installation method(s) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d864130..ce1db66 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,14 @@ Swift implementation of [JSON Web Token](https://tools.ietf.org/html/draft-ietf- ## Installation -[CocoaPods](http://cocoapods.org/) is the recommended installation method. +Swift Pacakage Manager is the recommended installation method for JSONWebToken, [CocoaPods](http://cocoapods.org/) is also supported. ```ruby pod 'JSONWebToken' ``` +**NOTE:** *Carthage may be supported, however support will not be provided for this installation method, use at your own risk if you know how it works.* + ## Usage ```swift From ad8ed43d5fb83ea730c81f2b8e8517cbe4cbf7d4 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 00:33:52 +0200 Subject: [PATCH 19/62] refactor: Move JWA to separate file --- JWT.xcodeproj/project.pbxproj | 10 +++++++ Sources/JWA.swift | 55 +++++++++++++++++++++++++++++++++++ Sources/JWT.swift | 55 ----------------------------------- 3 files changed, 65 insertions(+), 55 deletions(-) create mode 100644 Sources/JWA.swift diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index 4d053c4..b0c461f 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 271E10801F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; + 271E10811F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; + 271E10821F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; + 271E10831F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.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 */; }; @@ -62,6 +66,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 271E107F1F90253300B5033C /* JWA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWA.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 = ""; }; @@ -198,6 +203,7 @@ 520A71151C469F010005C709 /* Decode.swift */, 2777940F1DF22D0D00573F3E /* Encode.swift */, 520A71161C469F010005C709 /* JWT.swift */, + 271E107F1F90253300B5033C /* JWA.swift */, 273010FE1F33EABA00219C35 /* HMAC.swift */, 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */, 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */, @@ -425,6 +431,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 271E10801F90253300B5033C /* JWA.swift in Sources */, 273011161F34029900219C35 /* HMACCommonCrypto.swift in Sources */, 520A71181C469F010005C709 /* Claims.swift in Sources */, 520A711A1C469F010005C709 /* JWT.swift in Sources */, @@ -449,6 +456,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 271E10811F90253300B5033C /* JWA.swift in Sources */, 273011171F34029900219C35 /* HMACCommonCrypto.swift in Sources */, CD9B62171C7753D8005D4844 /* Claims.swift in Sources */, CD9B62181C7753D8005D4844 /* JWT.swift in Sources */, @@ -465,6 +473,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 271E10821F90253300B5033C /* JWA.swift in Sources */, 273011181F34029A00219C35 /* HMACCommonCrypto.swift in Sources */, CD9B62291C7753EC005D4844 /* Claims.swift in Sources */, CD9B622A1C7753EC005D4844 /* JWT.swift in Sources */, @@ -481,6 +490,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 271E10831F90253300B5033C /* JWA.swift in Sources */, 273011191F34029A00219C35 /* HMACCommonCrypto.swift in Sources */, CD9B623B1C7753FB005D4844 /* Claims.swift in Sources */, CD9B623C1C7753FB005D4844 /* JWT.swift in Sources */, diff --git a/Sources/JWA.swift b/Sources/JWA.swift new file mode 100644 index 0000000..950b1b1 --- /dev/null +++ b/Sources/JWA.swift @@ -0,0 +1,55 @@ +/// Represents a JSON Web Algorithm (JWA) +/// https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40 +public enum Algorithm: CustomStringConvertible { + /// No Algorithm, i-e, insecure + case none + + /// HMAC using SHA-256 hash algorithm + case hs256(Data) + + /// HMAC using SHA-384 hash algorithm + case hs384(Data) + + /// HMAC using SHA-512 hash algorithm + case hs512(Data) + + public var description: String { + switch self { + case .none: + return "none" + case .hs256: + return "HS256" + case .hs384: + return "HS384" + case .hs512: + return "HS512" + } + } + + /// Sign a message using the algorithm + func sign(_ message: String) -> String { + func signHS(_ key: Data, algorithm: HMACAlgorithm) -> String { + let messageData = message.data(using: String.Encoding.utf8, allowLossyConversion: false)! + return base64encode(hmac(algorithm: algorithm, key: key, message: messageData)) + } + + switch self { + case .none: + return "" + + case .hs256(let key): + return signHS(key, algorithm: .sha256) + + case .hs384(let key): + return signHS(key, algorithm: .sha384) + + case .hs512(let key): + return signHS(key, algorithm: .sha512) + } + } + + /// Verify a signature for a message using the algorithm + func verify(_ message: String, signature: Data) -> Bool { + return sign(message) == base64encode(signature) + } +} diff --git a/Sources/JWT.swift b/Sources/JWT.swift index b412da3..5e5569e 100644 --- a/Sources/JWT.swift +++ b/Sources/JWT.swift @@ -1,58 +1,3 @@ import Foundation public typealias Payload = [String: Any] - -/// The supported Algorithms -public enum Algorithm: CustomStringConvertible { - /// No Algorithm, i-e, insecure - case none - - /// HMAC using SHA-256 hash algorithm - case hs256(Data) - - /// HMAC using SHA-384 hash algorithm - case hs384(Data) - - /// HMAC using SHA-512 hash algorithm - case hs512(Data) - - public var description: String { - switch self { - case .none: - return "none" - case .hs256: - return "HS256" - case .hs384: - return "HS384" - case .hs512: - return "HS512" - } - } - - /// Sign a message using the algorithm - func sign(_ message: String) -> String { - func signHS(_ key: Data, algorithm: HMACAlgorithm) -> String { - let messageData = message.data(using: String.Encoding.utf8, allowLossyConversion: false)! - return base64encode(hmac(algorithm: algorithm, key: key, message: messageData)) - } - - switch self { - case .none: - return "" - - case .hs256(let key): - return signHS(key, algorithm: .sha256) - - case .hs384(let key): - return signHS(key, algorithm: .sha384) - - case .hs512(let key): - return signHS(key, algorithm: .sha512) - } - } - - /// Verify a signature for a message using the algorithm - func verify(_ message: String, signature: Data) -> Bool { - return sign(message) == base64encode(signature) - } -} From b20ecac938bcf48d7574ab57e74c802de78fb52a Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 00:46:58 +0200 Subject: [PATCH 20/62] refactor: Add `type` property to JOSEHeader --- JWT.xcodeproj/project.pbxproj | 4 +++ Sources/JOSEHeader.swift | 10 +++++++ Tests/JWTTests/JOSEHeaderTests.swift | 42 ++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 Tests/JWTTests/JOSEHeaderTests.swift diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index b0c461f..52fba4c 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 271E10811F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; 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 */; }; 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 */; }; @@ -67,6 +68,7 @@ /* 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 = ""; }; 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 = ""; }; @@ -179,6 +181,7 @@ isa = PBXGroup; children = ( 279D63AE1AD07FFF0024E2BC /* JWTTests.swift */, + 271E10841F90274A00B5033C /* JOSEHeaderTests.swift */, 279D63AC1AD07FFF0024E2BC /* Supporting Files */, ); name = Tests; @@ -449,6 +452,7 @@ buildActionMask = 2147483647; files = ( 279D63AF1AD07FFF0024E2BC /* JWTTests.swift in Sources */, + 271E10851F90274A00B5033C /* JOSEHeaderTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/JOSEHeader.swift b/Sources/JOSEHeader.swift index e19453c..4bfcf49 100644 --- a/Sources/JOSEHeader.swift +++ b/Sources/JOSEHeader.swift @@ -25,4 +25,14 @@ struct JOSEHeader { parameters["alg"] = newValue } } + + var type: String? { + get { + return parameters["typ"] as? String + } + + set { + parameters["typ"] = newValue + } + } } diff --git a/Tests/JWTTests/JOSEHeaderTests.swift b/Tests/JWTTests/JOSEHeaderTests.swift new file mode 100644 index 0000000..44af163 --- /dev/null +++ b/Tests/JWTTests/JOSEHeaderTests.swift @@ -0,0 +1,42 @@ +import XCTest +@testable import JWT + +class JOSEHeaderTests: XCTestCase { + // MARK: Algorithm + + func testGettingUnsetAlgoritm() { + let header = JOSEHeader(parameters: [:]) + XCTAssertNil(header.algorithm) + } + + func testGettingAlgoritm() { + let header = JOSEHeader(parameters: ["alg": "none"]) + XCTAssertEqual(header.algorithm, "none") + } + + func testSettingAlgoritm() { + var header = JOSEHeader(parameters: [:]) + + header.algorithm = "none" + XCTAssertEqual(header.algorithm, "none") + } + + // MARK: Type + + func testGettingUnsetType() { + let header = JOSEHeader(parameters: [:]) + XCTAssertNil(header.type) + } + + func testGettingType() { + let header = JOSEHeader(parameters: ["typ": "JWT"]) + XCTAssertEqual(header.type, "JWT") + } + + func testSettingType() { + var header = JOSEHeader(parameters: [:]) + + header.type = "JWT" + XCTAssertEqual(header.type, "JWT") + } +} From 7be4e4620e0daff27953e85da0018bc96ef5a8dd Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 01:12:54 +0200 Subject: [PATCH 21/62] refactor: Move JWT sources to JWT module --- JSONWebToken.podspec | 4 ++-- JWT.xcodeproj/project.pbxproj | 30 +++++++++++++++--------- Package.swift | 4 ++-- Sources/{ => JWT}/Base64.swift | 0 Sources/{ => JWT}/ClaimSet.swift | 0 Sources/{ => JWT}/Claims.swift | 0 Sources/{ => JWT}/Decode.swift | 0 Sources/{ => JWT}/Encode.swift | 0 Sources/{ => JWT}/HMAC.swift | 0 Sources/{ => JWT}/HMACCommonCrypto.swift | 0 Sources/{ => JWT}/HMACCryptoSwift.swift | 0 Sources/{ => JWT}/JOSEHeader.swift | 0 Sources/{ => JWT}/JWA.swift | 2 ++ Sources/{ => JWT}/JWT.swift | 0 14 files changed, 25 insertions(+), 15 deletions(-) rename Sources/{ => JWT}/Base64.swift (100%) rename Sources/{ => JWT}/ClaimSet.swift (100%) rename Sources/{ => JWT}/Claims.swift (100%) rename Sources/{ => JWT}/Decode.swift (100%) rename Sources/{ => JWT}/Encode.swift (100%) rename Sources/{ => JWT}/HMAC.swift (100%) rename Sources/{ => JWT}/HMACCommonCrypto.swift (100%) rename Sources/{ => JWT}/HMACCryptoSwift.swift (100%) rename Sources/{ => JWT}/JOSEHeader.swift (100%) rename Sources/{ => JWT}/JWA.swift (98%) rename Sources/{ => JWT}/JWT.swift (100%) diff --git a/JSONWebToken.podspec b/JSONWebToken.podspec index f17fd79..3ce74ef 100644 --- a/JSONWebToken.podspec +++ b/JSONWebToken.podspec @@ -6,14 +6,14 @@ Pod::Spec.new do |spec| spec.license = { :type => 'BSD', :file => 'LICENSE' } spec.author = { 'Kyle Fuller' => 'kyle@fuller.li' } spec.source = { :git => 'https://github.com/kylef/JSONWebToken.swift.git', :tag => "#{spec.version}" } - spec.source_files = 'Sources/*.swift' + spec.source_files = 'Sources/JWT/*.swift' spec.ios.deployment_target = '8.0' spec.osx.deployment_target = '10.9' spec.tvos.deployment_target = '9.0' spec.watchos.deployment_target = '2.0' spec.requires_arc = true spec.module_name = 'JWT' - spec.exclude_files = ['Sources/HMACCryptoSwift.swift'] + spec.exclude_files = ['Sources/JWT/HMACCryptoSwift.swift'] if ARGV.include?('lint') spec.pod_target_xcconfig = { diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index 52fba4c..3562610 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -133,6 +133,24 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 271E10861F902D8900B5033C /* JWT */ = { + isa = PBXGroup; + children = ( + 277794041DF221F800573F3E /* ClaimSet.swift */, + 2777940A1DF22BE400573F3E /* JOSEHeader.swift */, + 520A71131C469F010005C709 /* Base64.swift */, + 520A71141C469F010005C709 /* Claims.swift */, + 520A71151C469F010005C709 /* Decode.swift */, + 2777940F1DF22D0D00573F3E /* Encode.swift */, + 520A71161C469F010005C709 /* JWT.swift */, + 271E107F1F90253300B5033C /* JWA.swift */, + 273010FE1F33EABA00219C35 /* HMAC.swift */, + 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */, + 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */, + ); + path = JWT; + sourceTree = ""; + }; 279D63921AD07FFF0024E2BC = { isa = PBXGroup; children = ( @@ -199,17 +217,7 @@ 520A71121C469F010005C709 /* Sources */ = { isa = PBXGroup; children = ( - 277794041DF221F800573F3E /* ClaimSet.swift */, - 2777940A1DF22BE400573F3E /* JOSEHeader.swift */, - 520A71131C469F010005C709 /* Base64.swift */, - 520A71141C469F010005C709 /* Claims.swift */, - 520A71151C469F010005C709 /* Decode.swift */, - 2777940F1DF22D0D00573F3E /* Encode.swift */, - 520A71161C469F010005C709 /* JWT.swift */, - 271E107F1F90253300B5033C /* JWA.swift */, - 273010FE1F33EABA00219C35 /* HMAC.swift */, - 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */, - 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */, + 271E10861F902D8900B5033C /* JWT */, ); path = Sources; sourceTree = ""; diff --git a/Package.swift b/Package.swift index eb6f28b..707de2f 100644 --- a/Package.swift +++ b/Package.swift @@ -8,7 +8,7 @@ let package = Package( .Package(url: "https://github.com/kylef-archive/CommonCrypto.git", majorVersion: 1), ], exclude: [ - "Sources/HMACCryptoSwift.swift", + "Sources/JWT/HMACCryptoSwift.swift", ] ) #else @@ -18,7 +18,7 @@ let package = Package( .Package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", majorVersion: 0, minor: 6), ], exclude: [ - "Sources/HMACCommonCrypto.swift", + "Sources/JWT/HMACCommonCrypto.swift", ] ) #endif diff --git a/Sources/Base64.swift b/Sources/JWT/Base64.swift similarity index 100% rename from Sources/Base64.swift rename to Sources/JWT/Base64.swift diff --git a/Sources/ClaimSet.swift b/Sources/JWT/ClaimSet.swift similarity index 100% rename from Sources/ClaimSet.swift rename to Sources/JWT/ClaimSet.swift diff --git a/Sources/Claims.swift b/Sources/JWT/Claims.swift similarity index 100% rename from Sources/Claims.swift rename to Sources/JWT/Claims.swift diff --git a/Sources/Decode.swift b/Sources/JWT/Decode.swift similarity index 100% rename from Sources/Decode.swift rename to Sources/JWT/Decode.swift diff --git a/Sources/Encode.swift b/Sources/JWT/Encode.swift similarity index 100% rename from Sources/Encode.swift rename to Sources/JWT/Encode.swift diff --git a/Sources/HMAC.swift b/Sources/JWT/HMAC.swift similarity index 100% rename from Sources/HMAC.swift rename to Sources/JWT/HMAC.swift diff --git a/Sources/HMACCommonCrypto.swift b/Sources/JWT/HMACCommonCrypto.swift similarity index 100% rename from Sources/HMACCommonCrypto.swift rename to Sources/JWT/HMACCommonCrypto.swift diff --git a/Sources/HMACCryptoSwift.swift b/Sources/JWT/HMACCryptoSwift.swift similarity index 100% rename from Sources/HMACCryptoSwift.swift rename to Sources/JWT/HMACCryptoSwift.swift diff --git a/Sources/JOSEHeader.swift b/Sources/JWT/JOSEHeader.swift similarity index 100% rename from Sources/JOSEHeader.swift rename to Sources/JWT/JOSEHeader.swift diff --git a/Sources/JWA.swift b/Sources/JWT/JWA.swift similarity index 98% rename from Sources/JWA.swift rename to Sources/JWT/JWA.swift index 950b1b1..3ac9cef 100644 --- a/Sources/JWA.swift +++ b/Sources/JWT/JWA.swift @@ -1,3 +1,5 @@ +import Foundation + /// Represents a JSON Web Algorithm (JWA) /// https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40 public enum Algorithm: CustomStringConvertible { diff --git a/Sources/JWT.swift b/Sources/JWT/JWT.swift similarity index 100% rename from Sources/JWT.swift rename to Sources/JWT/JWT.swift From 69866e1cb1f72d6a61ebaa45615f4bc6c4350ee7 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 01:59:31 +0200 Subject: [PATCH 22/62] refactor: Implement Compact JSON Coders --- JWT.xcodeproj/project.pbxproj | 8 ++++++++ Sources/JWT/Base64.swift | 2 +- Sources/JWT/CompactJSONDecoder.swift | 9 +++++++++ Sources/JWT/CompactJSONEncoder.swift | 9 +++++++++ Sources/JWT/Encode.swift | 4 +++- 5 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 Sources/JWT/CompactJSONDecoder.swift create mode 100644 Sources/JWT/CompactJSONEncoder.swift 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) From a678be236990dee411b0f80b6737d58c4d84cd6d Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 02:47:07 +0200 Subject: [PATCH 23/62] refactor: Make JOSEHeader Codable --- JWT.xcodeproj/project.pbxproj | 12 ++++-- Sources/JWT/CompactJSONDecoder.swift | 12 +++++- Sources/JWT/Decode.swift | 12 ++---- Sources/JWT/JOSEHeader.swift | 36 +++++++---------- Tests/JWTTests/CompactJSONDecoderTests.swift | 16 ++++++++ Tests/JWTTests/CompactJSONEncoderTests.swift | 23 +++++++++++ Tests/JWTTests/JOSEHeaderTests.swift | 42 -------------------- 7 files changed, 75 insertions(+), 78 deletions(-) create mode 100644 Tests/JWTTests/CompactJSONDecoderTests.swift create mode 100644 Tests/JWTTests/CompactJSONEncoderTests.swift delete mode 100644 Tests/JWTTests/JOSEHeaderTests.swift diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index f1e8625..3a210ac 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -11,9 +11,10 @@ 271E10811F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; 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 */; }; + 271E108D1F9041C400B5033C /* CompactJSONDecoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108C1F9041C400B5033C /* CompactJSONDecoderTests.swift */; }; + 271E108F1F9042E900B5033C /* CompactJSONEncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108E1F9042E900B5033C /* CompactJSONEncoderTests.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 */; }; @@ -70,9 +71,10 @@ /* 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 = ""; }; + 271E108C1F9041C400B5033C /* CompactJSONDecoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactJSONDecoderTests.swift; sourceTree = ""; }; + 271E108E1F9042E900B5033C /* CompactJSONEncoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactJSONEncoderTests.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 = ""; }; @@ -204,8 +206,9 @@ 279D63AB1AD07FFF0024E2BC /* Tests */ = { isa = PBXGroup; children = ( + 271E108C1F9041C400B5033C /* CompactJSONDecoderTests.swift */, + 271E108E1F9042E900B5033C /* CompactJSONEncoderTests.swift */, 279D63AE1AD07FFF0024E2BC /* JWTTests.swift */, - 271E10841F90274A00B5033C /* JOSEHeaderTests.swift */, 279D63AC1AD07FFF0024E2BC /* Supporting Files */, ); name = Tests; @@ -467,8 +470,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 271E108F1F9042E900B5033C /* CompactJSONEncoderTests.swift in Sources */, + 271E108D1F9041C400B5033C /* CompactJSONDecoderTests.swift in Sources */, 279D63AF1AD07FFF0024E2BC /* JWTTests.swift in Sources */, - 271E10851F90274A00B5033C /* JOSEHeaderTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/JWT/CompactJSONDecoder.swift b/Sources/JWT/CompactJSONDecoder.swift index 1d29309..0606395 100644 --- a/Sources/JWT/CompactJSONDecoder.swift +++ b/Sources/JWT/CompactJSONDecoder.swift @@ -1,9 +1,17 @@ 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() + throw InvalidToken.decodeError("data should contain only ASCII characters") } - return try super.decode(type, from: base64decode(string)!) + return try decode(type, from: string) + } + + func decode(_ type: T.Type, from string: String) throws -> T where T : Decodable { + guard let decoded = base64decode(string) else { + throw InvalidToken.decodeError("data should be a valid base64 string") + } + + return try super.decode(type, from: decoded) } } diff --git a/Sources/JWT/Decode.swift b/Sources/JWT/Decode.swift index 3054160..c04bad6 100644 --- a/Sources/JWT/Decode.swift +++ b/Sources/JWT/Decode.swift @@ -88,14 +88,8 @@ func load(_ jwt: String) throws -> (header: JOSEHeader, payload: ClaimSet, signa let signatureSegment = segments[2] let signatureInput = "\(headerSegment).\(payloadSegment)" - guard let headerData = base64decode(headerSegment) else { - throw InvalidToken.decodeError("Header is not correctly encoded as base64") - } - - let header = (try? JSONSerialization.jsonObject(with: headerData, options: JSONSerialization.ReadingOptions(rawValue: 0))) as? Payload - if header == nil { - throw InvalidToken.decodeError("Invalid header") - } + let decoder = CompactJSONDecoder() + let header = try decoder.decode(JOSEHeader.self, from: headerSegment) let payloadData = base64decode(payloadSegment) if payloadData == nil { @@ -111,7 +105,7 @@ func load(_ jwt: String) throws -> (header: JOSEHeader, payload: ClaimSet, signa throw InvalidToken.decodeError("Signature is not correctly encoded as base64") } - return (header: JOSEHeader(parameters: header!), payload: ClaimSet(claims: payload!), signature: signature, signatureInput: signatureInput) + return (header: header, payload: ClaimSet(claims: payload!), signature: signature, signatureInput: signatureInput) } // MARK: Signature Verification diff --git a/Sources/JWT/JOSEHeader.swift b/Sources/JWT/JOSEHeader.swift index 4bfcf49..de48742 100644 --- a/Sources/JWT/JOSEHeader.swift +++ b/Sources/JWT/JOSEHeader.swift @@ -9,30 +9,24 @@ import Foundation -struct JOSEHeader { - var parameters: [String: Any] - - init(parameters: [String: Any]) { - self.parameters = parameters +struct JOSEHeader: Codable { + var type: String? + var algorithm: String? + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + type = try container.decodeIfPresent(String.self, forKey: .type) + algorithm = try container.decodeIfPresent(String.self, forKey: .algorithm) } - var algorithm: String? { - get { - return parameters["alg"] as? String - } - - set { - parameters["alg"] = newValue - } + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(type, forKey: .type) + try container.encodeIfPresent(algorithm, forKey: .algorithm) } - var type: String? { - get { - return parameters["typ"] as? String - } - - set { - parameters["typ"] = newValue - } + enum CodingKeys: String, CodingKey { + case type = "typ" + case algorithm = "alg" } } diff --git a/Tests/JWTTests/CompactJSONDecoderTests.swift b/Tests/JWTTests/CompactJSONDecoderTests.swift new file mode 100644 index 0000000..ed1bf26 --- /dev/null +++ b/Tests/JWTTests/CompactJSONDecoderTests.swift @@ -0,0 +1,16 @@ +import XCTest +@testable import JWT + +class CompactJSONDecodable: Decodable { + let key: String +} + +class CompactJSONDecoderTests: XCTestCase { + let decoder = CompactJSONDecoder() + + func testDecoder() throws { + let expected = "eyJrZXkiOiJ2YWx1ZSJ9".data(using: .ascii)! + let value = try decoder.decode(CompactJSONDecodable.self, from: expected) + XCTAssertEqual(value.key, "value") + } +} diff --git a/Tests/JWTTests/CompactJSONEncoderTests.swift b/Tests/JWTTests/CompactJSONEncoderTests.swift new file mode 100644 index 0000000..a0f59cd --- /dev/null +++ b/Tests/JWTTests/CompactJSONEncoderTests.swift @@ -0,0 +1,23 @@ +import XCTest +@testable import JWT + +class CompactJSONEncodable: Encodable { + let key: String + + init(key: String) { + self.key = key + } +} + +class CompactJSONEncoderTests: XCTestCase { + let encoder = CompactJSONEncoder() + + func testEncode() throws { + let value = CompactJSONEncodable(key: "value") + + let encoded = try encoder.encode(value) + + XCTAssertEqual(encoded, "eyJrZXkiOiJ2YWx1ZSJ9".data(using: .ascii)!) + } +} + diff --git a/Tests/JWTTests/JOSEHeaderTests.swift b/Tests/JWTTests/JOSEHeaderTests.swift deleted file mode 100644 index 44af163..0000000 --- a/Tests/JWTTests/JOSEHeaderTests.swift +++ /dev/null @@ -1,42 +0,0 @@ -import XCTest -@testable import JWT - -class JOSEHeaderTests: XCTestCase { - // MARK: Algorithm - - func testGettingUnsetAlgoritm() { - let header = JOSEHeader(parameters: [:]) - XCTAssertNil(header.algorithm) - } - - func testGettingAlgoritm() { - let header = JOSEHeader(parameters: ["alg": "none"]) - XCTAssertEqual(header.algorithm, "none") - } - - func testSettingAlgoritm() { - var header = JOSEHeader(parameters: [:]) - - header.algorithm = "none" - XCTAssertEqual(header.algorithm, "none") - } - - // MARK: Type - - func testGettingUnsetType() { - let header = JOSEHeader(parameters: [:]) - XCTAssertNil(header.type) - } - - func testGettingType() { - let header = JOSEHeader(parameters: ["typ": "JWT"]) - XCTAssertEqual(header.type, "JWT") - } - - func testSettingType() { - var header = JOSEHeader(parameters: [:]) - - header.type = "JWT" - XCTAssertEqual(header.type, "JWT") - } -} From 28fc53d58b574828efe64c5653c8e120e633caa2 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 03:00:21 +0200 Subject: [PATCH 24/62] refactor: Add keyID and contentType to JOSEHeader --- Sources/JWT/JOSEHeader.swift | 44 ++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/Sources/JWT/JOSEHeader.swift b/Sources/JWT/JOSEHeader.swift index de48742..3e673e7 100644 --- a/Sources/JWT/JOSEHeader.swift +++ b/Sources/JWT/JOSEHeader.swift @@ -10,23 +10,59 @@ import Foundation struct JOSEHeader: Codable { - var type: String? + /// The "alg" (algorithm) identifies the cryptographic algorithm used to secure the JWS var algorithm: String? + /// jwu + // TODO + + /// jwk + // TODO + + /// The "kid" (key ID) is a hint indicating which key was used to secure the JWS + var keyID: String? + + /// x5u + // TODO + + /// x5c + // TODO + + /// x5t + // TODO + + /// x5t#S256 + // TODO + + /// The "typ" (type) is used by JWS applications to declare the media type [IANA.MediaTypes] of this complete JWS + var type: String? + + /// The "cty" (content type) is used by JWS application to declare the media type [IANA.MediaTypes] of the secured content (the payload). + var contentType: String? + + /// The "crit" (critical) indicates that extensions to JWS, JWE and/or [JWA] are being used that MUST be understood and processed + // TODO + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - type = try container.decodeIfPresent(String.self, forKey: .type) algorithm = try container.decodeIfPresent(String.self, forKey: .algorithm) + keyID = try container.decodeIfPresent(String.self, forKey: .keyID) + type = try container.decodeIfPresent(String.self, forKey: .type) + contentType = try container.decodeIfPresent(String.self, forKey: .contentType) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(type, forKey: .type) try container.encodeIfPresent(algorithm, forKey: .algorithm) + try container.encodeIfPresent(keyID, forKey: .keyID) + try container.encodeIfPresent(type, forKey: .type) + try container.encodeIfPresent(contentType, forKey: .contentType) } enum CodingKeys: String, CodingKey { - case type = "typ" case algorithm = "alg" + case keyID = "kid" + case type = "typ" + case contentType = "cty" } } From 1a829a4ea3ab4cb17ce1aefe39552b9a6c03be50 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 03:03:31 +0200 Subject: [PATCH 25/62] refactor: Don't provide blank options --- Sources/JWT/Base64.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/JWT/Base64.swift b/Sources/JWT/Base64.swift index f6bb78e..4a93f7f 100644 --- a/Sources/JWT/Base64.swift +++ b/Sources/JWT/Base64.swift @@ -2,12 +2,12 @@ import Foundation /// URI Safe base64 encode func base64encode(_ input: Data) -> String { - let data = input.base64EncodedData(options: NSData.Base64EncodingOptions(rawValue: 0)) + let data = input.base64EncodedData() let string = String(data: data, encoding: .utf8)! return string - .replacingOccurrences(of: "+", with: "-", options: NSString.CompareOptions(rawValue: 0), range: nil) - .replacingOccurrences(of: "/", with: "_", options: NSString.CompareOptions(rawValue: 0), range: nil) - .replacingOccurrences(of: "=", with: "", options: NSString.CompareOptions(rawValue: 0), range: nil) + .replacingOccurrences(of: "+", with: "-") + .replacingOccurrences(of: "/", with: "_") + .replacingOccurrences(of: "=", with: "") } /// URI Safe base64 decode @@ -20,8 +20,8 @@ func base64decode(_ input: String) -> Data? { ending = String(repeating: "=", count: amount) } - let base64 = input.replacingOccurrences(of: "-", with: "+", options: NSString.CompareOptions(rawValue: 0), range: nil) - .replacingOccurrences(of: "_", with: "/", options: NSString.CompareOptions(rawValue: 0), range: nil) + ending + let base64 = input.replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") + ending - return Data(base64Encoded: base64, options: NSData.Base64DecodingOptions(rawValue: 0)) + return Data(base64Encoded: base64) } From 71875415e2a8f3104acf33afc0873bf5d366bda0 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 03:11:33 +0200 Subject: [PATCH 26/62] refactor: Split tests into separate files --- JWT.xcodeproj/project.pbxproj | 24 ++- Tests/JWTTests/ClaimSetTests.swift | 79 +++++++ Tests/JWTTests/IntegrationTests.swift | 40 ++++ .../{JWTTests.swift => JWTDecodeTests.swift} | 202 ------------------ Tests/JWTTests/JWTEncodeTests.swift | 36 ++++ Tests/JWTTests/PayloadTests.swift | 54 +++++ 6 files changed, 229 insertions(+), 206 deletions(-) create mode 100644 Tests/JWTTests/ClaimSetTests.swift create mode 100644 Tests/JWTTests/IntegrationTests.swift rename Tests/JWTTests/{JWTTests.swift => JWTDecodeTests.swift} (60%) create mode 100644 Tests/JWTTests/JWTEncodeTests.swift create mode 100644 Tests/JWTTests/PayloadTests.swift diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index 3a210ac..3d926c3 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -15,6 +15,10 @@ 271E108B1F9034B100B5033C /* CompactJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */; }; 271E108D1F9041C400B5033C /* CompactJSONDecoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108C1F9041C400B5033C /* CompactJSONDecoderTests.swift */; }; 271E108F1F9042E900B5033C /* CompactJSONEncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108E1F9042E900B5033C /* CompactJSONEncoderTests.swift */; }; + 271E10911F90488700B5033C /* JWTEncodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10901F90488700B5033C /* JWTEncodeTests.swift */; }; + 271E10931F9049A400B5033C /* PayloadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10921F9049A400B5033C /* PayloadTests.swift */; }; + 271E10951F9049E200B5033C /* ClaimSetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10941F9049E200B5033C /* ClaimSetTests.swift */; }; + 271E10971F904A0700B5033C /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10961F904A0700B5033C /* IntegrationTests.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 */; }; @@ -37,7 +41,7 @@ 277794131DF22D0D00573F3E /* Encode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2777940F1DF22D0D00573F3E /* Encode.swift */; }; 279D63A21AD07FFF0024E2BC /* JWT.h in Headers */ = {isa = PBXBuildFile; fileRef = 279D63A11AD07FFF0024E2BC /* JWT.h */; settings = {ATTRIBUTES = (Public, ); }; }; 279D63A81AD07FFF0024E2BC /* JWT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279D639C1AD07FFF0024E2BC /* JWT.framework */; }; - 279D63AF1AD07FFF0024E2BC /* JWTTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279D63AE1AD07FFF0024E2BC /* JWTTests.swift */; }; + 279D63AF1AD07FFF0024E2BC /* JWTDecodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279D63AE1AD07FFF0024E2BC /* JWTDecodeTests.swift */; }; 520A71171C469F010005C709 /* Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71131C469F010005C709 /* Base64.swift */; }; 520A71181C469F010005C709 /* Claims.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71141C469F010005C709 /* Claims.swift */; }; 520A71191C469F010005C709 /* Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71151C469F010005C709 /* Decode.swift */; }; @@ -75,6 +79,10 @@ 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactJSONDecoder.swift; sourceTree = ""; }; 271E108C1F9041C400B5033C /* CompactJSONDecoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactJSONDecoderTests.swift; sourceTree = ""; }; 271E108E1F9042E900B5033C /* CompactJSONEncoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactJSONEncoderTests.swift; sourceTree = ""; }; + 271E10901F90488700B5033C /* JWTEncodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWTEncodeTests.swift; sourceTree = ""; }; + 271E10921F9049A400B5033C /* PayloadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadTests.swift; sourceTree = ""; }; + 271E10941F9049E200B5033C /* ClaimSetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClaimSetTests.swift; sourceTree = ""; }; + 271E10961F904A0700B5033C /* IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationTests.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 = ""; }; @@ -86,7 +94,7 @@ 279D63A11AD07FFF0024E2BC /* JWT.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JWT.h; sourceTree = ""; }; 279D63A71AD07FFF0024E2BC /* JWTTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JWTTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 279D63AD1AD07FFF0024E2BC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 279D63AE1AD07FFF0024E2BC /* JWTTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWTTests.swift; sourceTree = ""; }; + 279D63AE1AD07FFF0024E2BC /* JWTDecodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWTDecodeTests.swift; sourceTree = ""; }; 520A71131C469F010005C709 /* Base64.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Base64.swift; sourceTree = ""; }; 520A71141C469F010005C709 /* Claims.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Claims.swift; sourceTree = ""; }; 520A71151C469F010005C709 /* Decode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Decode.swift; sourceTree = ""; }; @@ -208,7 +216,11 @@ children = ( 271E108C1F9041C400B5033C /* CompactJSONDecoderTests.swift */, 271E108E1F9042E900B5033C /* CompactJSONEncoderTests.swift */, - 279D63AE1AD07FFF0024E2BC /* JWTTests.swift */, + 271E10941F9049E200B5033C /* ClaimSetTests.swift */, + 271E10921F9049A400B5033C /* PayloadTests.swift */, + 271E10901F90488700B5033C /* JWTEncodeTests.swift */, + 279D63AE1AD07FFF0024E2BC /* JWTDecodeTests.swift */, + 271E10961F904A0700B5033C /* IntegrationTests.swift */, 279D63AC1AD07FFF0024E2BC /* Supporting Files */, ); name = Tests; @@ -470,9 +482,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 271E10971F904A0700B5033C /* IntegrationTests.swift in Sources */, 271E108F1F9042E900B5033C /* CompactJSONEncoderTests.swift in Sources */, + 271E10911F90488700B5033C /* JWTEncodeTests.swift in Sources */, 271E108D1F9041C400B5033C /* CompactJSONDecoderTests.swift in Sources */, - 279D63AF1AD07FFF0024E2BC /* JWTTests.swift in Sources */, + 279D63AF1AD07FFF0024E2BC /* JWTDecodeTests.swift in Sources */, + 271E10931F9049A400B5033C /* PayloadTests.swift in Sources */, + 271E10951F9049E200B5033C /* ClaimSetTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tests/JWTTests/ClaimSetTests.swift b/Tests/JWTTests/ClaimSetTests.swift new file mode 100644 index 0000000..594e648 --- /dev/null +++ b/Tests/JWTTests/ClaimSetTests.swift @@ -0,0 +1,79 @@ +import XCTest +import JWT + +class ValidationTests: XCTestCase { + func testClaimJustExpiredWithoutLeeway() { + var claims = ClaimSet() + claims.expiration = Date().addingTimeInterval(-1) + + do { + try claims.validateExpiary() + XCTFail("InvalidToken.expiredSignature error should have been thrown.") + } catch InvalidToken.expiredSignature { + // Correct error thrown + } catch { + XCTFail("Unexpected error while validating exp claim.") + } + } + + func testClaimJustNotExpiredWithoutLeeway() { + var claims = ClaimSet() + claims.expiration = Date().addingTimeInterval(-1) + + do { + try claims.validateExpiary(leeway: 2) + } catch { + XCTFail("Unexpected error while validating exp claim that should be valid with leeway.") + } + } + + func testNotBeforeIsImmatureSignatureWithoutLeeway() { + var claims = ClaimSet() + claims.notBefore = Date().addingTimeInterval(1) + + do { + try claims.validateNotBefore() + XCTFail("InvalidToken.immatureSignature error should have been thrown.") + } catch InvalidToken.immatureSignature { + // Correct error thrown + } catch { + XCTFail("Unexpected error while validating nbf claim.") + } + } + + func testNotBeforeIsValidWithLeeway() { + var claims = ClaimSet() + claims.notBefore = Date().addingTimeInterval(1) + + do { + try claims.validateNotBefore(leeway: 2) + } catch { + XCTFail("Unexpected error while validating nbf claim that should be valid with leeway.") + } + } + + func testIssuedAtIsInFutureWithoutLeeway() { + var claims = ClaimSet() + claims.issuedAt = Date().addingTimeInterval(1) + + do { + try claims.validateIssuedAt() + XCTFail("InvalidToken.invalidIssuedAt error should have been thrown.") + } catch InvalidToken.invalidIssuedAt { + // Correct error thrown + } catch { + XCTFail("Unexpected error while validating iat claim.") + } + } + + func testIssuedAtIsValidWithLeeway() { + var claims = ClaimSet() + claims.issuedAt = Date().addingTimeInterval(1) + + do { + try claims.validateIssuedAt(leeway: 2) + } catch { + XCTFail("Unexpected error while validating iat claim that should be valid with leeway.") + } + } +} diff --git a/Tests/JWTTests/IntegrationTests.swift b/Tests/JWTTests/IntegrationTests.swift new file mode 100644 index 0000000..f15b9d9 --- /dev/null +++ b/Tests/JWTTests/IntegrationTests.swift @@ -0,0 +1,40 @@ +import XCTest +import JWT + +class IntegrationTests: XCTestCase { + func testVerificationFailureWithoutLeeway() { + let token = JWT.encode(.none) { builder in + builder.issuer = "fuller.li" + builder.audience = "cocoapods" + builder.expiration = Date().addingTimeInterval(-1) // Token expired one second ago + builder.notBefore = Date().addingTimeInterval(1) // Token starts being valid in one second + builder.issuedAt = Date().addingTimeInterval(1) // Token is issued one second in the future + } + + do { + let _ = try JWT.decode(token, algorithm: .none, leeway: 0) + XCTFail("InvalidToken error should have been thrown.") + } catch is InvalidToken { + // Correct error thrown + } catch { + XCTFail("Unexpected error type while verifying token.") + } + } + + func testVerificationSuccessWithLeeway() { + let token = JWT.encode(.none) { builder in + builder.issuer = "fuller.li" + builder.audience = "cocoapods" + builder.expiration = Date().addingTimeInterval(-1) // Token expired one second ago + builder.notBefore = Date().addingTimeInterval(1) // Token starts being valid in one second + builder.issuedAt = Date().addingTimeInterval(1) // Token is issued one second in the future + } + + do { + let _ = try JWT.decode(token, algorithm: .none, leeway: 2) + // Due to leeway no error gets thrown. + } catch { + XCTFail("Unexpected error type while verifying token.") + } + } +} diff --git a/Tests/JWTTests/JWTTests.swift b/Tests/JWTTests/JWTDecodeTests.swift similarity index 60% rename from Tests/JWTTests/JWTTests.swift rename to Tests/JWTTests/JWTDecodeTests.swift index b8ffe50..8286e6e 100644 --- a/Tests/JWTTests/JWTTests.swift +++ b/Tests/JWTTests/JWTDecodeTests.swift @@ -2,93 +2,6 @@ import Foundation import XCTest import JWT -class EncodeTests: XCTestCase { - func testEncodingJWT() { - let payload = ["name": "Kyle"] as Payload - let jwt = JWT.encode(payload, algorithm: .hs256("secret".data(using: .utf8)!)) - - let expected = [ - // { "alg": "HS256", "typ": "JWT" } - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS3lsZSJ9.zxm7xcp1eZtZhp4t-nlw09ATQnnFKIiSN83uG8u6cAg", - - // { "typ": "JWT", "alg": "HS256" } - "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiS3lsZSJ9.4tCpoxfyfjbUyLjm9_zu-r52Vxn6bFq9kp6Rt9xMs4A", - ] - - XCTAssertTrue(expected.contains(jwt)) - } - - func testEncodingWithBuilder() { - let algorithm = Algorithm.hs256("secret".data(using: .utf8)!) - let jwt = JWT.encode(algorithm) { builder in - builder.issuer = "fuller.li" - } - - assertSuccess(try JWT.decode(jwt, algorithm: algorithm)) { payload in - XCTAssertEqual(payload as! [String: String], ["iss": "fuller.li"]) - } - } - - func testEncodingClaimsWithHeaders() { - let algorithm = Algorithm.hs256("secret".data(using: .utf8)!) - let jwt = JWT.encode(claims: ClaimSet(), algorithm: algorithm, headers: ["kid": "x"]) - - XCTAssertEqual(jwt, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IngifQ.e30.ddEotxYYMMdat5HPgYFQnkHRdPXsxPG71ooyhIUoqGA") - } -} - -class PayloadTests: XCTestCase { - func testIssuer() { - _ = JWT.encode(.none) { builder in - builder.issuer = "fuller.li" - XCTAssertEqual(builder.issuer, "fuller.li") - XCTAssertEqual(builder["iss"] as? String, "fuller.li") - } - } - - func testAudience() { - _ = JWT.encode(.none) { builder in - builder.audience = "cocoapods" - XCTAssertEqual(builder.audience, "cocoapods") - XCTAssertEqual(builder["aud"] as? String, "cocoapods") - } - } - - func testExpiration() { - _ = JWT.encode(.none) { builder in - let date = Date(timeIntervalSince1970: Date().timeIntervalSince1970) - builder.expiration = date - XCTAssertEqual(builder.expiration, date) - XCTAssertEqual(builder["exp"] as? TimeInterval, date.timeIntervalSince1970) - } - } - - func testNotBefore() { - _ = JWT.encode(.none) { builder in - let date = Date(timeIntervalSince1970: Date().timeIntervalSince1970) - builder.notBefore = date - XCTAssertEqual(builder.notBefore, date) - XCTAssertEqual(builder["nbf"] as? TimeInterval, date.timeIntervalSince1970) - } - } - - func testIssuedAt() { - _ = JWT.encode(.none) { builder in - let date = Date(timeIntervalSince1970: Date().timeIntervalSince1970) - builder.issuedAt = date - XCTAssertEqual(builder.issuedAt, date) - XCTAssertEqual(builder["iat"] as? TimeInterval, date.timeIntervalSince1970) - } - } - - func testCustomAttributes() { - _ = JWT.encode(.none) { builder in - builder["user"] = "kyle" - XCTAssertEqual(builder["user"] as? String, "kyle") - } - } -} - class DecodeTests: XCTestCase { func testDecodingValidJWTAsClaimSet() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS3lsZSJ9.zxm7xcp1eZtZhp4t-nlw09ATQnnFKIiSN83uG8u6cAg" @@ -279,121 +192,6 @@ class DecodeTests: XCTestCase { } } -class ValidationTests: XCTestCase { - func testClaimJustExpiredWithoutLeeway() { - var claims = ClaimSet() - claims.expiration = Date().addingTimeInterval(-1) - - do { - try claims.validateExpiary() - XCTFail("InvalidToken.expiredSignature error should have been thrown.") - } catch InvalidToken.expiredSignature { - // Correct error thrown - } catch { - XCTFail("Unexpected error while validating exp claim.") - } - } - - func testClaimJustNotExpiredWithoutLeeway() { - var claims = ClaimSet() - claims.expiration = Date().addingTimeInterval(-1) - - do { - try claims.validateExpiary(leeway: 2) - } catch { - XCTFail("Unexpected error while validating exp claim that should be valid with leeway.") - } - } - - func testNotBeforeIsImmatureSignatureWithoutLeeway() { - var claims = ClaimSet() - claims.notBefore = Date().addingTimeInterval(1) - - do { - try claims.validateNotBefore() - XCTFail("InvalidToken.immatureSignature error should have been thrown.") - } catch InvalidToken.immatureSignature { - // Correct error thrown - } catch { - XCTFail("Unexpected error while validating nbf claim.") - } - } - - func testNotBeforeIsValidWithLeeway() { - var claims = ClaimSet() - claims.notBefore = Date().addingTimeInterval(1) - - do { - try claims.validateNotBefore(leeway: 2) - } catch { - XCTFail("Unexpected error while validating nbf claim that should be valid with leeway.") - } - } - - func testIssuedAtIsInFutureWithoutLeeway() { - var claims = ClaimSet() - claims.issuedAt = Date().addingTimeInterval(1) - - do { - try claims.validateIssuedAt() - XCTFail("InvalidToken.invalidIssuedAt error should have been thrown.") - } catch InvalidToken.invalidIssuedAt { - // Correct error thrown - } catch { - XCTFail("Unexpected error while validating iat claim.") - } - } - - func testIssuedAtIsValidWithLeeway() { - var claims = ClaimSet() - claims.issuedAt = Date().addingTimeInterval(1) - - do { - try claims.validateIssuedAt(leeway: 2) - } catch { - XCTFail("Unexpected error while validating iat claim that should be valid with leeway.") - } - } -} - -class IntegrationTests: XCTestCase { - func testVerificationFailureWithoutLeeway() { - let token = JWT.encode(.none) { builder in - builder.issuer = "fuller.li" - builder.audience = "cocoapods" - builder.expiration = Date().addingTimeInterval(-1) // Token expired one second ago - builder.notBefore = Date().addingTimeInterval(1) // Token starts being valid in one second - builder.issuedAt = Date().addingTimeInterval(1) // Token is issued one second in the future - } - - do { - let _ = try JWT.decode(token, algorithm: .none, leeway: 0) - XCTFail("InvalidToken error should have been thrown.") - } catch is InvalidToken { - // Correct error thrown - } catch { - XCTFail("Unexpected error type while verifying token.") - } - } - - func testVerificationSuccessWithLeeway() { - let token = JWT.encode(.none) { builder in - builder.issuer = "fuller.li" - builder.audience = "cocoapods" - builder.expiration = Date().addingTimeInterval(-1) // Token expired one second ago - builder.notBefore = Date().addingTimeInterval(1) // Token starts being valid in one second - builder.issuedAt = Date().addingTimeInterval(1) // Token is issued one second in the future - } - - do { - let _ = try JWT.decode(token, algorithm: .none, leeway: 2) - // Due to leeway no error gets thrown. - } catch { - XCTFail("Unexpected error type while verifying token.") - } - } -} - // MARK: Helpers func assertSuccess(_ decoder: @autoclosure () throws -> Payload, closure: ((Payload) -> Void)? = nil) { diff --git a/Tests/JWTTests/JWTEncodeTests.swift b/Tests/JWTTests/JWTEncodeTests.swift new file mode 100644 index 0000000..0dbb7b3 --- /dev/null +++ b/Tests/JWTTests/JWTEncodeTests.swift @@ -0,0 +1,36 @@ +import XCTest +import JWT + + +class JWTEncodeTests: XCTestCase { + func testEncodingJWT() { + let payload = ["name": "Kyle"] as Payload + let jwt = JWT.encode(claims: payload, algorithm: .hs256("secret".data(using: .utf8)!)) + + let expected = [ + // { "alg": "HS256", "typ": "JWT" } + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS3lsZSJ9.zxm7xcp1eZtZhp4t-nlw09ATQnnFKIiSN83uG8u6cAg", + + // { "typ": "JWT", "alg": "HS256" } + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiS3lsZSJ9.4tCpoxfyfjbUyLjm9_zu-r52Vxn6bFq9kp6Rt9xMs4A", + ] + + XCTAssertTrue(expected.contains(jwt)) + } + + func testEncodingWithBuilder() { + let algorithm = Algorithm.hs256("secret".data(using: .utf8)!) + let jwt = JWT.encode(algorithm) { builder in + builder.issuer = "fuller.li" + } + + XCTAssertEqual(jwt, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.d7B7PAQcz1E6oNhrlxmHxHXHgg39_k7X7wWeahl8kSQ") + } + + func testEncodingClaimsWithHeaders() { + let algorithm = Algorithm.hs256("secret".data(using: .utf8)!) + let jwt = JWT.encode(claims: ClaimSet(), algorithm: algorithm, headers: ["kid": "x"]) + + XCTAssertEqual(jwt, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IngifQ.e30.ddEotxYYMMdat5HPgYFQnkHRdPXsxPG71ooyhIUoqGA") + } +} diff --git a/Tests/JWTTests/PayloadTests.swift b/Tests/JWTTests/PayloadTests.swift new file mode 100644 index 0000000..150be11 --- /dev/null +++ b/Tests/JWTTests/PayloadTests.swift @@ -0,0 +1,54 @@ +import XCTest +import JWT + +class PayloadTests: XCTestCase { + func testIssuer() { + _ = JWT.encode(.none) { builder in + builder.issuer = "fuller.li" + XCTAssertEqual(builder.issuer, "fuller.li") + XCTAssertEqual(builder["iss"] as? String, "fuller.li") + } + } + + func testAudience() { + _ = JWT.encode(.none) { builder in + builder.audience = "cocoapods" + XCTAssertEqual(builder.audience, "cocoapods") + XCTAssertEqual(builder["aud"] as? String, "cocoapods") + } + } + + func testExpiration() { + _ = JWT.encode(.none) { builder in + let date = Date(timeIntervalSince1970: Date().timeIntervalSince1970) + builder.expiration = date + XCTAssertEqual(builder.expiration, date) + XCTAssertEqual(builder["exp"] as? TimeInterval, date.timeIntervalSince1970) + } + } + + func testNotBefore() { + _ = JWT.encode(.none) { builder in + let date = Date(timeIntervalSince1970: Date().timeIntervalSince1970) + builder.notBefore = date + XCTAssertEqual(builder.notBefore, date) + XCTAssertEqual(builder["nbf"] as? TimeInterval, date.timeIntervalSince1970) + } + } + + func testIssuedAt() { + _ = JWT.encode(.none) { builder in + let date = Date(timeIntervalSince1970: Date().timeIntervalSince1970) + builder.issuedAt = date + XCTAssertEqual(builder.issuedAt, date) + XCTAssertEqual(builder["iat"] as? TimeInterval, date.timeIntervalSince1970) + } + } + + func testCustomAttributes() { + _ = JWT.encode(.none) { builder in + builder["user"] = "kyle" + XCTAssertEqual(builder["user"] as? String, "kyle") + } + } +} From 7154710df7220d63ccd9ab049f32a569d6c32a37 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 03:27:31 +0200 Subject: [PATCH 27/62] refactor: Use XCT for validating raising --- Sources/JWT/ClaimSet.swift | 32 ++++++----- Tests/JWTTests/JWTDecodeTests.swift | 87 ++++++++++++++--------------- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/Sources/JWT/ClaimSet.swift b/Sources/JWT/ClaimSet.swift index 7dcf872..114c04e 100644 --- a/Sources/JWT/ClaimSet.swift +++ b/Sources/JWT/ClaimSet.swift @@ -1,5 +1,19 @@ import Foundation +func parseTimeInterval(_ value: Any?) -> Date? { + guard let value = value else { return nil } + + if let string = value as? String, let interval = TimeInterval(string) { + return Date(timeIntervalSince1970: interval) + } + + if let interval = value as? TimeInterval { + return Date(timeIntervalSince1970: interval) + } + + return nil +} + public struct ClaimSet { var claims: [String: Any] @@ -48,11 +62,7 @@ extension ClaimSet { public var expiration: Date? { get { - if let expiration = claims["exp"] as? TimeInterval { - return Date(timeIntervalSince1970: expiration) - } - - return nil + return parseTimeInterval(claims["exp"]) } set { @@ -62,11 +72,7 @@ extension ClaimSet { public var notBefore: Date? { get { - if let notBefore = claims["nbf"] as? TimeInterval { - return Date(timeIntervalSince1970: notBefore) - } - - return nil + return parseTimeInterval(claims["nbf"]) } set { @@ -76,11 +82,7 @@ extension ClaimSet { public var issuedAt: Date? { get { - if let issuedAt = claims["iat"] as? TimeInterval { - return Date(timeIntervalSince1970: issuedAt) - } - - return nil + return parseTimeInterval(claims["iat"]) } set { diff --git a/Tests/JWTTests/JWTDecodeTests.swift b/Tests/JWTTests/JWTDecodeTests.swift index 8286e6e..24a17b3 100644 --- a/Tests/JWTTests/JWTDecodeTests.swift +++ b/Tests/JWTTests/JWTDecodeTests.swift @@ -10,86 +10,85 @@ class DecodeTests: XCTestCase { XCTAssertEqual(claims["name"] as? String, "Kyle") } - func testDecodingValidJWT() { + func testDecodingValidJWT() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS3lsZSJ9.zxm7xcp1eZtZhp4t-nlw09ATQnnFKIiSN83uG8u6cAg" - assertSuccess(try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) { payload in - XCTAssertEqual(payload as! [String: String], ["name": "Kyle"]) - } + let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + XCTAssertEqual(claims["name"] as? String, "Kyle") } func testFailsToDecodeInvalidStringWithoutThreeSegments() { - assertDecodeError(try decode("a.b", algorithm: .none), error: "Not enough segments") + XCTAssertThrowsError(try decode("a.b", algorithm: .none), "Not enough segments") } // MARK: Disable verify - func testDisablingVerify() { + func testDisablingVerify() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w" - assertSuccess(try decode(jwt, algorithm: .none, verify: false, issuer: "fuller.li")) + _ = try decode(jwt, algorithm: .none, verify: false, issuer: "fuller.li") as ClaimSet } // MARK: Issuer claim - func testSuccessfulIssuerValidation() { + func testSuccessfulIssuerValidation() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.d7B7PAQcz1E6oNhrlxmHxHXHgg39_k7X7wWeahl8kSQ" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "fuller.li")) { payload in - XCTAssertEqual(payload as! [String: String], ["iss": "fuller.li"]) - } + + let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + XCTAssertEqual(claims.issuer, "fuller.li") } func testIncorrectIssuerValidation() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.wOhJ9_6lx-3JGJPmJmtFCDI3kt7uMAMmhHIslti7ryI" - assertFailure(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "querykit.org")) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "querykit.org")) } func testMissingIssuerValidation() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w" - assertFailure(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "fuller.li")) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "fuller.li")) } // MARK: Expiration claim func testExpiredClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0MjgxODg0OTF9.cy6b2szsNkKnHFnz2GjTatGjoHBTs8vBKnPGZgpp91I" - assertFailure(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } func testInvalidExpiaryClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOlsiMTQyODE4ODQ5MSJdfQ.OwF-wd3THjxrEGUhh6IdnNhxQZ7ydwJ3Z6J_dfl9MBs" - assertFailure(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } - func testUnexpiredClaim() { + func testUnexpiredClaim() throws { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjgxODg0OTF9.EW7k-8Mvnv0GpvOKJalFRLoCB3a3xGG3i7hAZZXNAz0" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) { payload in - XCTAssertEqual(payload as! [String: Int], ["exp": 1728188491]) - } + + let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + XCTAssertEqual(claims.expiration?.timeIntervalSince1970, 1728188491) } - func testUnexpiredClaimString() { + func testUnexpiredClaimString() throws { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNzI4MTg4NDkxIn0.y4w7lNLrfRRPzuNUfM-ZvPkoOtrTU_d8ZVYasLdZGpk" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) { payload in - XCTAssertEqual(payload as! [String: String], ["exp": "1728188491"]) - } + + let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + XCTAssertEqual(claims.expiration?.timeIntervalSince1970, 1728188491) } // MARK: Not before claim - func testNotBeforeClaim() { + func testNotBeforeClaim() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0MjgxODk3MjB9.jFT0nXAJvEwyG6R7CMJlzNJb7FtZGv30QRZpYam5cvs" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) { payload in - XCTAssertEqual(payload as! [String: Int], ["nbf": 1428189720]) - } + + let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + XCTAssertEqual(claims.notBefore?.timeIntervalSince1970, 1428189720) } - func testNotBeforeClaimString() { + func testNotBeforeClaimString() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOiIxNDI4MTg5NzIwIn0.qZsj36irdmIAeXv6YazWDSFbpuxHtEh4Deof5YTpnVI" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) { payload in - XCTAssertEqual(payload as! [String: String], ["nbf": "1428189720"]) - } + + let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + XCTAssertEqual(claims.notBefore?.timeIntervalSince1970, 1428189720) } func testInvalidNotBeforeClaim() { @@ -100,29 +99,29 @@ class DecodeTests: XCTestCase { func testUnmetNotBeforeClaim() { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3MjgxODg0OTF9.Tzhu1tu-7BXcF5YEIFFE1Vmg4tEybUnaz58FR4PcblQ" - assertFailure(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } // MARK: Issued at claim - func testIssuedAtClaimInThePast() { + func testIssuedAtClaimInThePast() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MjgxODk3MjB9.I_5qjRcCUZVQdABLwG82CSuu2relSdIyJOyvXWUAJh4" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) { payload in - XCTAssertEqual(payload as! [String: Int], ["iat": 1428189720]) - } + + let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + XCTAssertEqual(claims.issuedAt?.timeIntervalSince1970, 1428189720) } - func testIssuedAtClaimInThePastString() { + func testIssuedAtClaimInThePastString() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNDI4MTg5NzIwIn0.M8veWtsY52oBwi7LRKzvNnzhjK0QBS8Su1r0atlns2k" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) { payload in - XCTAssertEqual(payload as! [String: String], ["iat": "1428189720"]) - } + + let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + XCTAssertEqual(claims.issuedAt?.timeIntervalSince1970, 1428189720) } func testIssuedAtClaimInTheFuture() { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MjgxODg0OTF9.owHiJyJmTcW1lBW5y_Rz3iBfSbcNiXlbZ2fY9qR7-aU" - assertFailure(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } func testInvalidIssuedAtClaim() { @@ -150,12 +149,12 @@ class DecodeTests: XCTestCase { func testMismatchAudienceClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJreWxlIn0.VEB_n06pTSLlTXPFkc46ARADJ9HXNUBUPo3VhL9RDe4" // kyle - assertFailure(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine")) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine")) } func testMissingAudienceClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w" - assertFailure(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle")) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle")) } // MARK: Signature verification @@ -169,7 +168,7 @@ class DecodeTests: XCTestCase { func testNoneFailsWithSecretAlgorithm() { let jwt = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ0ZXN0IjoiaW5nIn0." - assertFailure(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } func testMatchesAnyAlgorithm() { From 087e6e71f35c02cc722492650e76063e25c22628 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 09:02:39 +0200 Subject: [PATCH 28/62] refactor: Move payload deseriaisation to decoder --- Sources/JWT/CompactJSONDecoder.swift | 15 +++++++++++++++ Sources/JWT/Decode.swift | 13 ++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Sources/JWT/CompactJSONDecoder.swift b/Sources/JWT/CompactJSONDecoder.swift index 0606395..bb353d5 100644 --- a/Sources/JWT/CompactJSONDecoder.swift +++ b/Sources/JWT/CompactJSONDecoder.swift @@ -1,3 +1,5 @@ +import Foundation + 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 { @@ -14,4 +16,17 @@ class CompactJSONDecoder: JSONDecoder { return try super.decode(type, from: decoded) } + + func decode(from string: String) throws -> Payload { + guard let decoded = base64decode(string) else { + throw InvalidToken.decodeError("Payload is not correctly encoded as base64") + } + + let object = try JSONSerialization.jsonObject(with: decoded) + guard let payload = object as? Payload else { + throw InvalidToken.decodeError("Invalid payload") + } + + return payload + } } diff --git a/Sources/JWT/Decode.swift b/Sources/JWT/Decode.swift index c04bad6..5bfa569 100644 --- a/Sources/JWT/Decode.swift +++ b/Sources/JWT/Decode.swift @@ -90,22 +90,13 @@ func load(_ jwt: String) throws -> (header: JOSEHeader, payload: ClaimSet, signa let decoder = CompactJSONDecoder() let header = try decoder.decode(JOSEHeader.self, from: headerSegment) - - let payloadData = base64decode(payloadSegment) - if payloadData == nil { - throw InvalidToken.decodeError("Payload is not correctly encoded as base64") - } - - let payload = (try? JSONSerialization.jsonObject(with: payloadData!, options: JSONSerialization.ReadingOptions(rawValue: 0))) as? Payload - if payload == nil { - throw InvalidToken.decodeError("Invalid payload") - } + let payload = try decoder.decode(from: payloadSegment) guard let signature = base64decode(signatureSegment) else { throw InvalidToken.decodeError("Signature is not correctly encoded as base64") } - return (header: header, payload: ClaimSet(claims: payload!), signature: signature, signatureInput: signatureInput) + return (header: header, payload: ClaimSet(claims: payload), signature: signature, signatureInput: signatureInput) } // MARK: Signature Verification From f60df5b2bdd5963e55adbc030394cfcd54c447b6 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 09:05:26 +0200 Subject: [PATCH 29/62] refactor: Move encoding to compact encoder --- Sources/JWT/CompactJSONEncoder.swift | 8 ++++++++ Sources/JWT/Encode.swift | 10 +--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Sources/JWT/CompactJSONEncoder.swift b/Sources/JWT/CompactJSONEncoder.swift index c3e454f..f759453 100644 --- a/Sources/JWT/CompactJSONEncoder.swift +++ b/Sources/JWT/CompactJSONEncoder.swift @@ -6,4 +6,12 @@ class CompactJSONEncoder: JSONEncoder { func encodeString(_ value: T) throws -> String { return base64encode(try super.encode(value)) } + + func encodeString(_ value: [String: Any]) -> String? { + if let data = try? JSONSerialization.data(withJSONObject: value) { + return base64encode(data) + } + + return nil + } } diff --git a/Sources/JWT/Encode.swift b/Sources/JWT/Encode.swift index 3c5bb68..0aaf196 100644 --- a/Sources/JWT/Encode.swift +++ b/Sources/JWT/Encode.swift @@ -8,14 +8,6 @@ import Foundation 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) - } - - return nil - } - var headers = headers ?? [:] if !headers.keys.contains("typ") { headers["typ"] = "JWT" @@ -23,7 +15,7 @@ public func encode(claims: ClaimSet, algorithm: Algorithm, headers: [String: Str headers["alg"] = algorithm.description let header = try! encoder.encodeString(headers) - let payload = encodeJSON(claims.claims)! + let payload = encoder.encodeString(claims.claims)! let signingInput = "\(header).\(payload)" let signature = algorithm.sign(signingInput) return "\(signingInput).\(signature)" From d55e7b7fde24dd0fec3daba49689de44629ea1cd Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 13 Oct 2017 09:37:10 +0200 Subject: [PATCH 30/62] chore: Update CI to Swift 4 The library no longer supports Swift 3 in this version. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 41fcf91..c7f1e9e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,9 @@ os: language: generic sudo: required dist: trusty -osx_image: xcode8.3 +osx_image: xcode9 env: -- SWIFT_VERSION=3.1.1 +- SWIFT_VERSION=4.0 install: - if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"; fi - git submodule update --init --recursive From 9045d647eec6f37b6d536243e3ad02c9a12411e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Hern=C3=A1ndez?= Date: Thu, 2 Nov 2017 17:58:57 +0100 Subject: [PATCH 31/62] fix(project): Add missing files to macOS, tvOS, watchOS targets (#94) --- JWT.xcodeproj/project.pbxproj | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj index 3d926c3..6c895b0 100644 --- a/JWT.xcodeproj/project.pbxproj +++ b/JWT.xcodeproj/project.pbxproj @@ -42,6 +42,12 @@ 279D63A21AD07FFF0024E2BC /* JWT.h in Headers */ = {isa = PBXBuildFile; fileRef = 279D63A11AD07FFF0024E2BC /* JWT.h */; settings = {ATTRIBUTES = (Public, ); }; }; 279D63A81AD07FFF0024E2BC /* JWT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279D639C1AD07FFF0024E2BC /* JWT.framework */; }; 279D63AF1AD07FFF0024E2BC /* JWTDecodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279D63AE1AD07FFF0024E2BC /* JWTDecodeTests.swift */; }; + 501BF92F1FAB05AE00449B76 /* CompactJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */; }; + 501BF9301FAB05C500449B76 /* CompactJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */; }; + 501BF9311FAB05E400449B76 /* CompactJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */; }; + 501BF9321FAB05E400449B76 /* CompactJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */; }; + 501BF9331FAB05E700449B76 /* CompactJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */; }; + 501BF9341FAB05E700449B76 /* CompactJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */; }; 520A71171C469F010005C709 /* Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71131C469F010005C709 /* Base64.swift */; }; 520A71181C469F010005C709 /* Claims.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71141C469F010005C709 /* Claims.swift */; }; 520A71191C469F010005C709 /* Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71151C469F010005C709 /* Decode.swift */; }; @@ -499,12 +505,14 @@ 271E10811F90253300B5033C /* JWA.swift in Sources */, 273011171F34029900219C35 /* HMACCommonCrypto.swift in Sources */, CD9B62171C7753D8005D4844 /* Claims.swift in Sources */, + 501BF92F1FAB05AE00449B76 /* CompactJSONEncoder.swift in Sources */, CD9B62181C7753D8005D4844 /* JWT.swift in Sources */, CD9B62191C7753D8005D4844 /* Decode.swift in Sources */, 277794111DF22D0D00573F3E /* Encode.swift in Sources */, 2777940C1DF22BE400573F3E /* JOSEHeader.swift in Sources */, 277794061DF221F800573F3E /* ClaimSet.swift in Sources */, 273011001F33EABA00219C35 /* HMAC.swift in Sources */, + 501BF9301FAB05C500449B76 /* CompactJSONDecoder.swift in Sources */, CD9B621A1C7753D8005D4844 /* Base64.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -516,12 +524,14 @@ 271E10821F90253300B5033C /* JWA.swift in Sources */, 273011181F34029A00219C35 /* HMACCommonCrypto.swift in Sources */, CD9B62291C7753EC005D4844 /* Claims.swift in Sources */, + 501BF9311FAB05E400449B76 /* CompactJSONEncoder.swift in Sources */, CD9B622A1C7753EC005D4844 /* JWT.swift in Sources */, CD9B622B1C7753EC005D4844 /* Decode.swift in Sources */, 277794121DF22D0D00573F3E /* Encode.swift in Sources */, 2777940D1DF22BE400573F3E /* JOSEHeader.swift in Sources */, 277794071DF221F800573F3E /* ClaimSet.swift in Sources */, 273011011F33EABA00219C35 /* HMAC.swift in Sources */, + 501BF9331FAB05E700449B76 /* CompactJSONDecoder.swift in Sources */, CD9B622C1C7753EC005D4844 /* Base64.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -533,12 +543,14 @@ 271E10831F90253300B5033C /* JWA.swift in Sources */, 273011191F34029A00219C35 /* HMACCommonCrypto.swift in Sources */, CD9B623B1C7753FB005D4844 /* Claims.swift in Sources */, + 501BF9321FAB05E400449B76 /* CompactJSONEncoder.swift in Sources */, CD9B623C1C7753FB005D4844 /* JWT.swift in Sources */, CD9B623D1C7753FB005D4844 /* Decode.swift in Sources */, 277794131DF22D0D00573F3E /* Encode.swift in Sources */, 2777940E1DF22BE400573F3E /* JOSEHeader.swift in Sources */, 277794081DF221F800573F3E /* ClaimSet.swift in Sources */, 273011021F33EABA00219C35 /* HMAC.swift in Sources */, + 501BF9341FAB05E700449B76 /* CompactJSONDecoder.swift in Sources */, CD9B623E1C7753FB005D4844 /* Base64.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; From 36f4ee0e60faa0068c1a8290d25f4428e67a56c0 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 31 Jan 2018 00:39:41 +0000 Subject: [PATCH 32/62] chore(ci): Allow CocoaPods warnings The warning is usually about not supplying the Swift version. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c7f1e9e..20995c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,4 +16,4 @@ script: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-iOS build -sdk iphonesimulator; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-tvOS build -sdk appletvsimulator; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-watchOS build -sdk watchsimulator; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pod lib lint; fi +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pod lib lint --allow-warnings; fi From e2052f2ab8afdeaa564c17c8368948b3fe899f0a Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 31 Jan 2018 00:44:50 +0000 Subject: [PATCH 33/62] fix: Build error caused when Foundation is not present By default when building via Xcode Foundation does not need to be imported --- Sources/JWT/CompactJSONEncoder.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/JWT/CompactJSONEncoder.swift b/Sources/JWT/CompactJSONEncoder.swift index f759453..2e4a10c 100644 --- a/Sources/JWT/CompactJSONEncoder.swift +++ b/Sources/JWT/CompactJSONEncoder.swift @@ -1,3 +1,6 @@ +import Foundation + + class CompactJSONEncoder: JSONEncoder { override func encode(_ value: T) throws -> Data { return try encodeString(value).data(using: .ascii) ?? Data() From b7188dc07c5a66267e67a7d87ba77ee009e2ddd8 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 31 Jan 2018 00:49:22 +0000 Subject: [PATCH 34/62] fix: Upgrade to CryptoSwift 0.8.0 --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 707de2f..240d007 100644 --- a/Package.swift +++ b/Package.swift @@ -15,7 +15,7 @@ let package = Package( let package = Package( name: "JWT", dependencies: [ - .Package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", majorVersion: 0, minor: 6), + .Package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", majorVersion: 0, minor: 8), ], exclude: [ "Sources/JWT/HMACCommonCrypto.swift", From d9a419a18a689cb0d8b263348b73f5ef28562f76 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 7 Feb 2018 09:14:23 +0000 Subject: [PATCH 35/62] docs: Always force unwrap the known valid UTF8 key Closes #101 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce1db66..0874ddd 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ claims.issuer = "fuller.li" claims.issuedAt = Date() claims["custom"] = "Hi" -JWT.encode(claims: claims, algorithm: .hs256("secret".data(using: .utf8))) +JWT.encode(claims: claims, algorithm: .hs256("secret".data(using: .utf8)!)) ``` #### Building a JWT with the builder pattern From 9d057e72ec4829e5403e22587dc4a61347accdcc Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 7 Feb 2018 21:21:56 +0000 Subject: [PATCH 36/62] feat: Extract algorithms to JWA --- JSONWebToken.podspec | 7 ++- Package.swift | 37 +++++++++------ Sources/JWA/HMAC/HMAC.swift | 36 ++++++++++++++ Sources/JWA/HMAC/HMACCommonCrypto.swift | 48 +++++++++++++++++++ Sources/JWA/HMAC/HMACCryptoSwift.swift | 32 +++++++++++++ Sources/JWA/JWA.swift | 32 +++++++++++++ Sources/JWA/None.swift | 15 ++++++ Sources/JWT/Algorithm.swift | 36 ++++++++++++++ Sources/JWT/Decode.swift | 2 +- Sources/JWT/Encode.swift | 3 +- Sources/JWT/HMAC.swift | 7 --- Sources/JWT/HMACCommonCrypto.swift | 46 ------------------ Sources/JWT/HMACCryptoSwift.swift | 28 ----------- Sources/JWT/JWA.swift | 57 ---------------------- Tests/JWATests/HMACTests.swift | 63 +++++++++++++++++++++++++ Tests/JWATests/NoneTests.swift | 23 +++++++++ 16 files changed, 316 insertions(+), 156 deletions(-) create mode 100644 Sources/JWA/HMAC/HMAC.swift create mode 100644 Sources/JWA/HMAC/HMACCommonCrypto.swift create mode 100644 Sources/JWA/HMAC/HMACCryptoSwift.swift create mode 100644 Sources/JWA/JWA.swift create mode 100644 Sources/JWA/None.swift create mode 100644 Sources/JWT/Algorithm.swift delete mode 100644 Sources/JWT/HMAC.swift delete mode 100644 Sources/JWT/HMACCommonCrypto.swift delete mode 100644 Sources/JWT/HMACCryptoSwift.swift delete mode 100644 Sources/JWT/JWA.swift create mode 100644 Tests/JWATests/HMACTests.swift create mode 100644 Tests/JWATests/NoneTests.swift diff --git a/JSONWebToken.podspec b/JSONWebToken.podspec index 3ce74ef..1d0094d 100644 --- a/JSONWebToken.podspec +++ b/JSONWebToken.podspec @@ -6,14 +6,17 @@ Pod::Spec.new do |spec| spec.license = { :type => 'BSD', :file => 'LICENSE' } spec.author = { 'Kyle Fuller' => 'kyle@fuller.li' } spec.source = { :git => 'https://github.com/kylef/JSONWebToken.swift.git', :tag => "#{spec.version}" } - spec.source_files = 'Sources/JWT/*.swift' + spec.source_files = [ + 'Sources/JWA/HMAC/*.swift', + 'Sources/{JWA,JWT}/*.swift', + ] spec.ios.deployment_target = '8.0' spec.osx.deployment_target = '10.9' spec.tvos.deployment_target = '9.0' spec.watchos.deployment_target = '2.0' spec.requires_arc = true spec.module_name = 'JWT' - spec.exclude_files = ['Sources/JWT/HMACCryptoSwift.swift'] + spec.exclude_files = ['Sources/JWA/HMAC/HMACCryptoSwift.swift'] if ARGV.include?('lint') spec.pod_target_xcconfig = { diff --git a/Package.swift b/Package.swift index 240d007..5ba29b4 100644 --- a/Package.swift +++ b/Package.swift @@ -1,24 +1,33 @@ +// swift-tools-version:4.0 + import PackageDescription #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) -let package = Package( - name: "JWT", - dependencies: [ - .Package(url: "https://github.com/kylef-archive/CommonCrypto.git", majorVersion: 1), - ], - exclude: [ - "Sources/JWT/HMACCryptoSwift.swift", - ] -) +let dependencies = [ + Package.Dependency.package(url: "https://github.com/kylef-archive/CommonCrypto.git", from: "1.0.0"), +] +let excludes = ["HMAC/HMACCryptoSwift.swift"] +let targetDependencies: [Target.Dependency] = [] #else +let dependencies = [ + Package.Dependency.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "0.8.0"), +] +let excludes = ["HMAC/HMACCommonCrypto.swift"] +let targetDependencies: [Target.Dependency] = ["CryptoSwift"] +#endif + + let package = Package( name: "JWT", - dependencies: [ - .Package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", majorVersion: 0, minor: 8), + products: [ + .library(name: "JWT", targets: ["JWT"]), ], - exclude: [ - "Sources/JWT/HMACCommonCrypto.swift", + dependencies: dependencies, + targets: [ + .target(name: "JWA", dependencies: targetDependencies, exclude: excludes), + .target(name: "JWT", dependencies: ["JWA"]), + .testTarget(name: "JWATests", dependencies: ["JWA"]), + .testTarget(name: "JWTTests", dependencies: ["JWT"]), ] ) -#endif diff --git a/Sources/JWA/HMAC/HMAC.swift b/Sources/JWA/HMAC/HMAC.swift new file mode 100644 index 0000000..9252a03 --- /dev/null +++ b/Sources/JWA/HMAC/HMAC.swift @@ -0,0 +1,36 @@ +import Foundation + + +final public class HMACAlgorithm: Algorithm { + public let key: Data + public let hash: Hash + + public enum Hash { + case sha256 + case sha384 + case sha512 + } + + public init(key: Data, hash: Hash) { + self.key = key + self.hash = hash + } + + public init?(key: String, hash: Hash) { + guard let key = key.data(using: .utf8) else { return nil } + + self.key = key + self.hash = hash + } + + public var name: String { + switch hash { + case .sha256: + return "HS256" + case .sha384: + return "HS384" + case .sha512: + return "HS512" + } + } +} diff --git a/Sources/JWA/HMAC/HMACCommonCrypto.swift b/Sources/JWA/HMAC/HMACCommonCrypto.swift new file mode 100644 index 0000000..299fd8a --- /dev/null +++ b/Sources/JWA/HMAC/HMACCommonCrypto.swift @@ -0,0 +1,48 @@ +import Foundation +import CommonCrypto + + +extension HMACAlgorithm: SignAlgorithm, VerifyAlgorithm { + public func sign(_ message: Data) -> Data { + let context = UnsafeMutablePointer.allocate(capacity: 1) + defer { context.deallocate(capacity: 1) } + + key.withUnsafeBytes() { (buffer: UnsafePointer) in + CCHmacInit(context, hash.commonCryptoAlgorithm, buffer, size_t(key.count)) + } + + message.withUnsafeBytes { (buffer: UnsafePointer) in + CCHmacUpdate(context, buffer, size_t(message.count)) + } + + var hmac = Array(repeating: 0, count: Int(hash.commonCryptoDigestLength)) + CCHmacFinal(context, &hmac) + + return Data(hmac) + } +} + + +extension HMACAlgorithm.Hash { + var commonCryptoAlgorithm: CCHmacAlgorithm { + switch self { + case .sha256: + return CCHmacAlgorithm(kCCHmacAlgSHA256) + case .sha384: + return CCHmacAlgorithm(kCCHmacAlgSHA384) + case .sha512: + return CCHmacAlgorithm(kCCHmacAlgSHA512) + } + } + + var commonCryptoDigestLength: Int32 { + switch self { + case .sha256: + return CC_SHA256_DIGEST_LENGTH + case .sha384: + return CC_SHA384_DIGEST_LENGTH + case .sha512: + return CC_SHA512_DIGEST_LENGTH + } + } +} diff --git a/Sources/JWA/HMAC/HMACCryptoSwift.swift b/Sources/JWA/HMAC/HMACCryptoSwift.swift new file mode 100644 index 0000000..6153049 --- /dev/null +++ b/Sources/JWA/HMAC/HMACCryptoSwift.swift @@ -0,0 +1,32 @@ +import Foundation +import CryptoSwift + + +extension HMACAlgorithm: SignAlgorithm, VerifyAlgorithm { + public func sign(_ message: Data) -> Data { + let mac = HMAC(key: key.bytes, variant: hash.cryptoSwiftVariant) + + let result: [UInt8] + do { + result = try mac.authenticate(message.bytes) + } catch { + result = [] + } + + return Data(bytes: result) + } +} + + +extension HMACAlgorithm.Hash { + var cryptoSwiftVariant: HMAC.Variant { + switch self { + case .sha256: + return .sha256 + case .sha384: + return .sha384 + case .sha512: + return .sha512 + } + } +} diff --git a/Sources/JWA/JWA.swift b/Sources/JWA/JWA.swift new file mode 100644 index 0000000..2e02f7d --- /dev/null +++ b/Sources/JWA/JWA.swift @@ -0,0 +1,32 @@ +import Foundation + + +/// Represents a JSON Web Algorithm (JWA) +/// https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40 +public protocol Algorithm: class { + var name: String { get } +} + + +// MARK: Signing + +/// Represents a JSON Web Algorithm (JWA) that is capable of signing +public protocol SignAlgorithm: Algorithm { + func sign(_ message: Data) -> Data +} + + +// MARK: Verifying + +/// Represents a JSON Web Algorithm (JWA) that is capable of verifying +public protocol VerifyAlgorithm: Algorithm { + func verify(_ message: Data, signature: Data) -> Bool +} + + +extension SignAlgorithm { + /// Verify a signature for a message using the algorithm + public func verify(_ message: Data, signature: Data) -> Bool { + return sign(message) == signature + } +} diff --git a/Sources/JWA/None.swift b/Sources/JWA/None.swift new file mode 100644 index 0000000..26a238d --- /dev/null +++ b/Sources/JWA/None.swift @@ -0,0 +1,15 @@ +import Foundation + + +/// No Algorithm, i-e, insecure +public final class NoneAlgorithm: Algorithm, SignAlgorithm, VerifyAlgorithm { + public var name: String { + return "none" + } + + public init() {} + + public func sign(_ message: Data) -> Data { + return Data() + } +} diff --git a/Sources/JWT/Algorithm.swift b/Sources/JWT/Algorithm.swift new file mode 100644 index 0000000..f1d1e91 --- /dev/null +++ b/Sources/JWT/Algorithm.swift @@ -0,0 +1,36 @@ +import Foundation +import JWA + + +/// Represents a JSON Web Algorithm (JWA) +/// https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40 +public enum Algorithm: CustomStringConvertible { + /// No Algorithm, i-e, insecure + case none + + /// HMAC using SHA-256 hash algorithm + case hs256(Data) + + /// HMAC using SHA-384 hash algorithm + case hs384(Data) + + /// HMAC using SHA-512 hash algorithm + case hs512(Data) + + var algorithm: SignAlgorithm { + switch self { + case .none: + return NoneAlgorithm() + case .hs256(let key): + return HMACAlgorithm(key: key, hash: .sha256) + case .hs384(let key): + return HMACAlgorithm(key: key, hash: .sha384) + case .hs512(let key): + return HMACAlgorithm(key: key, hash: .sha512) + } + } + + public var description: String { + return algorithm.name + } +} diff --git a/Sources/JWT/Decode.swift b/Sources/JWT/Decode.swift index 5bfa569..0e2b6d0 100644 --- a/Sources/JWT/Decode.swift +++ b/Sources/JWT/Decode.swift @@ -108,7 +108,7 @@ func verifySignature(_ algorithms: [Algorithm], header: JOSEHeader, signingInput let verifiedAlgorithms = algorithms .filter { algorithm in algorithm.description == alg } - .filter { algorithm in algorithm.verify(signingInput, signature: signature) } + .filter { algorithm in algorithm.algorithm.verify(signingInput.data(using: .utf8)!, signature: signature) } if verifiedAlgorithms.isEmpty { throw InvalidToken.invalidAlgorithm diff --git a/Sources/JWT/Encode.swift b/Sources/JWT/Encode.swift index 0aaf196..643c827 100644 --- a/Sources/JWT/Encode.swift +++ b/Sources/JWT/Encode.swift @@ -1,5 +1,6 @@ import Foundation + /*** Encode a set of claims - parameter claims: The set of claims - parameter algorithm: The algorithm to sign the payload with @@ -17,7 +18,7 @@ public func encode(claims: ClaimSet, algorithm: Algorithm, headers: [String: Str let header = try! encoder.encodeString(headers) let payload = encoder.encodeString(claims.claims)! let signingInput = "\(header).\(payload)" - let signature = algorithm.sign(signingInput) + let signature = base64encode(algorithm.algorithm.sign(signingInput.data(using: .utf8)!)) return "\(signingInput).\(signature)" } diff --git a/Sources/JWT/HMAC.swift b/Sources/JWT/HMAC.swift deleted file mode 100644 index 2e9c66a..0000000 --- a/Sources/JWT/HMAC.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -enum HMACAlgorithm { - case sha256 - case sha384 - case sha512 -} diff --git a/Sources/JWT/HMACCommonCrypto.swift b/Sources/JWT/HMACCommonCrypto.swift deleted file mode 100644 index a144ccb..0000000 --- a/Sources/JWT/HMACCommonCrypto.swift +++ /dev/null @@ -1,46 +0,0 @@ -import Foundation -import CommonCrypto - - -extension HMACAlgorithm { - var commonCryptoAlgorithm: CCHmacAlgorithm { - switch self { - case .sha256: - return CCHmacAlgorithm(kCCHmacAlgSHA256) - case .sha384: - return CCHmacAlgorithm(kCCHmacAlgSHA384) - case .sha512: - return CCHmacAlgorithm(kCCHmacAlgSHA512) - } - } - - var commonCryptoDigestLength: Int32 { - switch self { - case .sha256: - return CC_SHA256_DIGEST_LENGTH - case .sha384: - return CC_SHA384_DIGEST_LENGTH - case .sha512: - return CC_SHA512_DIGEST_LENGTH - } - } -} - - -func hmac(algorithm: HMACAlgorithm, key: Data, message: Data) -> Data { - let context = UnsafeMutablePointer.allocate(capacity: 1) - defer { context.deallocate(capacity: 1) } - - key.withUnsafeBytes() { (buffer: UnsafePointer) in - CCHmacInit(context, algorithm.commonCryptoAlgorithm, buffer, size_t(key.count)) - } - - message.withUnsafeBytes { (buffer: UnsafePointer) in - CCHmacUpdate(context, buffer, size_t(message.count)) - } - - var hmac = Array(repeating: 0, count: Int(algorithm.commonCryptoDigestLength)) - CCHmacFinal(context, &hmac) - - return Data(hmac) -} diff --git a/Sources/JWT/HMACCryptoSwift.swift b/Sources/JWT/HMACCryptoSwift.swift deleted file mode 100644 index 401a803..0000000 --- a/Sources/JWT/HMACCryptoSwift.swift +++ /dev/null @@ -1,28 +0,0 @@ -import Foundation -import CryptoSwift - - -extension HMACAlgorithm { - var cryptoSwiftVariant: HMAC.Variant { - switch self { - case .sha256: - return .sha256 - case .sha384: - return .sha384 - case .sha512: - return .sha512 - } - } -} - - -func hmac(algorithm: HMACAlgorithm, key: Data, message: Data) -> Data { - let mac = HMAC(key: key.bytes, variant: algorithm.cryptoSwiftVariant) - let result: [UInt8] - do { - result = try mac.authenticate(message.bytes) - } catch { - result = [] - } - return Data(bytes: result) -} diff --git a/Sources/JWT/JWA.swift b/Sources/JWT/JWA.swift deleted file mode 100644 index 3ac9cef..0000000 --- a/Sources/JWT/JWA.swift +++ /dev/null @@ -1,57 +0,0 @@ -import Foundation - -/// Represents a JSON Web Algorithm (JWA) -/// https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40 -public enum Algorithm: CustomStringConvertible { - /// No Algorithm, i-e, insecure - case none - - /// HMAC using SHA-256 hash algorithm - case hs256(Data) - - /// HMAC using SHA-384 hash algorithm - case hs384(Data) - - /// HMAC using SHA-512 hash algorithm - case hs512(Data) - - public var description: String { - switch self { - case .none: - return "none" - case .hs256: - return "HS256" - case .hs384: - return "HS384" - case .hs512: - return "HS512" - } - } - - /// Sign a message using the algorithm - func sign(_ message: String) -> String { - func signHS(_ key: Data, algorithm: HMACAlgorithm) -> String { - let messageData = message.data(using: String.Encoding.utf8, allowLossyConversion: false)! - return base64encode(hmac(algorithm: algorithm, key: key, message: messageData)) - } - - switch self { - case .none: - return "" - - case .hs256(let key): - return signHS(key, algorithm: .sha256) - - case .hs384(let key): - return signHS(key, algorithm: .sha384) - - case .hs512(let key): - return signHS(key, algorithm: .sha512) - } - } - - /// Verify a signature for a message using the algorithm - func verify(_ message: String, signature: Data) -> Bool { - return sign(message) == base64encode(signature) - } -} diff --git a/Tests/JWATests/HMACTests.swift b/Tests/JWATests/HMACTests.swift new file mode 100644 index 0000000..2991630 --- /dev/null +++ b/Tests/JWATests/HMACTests.swift @@ -0,0 +1,63 @@ +import Foundation +import XCTest +import JWA + + +class HMACAlgorithmTests: XCTestCase { + let key = "secret".data(using: .utf8)! + let message = "message".data(using: .utf8)! + let sha256Signature = Data(base64Encoded: "i19IcCmVwVmMVz2x4hhmqbgl1KeU0WnXBgoDYFeWNgs=")! + let sha384Signature = Data(base64Encoded: "rQ706A2kJ7KjPURXyXK/dZ9Qdm+7ZlaQ1Qt8s43VIX21Wck+p8vuSOKuGltKr9NL")! + let sha512Signature = Data(base64Encoded: "G7pYfHMO7box9Tq7C2ylieCd5OiU7kVeYUCAc5l1mtqvoGnux8AWR7sXPcsX9V0ir0mhgHG3SMXC7df3qCnGMg==")! + + // MARK: Name + + func testSHA256Name() { + let algorithm = HMACAlgorithm(key: key, hash: .sha256) + XCTAssertEqual(algorithm.name, "HS256") + } + + func testSHA384Name() { + let algorithm = HMACAlgorithm(key: key, hash: .sha384) + XCTAssertEqual(algorithm.name, "HS384") + } + + func testSHA512Name() { + let algorithm = HMACAlgorithm(key: key, hash: .sha512) + XCTAssertEqual(algorithm.name, "HS512") + } + + // MARK: Signing + + func testSHA256Sign() { + let algorithm = HMACAlgorithm(key: key, hash: .sha256) + XCTAssertEqual(algorithm.sign(message), sha256Signature) + } + + func testSHA384Sign() { + let algorithm = HMACAlgorithm(key: key, hash: .sha384) + XCTAssertEqual(algorithm.sign(message), sha384Signature) + } + + func testSHA512Sign() { + let algorithm = HMACAlgorithm(key: key, hash: .sha512) + XCTAssertEqual(algorithm.sign(message), sha512Signature) + } + + // MARK: Verify + + func testSHA256Verify() { + let algorithm = HMACAlgorithm(key: key, hash: .sha256) + XCTAssertTrue(algorithm.verify(message, signature: sha256Signature)) + } + + func testSHA384Verify() { + let algorithm = HMACAlgorithm(key: key, hash: .sha384) + XCTAssertTrue(algorithm.verify(message, signature: sha384Signature)) + } + + func testSHA512Verify() { + let algorithm = HMACAlgorithm(key: key, hash: .sha512) + XCTAssertTrue(algorithm.verify(message, signature: sha512Signature)) + } +} diff --git a/Tests/JWATests/NoneTests.swift b/Tests/JWATests/NoneTests.swift new file mode 100644 index 0000000..c3987c5 --- /dev/null +++ b/Tests/JWATests/NoneTests.swift @@ -0,0 +1,23 @@ +import XCTest +import JWA + + +class NoneAlgorithmTests: XCTestCase { + let message = "message".data(using: .utf8)! + let signature = Data() + + func testName() { + let algorithm = NoneAlgorithm() + XCTAssertEqual(algorithm.name, "none") + } + + func testSign() { + let algorithm = NoneAlgorithm() + XCTAssertEqual(algorithm.sign(message), signature) + } + + func testVerify() { + let algorithm = NoneAlgorithm() + XCTAssertTrue(algorithm.verify(message, signature: signature)) + } +} From 614d37e04453c956c7243fe977a49a6551b605a4 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 7 Feb 2018 21:49:21 +0000 Subject: [PATCH 37/62] chore: Remove Xcode Project for now Not possible to keep this in-sync during development, maybe restored in future --- .travis.yml | 10 +- JSONWebToken.podspec | 32 - JWT.xcodeproj/project.pbxproj | 921 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/xcschemes/JWT-OSX.xcscheme | 115 --- .../xcshareddata/xcschemes/JWT-iOS.xcscheme | 82 -- .../xcshareddata/xcschemes/JWT-tvOS.xcscheme | 82 -- .../xcschemes/JWT-watchOS.xcscheme | 82 -- JWT/Info.plist | 28 - JWT/JWT.h | 17 - 10 files changed, 5 insertions(+), 1371 deletions(-) delete mode 100644 JSONWebToken.podspec delete mode 100644 JWT.xcodeproj/project.pbxproj delete mode 100644 JWT.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 JWT.xcodeproj/xcshareddata/xcschemes/JWT-OSX.xcscheme delete mode 100644 JWT.xcodeproj/xcshareddata/xcschemes/JWT-iOS.xcscheme delete mode 100644 JWT.xcodeproj/xcshareddata/xcschemes/JWT-tvOS.xcscheme delete mode 100644 JWT.xcodeproj/xcshareddata/xcschemes/JWT-watchOS.xcscheme delete mode 100644 JWT/Info.plist delete mode 100644 JWT/JWT.h diff --git a/.travis.yml b/.travis.yml index 20995c2..cbcea7f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,8 @@ install: - git submodule update --init --recursive script: - swift test -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-OSX test -sdk macosx; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-iOS build -sdk iphonesimulator; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-tvOS build -sdk appletvsimulator; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-watchOS build -sdk watchsimulator; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pod lib lint --allow-warnings; fi +#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-OSX test -sdk macosx; fi +#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-iOS build -sdk iphonesimulator; fi +#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-tvOS build -sdk appletvsimulator; fi +#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-watchOS build -sdk watchsimulator; fi +#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pod lib lint --allow-warnings; fi diff --git a/JSONWebToken.podspec b/JSONWebToken.podspec deleted file mode 100644 index 1d0094d..0000000 --- a/JSONWebToken.podspec +++ /dev/null @@ -1,32 +0,0 @@ -Pod::Spec.new do |spec| - spec.name = 'JSONWebToken' - spec.version = '2.2.0' - spec.summary = 'Swift library for JSON Web Tokens (JWT).' - spec.homepage = 'https://github.com/kylef/JSONWebToken.swift' - spec.license = { :type => 'BSD', :file => 'LICENSE' } - spec.author = { 'Kyle Fuller' => 'kyle@fuller.li' } - spec.source = { :git => 'https://github.com/kylef/JSONWebToken.swift.git', :tag => "#{spec.version}" } - spec.source_files = [ - 'Sources/JWA/HMAC/*.swift', - 'Sources/{JWA,JWT}/*.swift', - ] - spec.ios.deployment_target = '8.0' - spec.osx.deployment_target = '10.9' - spec.tvos.deployment_target = '9.0' - spec.watchos.deployment_target = '2.0' - spec.requires_arc = true - spec.module_name = 'JWT' - spec.exclude_files = ['Sources/JWA/HMAC/HMACCryptoSwift.swift'] - - if ARGV.include?('lint') - spec.pod_target_xcconfig = { - 'SWIFT_INCLUDE_PATHS' => Dir.pwd, - } - else - spec.pod_target_xcconfig = { - 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/JSONWebToken/', - } - end - - spec.preserve_paths = 'CommonCrypto/{shim.h,module.modulemap}' -end diff --git a/JWT.xcodeproj/project.pbxproj b/JWT.xcodeproj/project.pbxproj deleted file mode 100644 index 6c895b0..0000000 --- a/JWT.xcodeproj/project.pbxproj +++ /dev/null @@ -1,921 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 271E10801F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; - 271E10811F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; - 271E10821F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; - 271E10831F90253300B5033C /* JWA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E107F1F90253300B5033C /* JWA.swift */; }; - 271E10891F90334B00B5033C /* CompactJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */; }; - 271E108B1F9034B100B5033C /* CompactJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */; }; - 271E108D1F9041C400B5033C /* CompactJSONDecoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108C1F9041C400B5033C /* CompactJSONDecoderTests.swift */; }; - 271E108F1F9042E900B5033C /* CompactJSONEncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108E1F9042E900B5033C /* CompactJSONEncoderTests.swift */; }; - 271E10911F90488700B5033C /* JWTEncodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10901F90488700B5033C /* JWTEncodeTests.swift */; }; - 271E10931F9049A400B5033C /* PayloadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10921F9049A400B5033C /* PayloadTests.swift */; }; - 271E10951F9049E200B5033C /* ClaimSetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10941F9049E200B5033C /* ClaimSetTests.swift */; }; - 271E10971F904A0700B5033C /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10961F904A0700B5033C /* IntegrationTests.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 */; }; - 273011021F33EABA00219C35 /* HMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273010FE1F33EABA00219C35 /* HMAC.swift */; }; - 273011161F34029900219C35 /* HMACCommonCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */; }; - 273011171F34029900219C35 /* HMACCommonCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */; }; - 273011181F34029A00219C35 /* HMACCommonCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */; }; - 273011191F34029A00219C35 /* HMACCommonCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */; }; - 277794051DF221F800573F3E /* ClaimSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277794041DF221F800573F3E /* ClaimSet.swift */; }; - 277794061DF221F800573F3E /* ClaimSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277794041DF221F800573F3E /* ClaimSet.swift */; }; - 277794071DF221F800573F3E /* ClaimSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277794041DF221F800573F3E /* ClaimSet.swift */; }; - 277794081DF221F800573F3E /* ClaimSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277794041DF221F800573F3E /* ClaimSet.swift */; }; - 2777940B1DF22BE400573F3E /* JOSEHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2777940A1DF22BE400573F3E /* JOSEHeader.swift */; }; - 2777940C1DF22BE400573F3E /* JOSEHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2777940A1DF22BE400573F3E /* JOSEHeader.swift */; }; - 2777940D1DF22BE400573F3E /* JOSEHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2777940A1DF22BE400573F3E /* JOSEHeader.swift */; }; - 2777940E1DF22BE400573F3E /* JOSEHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2777940A1DF22BE400573F3E /* JOSEHeader.swift */; }; - 277794101DF22D0D00573F3E /* Encode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2777940F1DF22D0D00573F3E /* Encode.swift */; }; - 277794111DF22D0D00573F3E /* Encode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2777940F1DF22D0D00573F3E /* Encode.swift */; }; - 277794121DF22D0D00573F3E /* Encode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2777940F1DF22D0D00573F3E /* Encode.swift */; }; - 277794131DF22D0D00573F3E /* Encode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2777940F1DF22D0D00573F3E /* Encode.swift */; }; - 279D63A21AD07FFF0024E2BC /* JWT.h in Headers */ = {isa = PBXBuildFile; fileRef = 279D63A11AD07FFF0024E2BC /* JWT.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 279D63A81AD07FFF0024E2BC /* JWT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279D639C1AD07FFF0024E2BC /* JWT.framework */; }; - 279D63AF1AD07FFF0024E2BC /* JWTDecodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279D63AE1AD07FFF0024E2BC /* JWTDecodeTests.swift */; }; - 501BF92F1FAB05AE00449B76 /* CompactJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */; }; - 501BF9301FAB05C500449B76 /* CompactJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */; }; - 501BF9311FAB05E400449B76 /* CompactJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */; }; - 501BF9321FAB05E400449B76 /* CompactJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */; }; - 501BF9331FAB05E700449B76 /* CompactJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */; }; - 501BF9341FAB05E700449B76 /* CompactJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */; }; - 520A71171C469F010005C709 /* Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71131C469F010005C709 /* Base64.swift */; }; - 520A71181C469F010005C709 /* Claims.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71141C469F010005C709 /* Claims.swift */; }; - 520A71191C469F010005C709 /* Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71151C469F010005C709 /* Decode.swift */; }; - 520A711A1C469F010005C709 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71161C469F010005C709 /* JWT.swift */; }; - CD9B62171C7753D8005D4844 /* Claims.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71141C469F010005C709 /* Claims.swift */; }; - CD9B62181C7753D8005D4844 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71161C469F010005C709 /* JWT.swift */; }; - CD9B62191C7753D8005D4844 /* Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71151C469F010005C709 /* Decode.swift */; }; - CD9B621A1C7753D8005D4844 /* Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71131C469F010005C709 /* Base64.swift */; }; - CD9B621E1C7753D8005D4844 /* JWT.h in Headers */ = {isa = PBXBuildFile; fileRef = 279D63A11AD07FFF0024E2BC /* JWT.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CD9B62291C7753EC005D4844 /* Claims.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71141C469F010005C709 /* Claims.swift */; }; - CD9B622A1C7753EC005D4844 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71161C469F010005C709 /* JWT.swift */; }; - CD9B622B1C7753EC005D4844 /* Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71151C469F010005C709 /* Decode.swift */; }; - CD9B622C1C7753EC005D4844 /* Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71131C469F010005C709 /* Base64.swift */; }; - CD9B62301C7753EC005D4844 /* JWT.h in Headers */ = {isa = PBXBuildFile; fileRef = 279D63A11AD07FFF0024E2BC /* JWT.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CD9B623B1C7753FB005D4844 /* Claims.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71141C469F010005C709 /* Claims.swift */; }; - CD9B623C1C7753FB005D4844 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71161C469F010005C709 /* JWT.swift */; }; - CD9B623D1C7753FB005D4844 /* Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71151C469F010005C709 /* Decode.swift */; }; - CD9B623E1C7753FB005D4844 /* Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520A71131C469F010005C709 /* Base64.swift */; }; - CD9B62421C7753FB005D4844 /* JWT.h in Headers */ = {isa = PBXBuildFile; fileRef = 279D63A11AD07FFF0024E2BC /* JWT.h */; settings = {ATTRIBUTES = (Public, ); }; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 279D63A91AD07FFF0024E2BC /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 279D63931AD07FFF0024E2BC /* Project object */; - proxyType = 1; - remoteGlobalIDString = 279D639B1AD07FFF0024E2BC; - remoteInfo = JWT; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 271E107F1F90253300B5033C /* JWA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWA.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 = ""; }; - 271E108C1F9041C400B5033C /* CompactJSONDecoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactJSONDecoderTests.swift; sourceTree = ""; }; - 271E108E1F9042E900B5033C /* CompactJSONEncoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactJSONEncoderTests.swift; sourceTree = ""; }; - 271E10901F90488700B5033C /* JWTEncodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWTEncodeTests.swift; sourceTree = ""; }; - 271E10921F9049A400B5033C /* PayloadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadTests.swift; sourceTree = ""; }; - 271E10941F9049E200B5033C /* ClaimSetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClaimSetTests.swift; sourceTree = ""; }; - 271E10961F904A0700B5033C /* IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationTests.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 = ""; }; - 277794041DF221F800573F3E /* ClaimSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClaimSet.swift; sourceTree = ""; }; - 2777940A1DF22BE400573F3E /* JOSEHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JOSEHeader.swift; sourceTree = ""; }; - 2777940F1DF22D0D00573F3E /* Encode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Encode.swift; sourceTree = ""; }; - 279D639C1AD07FFF0024E2BC /* JWT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JWT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 279D63A01AD07FFF0024E2BC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 279D63A11AD07FFF0024E2BC /* JWT.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JWT.h; sourceTree = ""; }; - 279D63A71AD07FFF0024E2BC /* JWTTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JWTTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 279D63AD1AD07FFF0024E2BC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 279D63AE1AD07FFF0024E2BC /* JWTDecodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWTDecodeTests.swift; sourceTree = ""; }; - 520A71131C469F010005C709 /* Base64.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Base64.swift; sourceTree = ""; }; - 520A71141C469F010005C709 /* Claims.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Claims.swift; sourceTree = ""; }; - 520A71151C469F010005C709 /* Decode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Decode.swift; sourceTree = ""; }; - 520A71161C469F010005C709 /* JWT.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = ""; }; - 520A711B1C469F440005C709 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; - 540942F3614C41E3827F2013 /* Pods_JWT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_JWT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CD9B62231C7753D8005D4844 /* JWT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JWT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CD9B62351C7753EC005D4844 /* JWT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JWT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CD9B62471C7753FB005D4844 /* JWT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JWT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CE8198B6E30BA6B8F8125FA7 /* Pods_JWTTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_JWTTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 279D63981AD07FFF0024E2BC /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 279D63A41AD07FFF0024E2BC /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 279D63A81AD07FFF0024E2BC /* JWT.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B621B1C7753D8005D4844 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B622D1C7753EC005D4844 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B623F1C7753FB005D4844 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 271E10861F902D8900B5033C /* JWT */ = { - isa = PBXGroup; - children = ( - 277794041DF221F800573F3E /* ClaimSet.swift */, - 2777940A1DF22BE400573F3E /* JOSEHeader.swift */, - 271E10881F90334B00B5033C /* CompactJSONEncoder.swift */, - 271E108A1F9034B100B5033C /* CompactJSONDecoder.swift */, - 520A71131C469F010005C709 /* Base64.swift */, - 520A71141C469F010005C709 /* Claims.swift */, - 520A71151C469F010005C709 /* Decode.swift */, - 2777940F1DF22D0D00573F3E /* Encode.swift */, - 520A71161C469F010005C709 /* JWT.swift */, - 271E107F1F90253300B5033C /* JWA.swift */, - 273010FE1F33EABA00219C35 /* HMAC.swift */, - 273011041F33FC5F00219C35 /* HMACCommonCrypto.swift */, - 273011091F33FC9100219C35 /* HMACCryptoSwift.swift */, - ); - path = JWT; - sourceTree = ""; - }; - 279D63921AD07FFF0024E2BC = { - isa = PBXGroup; - children = ( - 520A711B1C469F440005C709 /* Package.swift */, - 520A71121C469F010005C709 /* Sources */, - 279D639E1AD07FFF0024E2BC /* Sources */, - 279D63AB1AD07FFF0024E2BC /* Tests */, - 279D639D1AD07FFF0024E2BC /* Products */, - AC8AE547FDAF3DD80EB4DB2F /* Frameworks */, - ); - indentWidth = 2; - sourceTree = ""; - tabWidth = 2; - }; - 279D639D1AD07FFF0024E2BC /* Products */ = { - isa = PBXGroup; - children = ( - 279D639C1AD07FFF0024E2BC /* JWT.framework */, - 279D63A71AD07FFF0024E2BC /* JWTTests.xctest */, - CD9B62231C7753D8005D4844 /* JWT.framework */, - CD9B62351C7753EC005D4844 /* JWT.framework */, - CD9B62471C7753FB005D4844 /* JWT.framework */, - ); - name = Products; - sourceTree = ""; - }; - 279D639E1AD07FFF0024E2BC /* Sources */ = { - isa = PBXGroup; - children = ( - 279D63A11AD07FFF0024E2BC /* JWT.h */, - 279D639F1AD07FFF0024E2BC /* Supporting Files */, - ); - name = Sources; - path = JWT; - sourceTree = ""; - }; - 279D639F1AD07FFF0024E2BC /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 279D63A01AD07FFF0024E2BC /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 279D63AB1AD07FFF0024E2BC /* Tests */ = { - isa = PBXGroup; - children = ( - 271E108C1F9041C400B5033C /* CompactJSONDecoderTests.swift */, - 271E108E1F9042E900B5033C /* CompactJSONEncoderTests.swift */, - 271E10941F9049E200B5033C /* ClaimSetTests.swift */, - 271E10921F9049A400B5033C /* PayloadTests.swift */, - 271E10901F90488700B5033C /* JWTEncodeTests.swift */, - 279D63AE1AD07FFF0024E2BC /* JWTDecodeTests.swift */, - 271E10961F904A0700B5033C /* IntegrationTests.swift */, - 279D63AC1AD07FFF0024E2BC /* Supporting Files */, - ); - name = Tests; - path = Tests/JWTTests; - sourceTree = ""; - }; - 279D63AC1AD07FFF0024E2BC /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 279D63AD1AD07FFF0024E2BC /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 520A71121C469F010005C709 /* Sources */ = { - isa = PBXGroup; - children = ( - 271E10861F902D8900B5033C /* JWT */, - ); - path = Sources; - sourceTree = ""; - }; - AC8AE547FDAF3DD80EB4DB2F /* Frameworks */ = { - isa = PBXGroup; - children = ( - 540942F3614C41E3827F2013 /* Pods_JWT.framework */, - CE8198B6E30BA6B8F8125FA7 /* Pods_JWTTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 279D63991AD07FFF0024E2BC /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 279D63A21AD07FFF0024E2BC /* JWT.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B621D1C7753D8005D4844 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - CD9B621E1C7753D8005D4844 /* JWT.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B622F1C7753EC005D4844 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - CD9B62301C7753EC005D4844 /* JWT.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B62411C7753FB005D4844 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - CD9B62421C7753FB005D4844 /* JWT.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 279D639B1AD07FFF0024E2BC /* JWT-OSX */ = { - isa = PBXNativeTarget; - buildConfigurationList = 279D63B21AD07FFF0024E2BC /* Build configuration list for PBXNativeTarget "JWT-OSX" */; - buildPhases = ( - 279D63971AD07FFF0024E2BC /* Sources */, - 279D63981AD07FFF0024E2BC /* Frameworks */, - 279D63991AD07FFF0024E2BC /* Headers */, - 66725DA11C591D9800FC32F4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "JWT-OSX"; - productName = JWT; - productReference = 279D639C1AD07FFF0024E2BC /* JWT.framework */; - productType = "com.apple.product-type.framework"; - }; - 279D63A61AD07FFF0024E2BC /* JWTTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 279D63B51AD07FFF0024E2BC /* Build configuration list for PBXNativeTarget "JWTTests" */; - buildPhases = ( - 279D63A31AD07FFF0024E2BC /* Sources */, - 279D63A41AD07FFF0024E2BC /* Frameworks */, - 279D63A51AD07FFF0024E2BC /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 279D63AA1AD07FFF0024E2BC /* PBXTargetDependency */, - ); - name = JWTTests; - productName = JWTTests; - productReference = 279D63A71AD07FFF0024E2BC /* JWTTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - CD9B62131C7753D8005D4844 /* JWT-iOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = CD9B62201C7753D8005D4844 /* Build configuration list for PBXNativeTarget "JWT-iOS" */; - buildPhases = ( - CD9B62161C7753D8005D4844 /* Sources */, - CD9B621B1C7753D8005D4844 /* Frameworks */, - CD9B621D1C7753D8005D4844 /* Headers */, - CD9B621F1C7753D8005D4844 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "JWT-iOS"; - productName = JWT; - productReference = CD9B62231C7753D8005D4844 /* JWT.framework */; - productType = "com.apple.product-type.framework"; - }; - CD9B62251C7753EC005D4844 /* JWT-tvOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = CD9B62321C7753EC005D4844 /* Build configuration list for PBXNativeTarget "JWT-tvOS" */; - buildPhases = ( - CD9B62281C7753EC005D4844 /* Sources */, - CD9B622D1C7753EC005D4844 /* Frameworks */, - CD9B622F1C7753EC005D4844 /* Headers */, - CD9B62311C7753EC005D4844 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "JWT-tvOS"; - productName = JWT; - productReference = CD9B62351C7753EC005D4844 /* JWT.framework */; - productType = "com.apple.product-type.framework"; - }; - CD9B62371C7753FB005D4844 /* JWT-watchOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = CD9B62441C7753FB005D4844 /* Build configuration list for PBXNativeTarget "JWT-watchOS" */; - buildPhases = ( - CD9B623A1C7753FB005D4844 /* Sources */, - CD9B623F1C7753FB005D4844 /* Frameworks */, - CD9B62411C7753FB005D4844 /* Headers */, - CD9B62431C7753FB005D4844 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "JWT-watchOS"; - productName = JWT; - productReference = CD9B62471C7753FB005D4844 /* JWT.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 279D63931AD07FFF0024E2BC /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftMigration = 0700; - LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0910; - ORGANIZATIONNAME = Cocode; - TargetAttributes = { - 279D639B1AD07FFF0024E2BC = { - CreatedOnToolsVersion = 6.2; - }; - 279D63A61AD07FFF0024E2BC = { - CreatedOnToolsVersion = 6.2; - }; - }; - }; - buildConfigurationList = 279D63961AD07FFF0024E2BC /* Build configuration list for PBXProject "JWT" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 279D63921AD07FFF0024E2BC; - productRefGroup = 279D639D1AD07FFF0024E2BC /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 279D639B1AD07FFF0024E2BC /* JWT-OSX */, - CD9B62131C7753D8005D4844 /* JWT-iOS */, - CD9B62251C7753EC005D4844 /* JWT-tvOS */, - CD9B62371C7753FB005D4844 /* JWT-watchOS */, - 279D63A61AD07FFF0024E2BC /* JWTTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 279D63A51AD07FFF0024E2BC /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 66725DA11C591D9800FC32F4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B621F1C7753D8005D4844 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B62311C7753EC005D4844 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B62431C7753FB005D4844 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 279D63971AD07FFF0024E2BC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 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; - }; - 279D63A31AD07FFF0024E2BC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 271E10971F904A0700B5033C /* IntegrationTests.swift in Sources */, - 271E108F1F9042E900B5033C /* CompactJSONEncoderTests.swift in Sources */, - 271E10911F90488700B5033C /* JWTEncodeTests.swift in Sources */, - 271E108D1F9041C400B5033C /* CompactJSONDecoderTests.swift in Sources */, - 279D63AF1AD07FFF0024E2BC /* JWTDecodeTests.swift in Sources */, - 271E10931F9049A400B5033C /* PayloadTests.swift in Sources */, - 271E10951F9049E200B5033C /* ClaimSetTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B62161C7753D8005D4844 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 271E10811F90253300B5033C /* JWA.swift in Sources */, - 273011171F34029900219C35 /* HMACCommonCrypto.swift in Sources */, - CD9B62171C7753D8005D4844 /* Claims.swift in Sources */, - 501BF92F1FAB05AE00449B76 /* CompactJSONEncoder.swift in Sources */, - CD9B62181C7753D8005D4844 /* JWT.swift in Sources */, - CD9B62191C7753D8005D4844 /* Decode.swift in Sources */, - 277794111DF22D0D00573F3E /* Encode.swift in Sources */, - 2777940C1DF22BE400573F3E /* JOSEHeader.swift in Sources */, - 277794061DF221F800573F3E /* ClaimSet.swift in Sources */, - 273011001F33EABA00219C35 /* HMAC.swift in Sources */, - 501BF9301FAB05C500449B76 /* CompactJSONDecoder.swift in Sources */, - CD9B621A1C7753D8005D4844 /* Base64.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B62281C7753EC005D4844 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 271E10821F90253300B5033C /* JWA.swift in Sources */, - 273011181F34029A00219C35 /* HMACCommonCrypto.swift in Sources */, - CD9B62291C7753EC005D4844 /* Claims.swift in Sources */, - 501BF9311FAB05E400449B76 /* CompactJSONEncoder.swift in Sources */, - CD9B622A1C7753EC005D4844 /* JWT.swift in Sources */, - CD9B622B1C7753EC005D4844 /* Decode.swift in Sources */, - 277794121DF22D0D00573F3E /* Encode.swift in Sources */, - 2777940D1DF22BE400573F3E /* JOSEHeader.swift in Sources */, - 277794071DF221F800573F3E /* ClaimSet.swift in Sources */, - 273011011F33EABA00219C35 /* HMAC.swift in Sources */, - 501BF9331FAB05E700449B76 /* CompactJSONDecoder.swift in Sources */, - CD9B622C1C7753EC005D4844 /* Base64.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD9B623A1C7753FB005D4844 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 271E10831F90253300B5033C /* JWA.swift in Sources */, - 273011191F34029A00219C35 /* HMACCommonCrypto.swift in Sources */, - CD9B623B1C7753FB005D4844 /* Claims.swift in Sources */, - 501BF9321FAB05E400449B76 /* CompactJSONEncoder.swift in Sources */, - CD9B623C1C7753FB005D4844 /* JWT.swift in Sources */, - CD9B623D1C7753FB005D4844 /* Decode.swift in Sources */, - 277794131DF22D0D00573F3E /* Encode.swift in Sources */, - 2777940E1DF22BE400573F3E /* JOSEHeader.swift in Sources */, - 277794081DF221F800573F3E /* ClaimSet.swift in Sources */, - 273011021F33EABA00219C35 /* HMAC.swift in Sources */, - 501BF9341FAB05E700449B76 /* CompactJSONDecoder.swift in Sources */, - CD9B623E1C7753FB005D4844 /* Base64.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 279D63AA1AD07FFF0024E2BC /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 279D639B1AD07FFF0024E2BC /* JWT-OSX */; - targetProxy = 279D63A91AD07FFF0024E2BC /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 279D63B01AD07FFF0024E2BC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(PROJECT_NAME)"; - SDKROOT = macosx; - SWIFT_INCLUDE_PATHS = "$(SRCROOT)"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 279D63B11AD07FFF0024E2BC /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = "$(PROJECT_NAME)"; - SDKROOT = macosx; - SWIFT_INCLUDE_PATHS = "$(SRCROOT)"; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 279D63B31AD07FFF0024E2BC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = JWT/Info.plist; - INSTALL_PATH = "@rpath"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 279D63B41AD07FFF0024E2BC /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = JWT/Info.plist; - INSTALL_PATH = "@rpath"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 279D63B61AD07FFF0024E2BC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(DEVELOPER_FRAMEWORKS_DIR)", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = Tests/JWTTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 279D63B71AD07FFF0024E2BC /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(DEVELOPER_FRAMEWORKS_DIR)", - "$(inherited)", - ); - INFOPLIST_FILE = Tests/JWTTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - CD9B62211C7753D8005D4844 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = JWT/Info.plist; - INSTALL_PATH = "@rpath"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - CD9B62221C7753D8005D4844 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = JWT/Info.plist; - INSTALL_PATH = "@rpath"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - CD9B62331C7753EC005D4844 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = JWT/Info.plist; - INSTALL_PATH = "@rpath"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; - }; - name = Debug; - }; - CD9B62341C7753EC005D4844 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = JWT/Info.plist; - INSTALL_PATH = "@rpath"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - CD9B62451C7753FB005D4844 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = JWT/Info.plist; - INSTALL_PATH = "@rpath"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - SDKROOT = watchos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = 4; - WATCHOS_DEPLOYMENT_TARGET = 2.0; - }; - name = Debug; - }; - CD9B62461C7753FB005D4844 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = JWT/Info.plist; - INSTALL_PATH = "@rpath"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - SDKROOT = watchos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = 4; - VALIDATE_PRODUCT = YES; - WATCHOS_DEPLOYMENT_TARGET = 2.0; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 279D63961AD07FFF0024E2BC /* Build configuration list for PBXProject "JWT" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 279D63B01AD07FFF0024E2BC /* Debug */, - 279D63B11AD07FFF0024E2BC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 279D63B21AD07FFF0024E2BC /* Build configuration list for PBXNativeTarget "JWT-OSX" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 279D63B31AD07FFF0024E2BC /* Debug */, - 279D63B41AD07FFF0024E2BC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 279D63B51AD07FFF0024E2BC /* Build configuration list for PBXNativeTarget "JWTTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 279D63B61AD07FFF0024E2BC /* Debug */, - 279D63B71AD07FFF0024E2BC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CD9B62201C7753D8005D4844 /* Build configuration list for PBXNativeTarget "JWT-iOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CD9B62211C7753D8005D4844 /* Debug */, - CD9B62221C7753D8005D4844 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CD9B62321C7753EC005D4844 /* Build configuration list for PBXNativeTarget "JWT-tvOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CD9B62331C7753EC005D4844 /* Debug */, - CD9B62341C7753EC005D4844 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CD9B62441C7753FB005D4844 /* Build configuration list for PBXNativeTarget "JWT-watchOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CD9B62451C7753FB005D4844 /* Debug */, - CD9B62461C7753FB005D4844 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 279D63931AD07FFF0024E2BC /* Project object */; -} diff --git a/JWT.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/JWT.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index e3cefe8..0000000 --- a/JWT.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-OSX.xcscheme b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-OSX.xcscheme deleted file mode 100644 index dc61530..0000000 --- a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-OSX.xcscheme +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-iOS.xcscheme b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-iOS.xcscheme deleted file mode 100644 index 387dbf8..0000000 --- a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-iOS.xcscheme +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-tvOS.xcscheme b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-tvOS.xcscheme deleted file mode 100644 index 46efb5f..0000000 --- a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-tvOS.xcscheme +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-watchOS.xcscheme b/JWT.xcodeproj/xcshareddata/xcschemes/JWT-watchOS.xcscheme deleted file mode 100644 index c0bf55d..0000000 --- a/JWT.xcodeproj/xcshareddata/xcschemes/JWT-watchOS.xcscheme +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/JWT/Info.plist b/JWT/Info.plist deleted file mode 100644 index ba3fdf1..0000000 --- a/JWT/Info.plist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSHumanReadableCopyright - Copyright © 2015 Cocode. All rights reserved. - NSPrincipalClass - - - diff --git a/JWT/JWT.h b/JWT/JWT.h deleted file mode 100644 index 1af30d5..0000000 --- a/JWT/JWT.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// JWT.h -// JWT -// -// Created by Kyle Fuller on 04/04/2015. -// Copyright (c) 2015 Cocode. All rights reserved. -// - -#import - -//! Project version number for JWT. -FOUNDATION_EXPORT double JWTVersionNumber; - -//! Project version string for JWT. -FOUNDATION_EXPORT const unsigned char JWTVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import From 20f2efeab560931e3c1700b02f72035736cde1ff Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 7 Feb 2018 22:12:35 +0000 Subject: [PATCH 38/62] chore: Restore building on all platforms using generated Xcode --- .travis.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index cbcea7f..7674264 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,9 @@ install: - git submodule update --init --recursive script: - swift test -#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-OSX test -sdk macosx; fi -#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-iOS build -sdk iphonesimulator; fi -#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-tvOS build -sdk appletvsimulator; fi -#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-watchOS build -sdk watchsimulator; fi +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then swift package generate-xcodeproj; fi +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package test -sdk macosx; fi +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk iphonesimulator; fi +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk appletvsimulator; fi +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk watchsimulator; fi #- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pod lib lint --allow-warnings; fi From 9f67977fd82c88b1aace2e861640a961d589bb83 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 7 Feb 2018 22:32:17 +0000 Subject: [PATCH 39/62] chore: Refactor Travis to use build matrix --- .travis.yml | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7674264..225f25f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,44 @@ os: -- linux -- osx + - osx + - linux +osx_image: xcode9 language: generic sudo: required dist: trusty -osx_image: xcode9 env: -- SWIFT_VERSION=4.0 + global: + - SWIFT_VERSION=4.0 + matrix: + - SWIFTPM_BUILD=true + - SWIFTPM_TEST=true + - XCODE_TEST_SDK=macosx + - XCODE_BUILD_SDK=iphonesimulator + - XCODE_BUILD_SDK=appletvsimulator + - XCODE_BUILD_SDK=watchsimulator + +matrix: + exclude: + # No need to build and test on macOS + - os: osx + env: SWIFTPM_BUILD=true + # LinuxMain.swift is out of sync + - os: linux + env: SWIFTPM_TEST=true + - os: linux + env: XCODE_TEST_SDK=macosx + - os: linux + env: XCODE_BUILD_SDK=iphonesimulator + - os: linux + env: XCODE_BUILD_SDK=appletvsimulator + - os: linux + env: XCODE_BUILD_SDK=watchsimulator + install: -- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"; fi -- git submodule update --init --recursive + - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" + script: -- swift test -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then swift package generate-xcodeproj; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package test -sdk macosx; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk iphonesimulator; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk appletvsimulator; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk watchsimulator; fi -#- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pod lib lint --allow-warnings; fi +- if [ -n "$SWIFTPM_BUILD" ]; then swift build; fi +- if [ -n "$SWIFTPM_TEST" ]; then swift test; fi +- if [ -n "$XCODE_BUILD_SDK" ] || [ -n "$XCODE_TEST_SDK" ]; then swift package generate-xcodeproj; fi +- if [ -n "$XCODE_BUILD_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk $XCODE_BUILD_SDK; fi +- if [ -n "$XCODE_TEST_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package test -sdk $XCODE_TEST_SDK; fi From 7f422516b1be5fae8dc5888185f4ddb7bea12dfb Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 17:21:23 -0500 Subject: [PATCH 40/62] Remove CommonCrypto directory as Swift 4.2 no longer requires this --- CommonCrypto/module.modulemap | 4 ---- CommonCrypto/shim.h | 1 - Package.swift | 4 +--- 3 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 CommonCrypto/module.modulemap delete mode 100644 CommonCrypto/shim.h diff --git a/CommonCrypto/module.modulemap b/CommonCrypto/module.modulemap deleted file mode 100644 index b70f7d6..0000000 --- a/CommonCrypto/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CommonCrypto [system] { - header "shim.h" - export * -} diff --git a/CommonCrypto/shim.h b/CommonCrypto/shim.h deleted file mode 100644 index c332624..0000000 --- a/CommonCrypto/shim.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/Package.swift b/Package.swift index 5ba29b4..7b5d1f1 100644 --- a/Package.swift +++ b/Package.swift @@ -4,9 +4,7 @@ import PackageDescription #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) -let dependencies = [ - Package.Dependency.package(url: "https://github.com/kylef-archive/CommonCrypto.git", from: "1.0.0"), -] +let dependencies: [Package.Dependency] = [] let excludes = ["HMAC/HMACCryptoSwift.swift"] let targetDependencies: [Target.Dependency] = [] #else From 800490657dc81ea1c22a46bcd94226d3337214c3 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 17:59:06 -0500 Subject: [PATCH 41/62] Correct encoding unit tests to account for unordered Swift dictionaries --- Tests/JWTTests/JWTEncodeTests.swift | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/Tests/JWTTests/JWTEncodeTests.swift b/Tests/JWTTests/JWTEncodeTests.swift index 0dbb7b3..08882a2 100644 --- a/Tests/JWTTests/JWTEncodeTests.swift +++ b/Tests/JWTTests/JWTEncodeTests.swift @@ -23,14 +23,36 @@ class JWTEncodeTests: XCTestCase { let jwt = JWT.encode(algorithm) { builder in builder.issuer = "fuller.li" } - - XCTAssertEqual(jwt, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.d7B7PAQcz1E6oNhrlxmHxHXHgg39_k7X7wWeahl8kSQ") + + let expected = [ + // { "alg": "HS256", "typ": "JWT" } + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.d7B7PAQcz1E6oNhrlxmHxHXHgg39_k7X7wWeahl8kSQ", + // { "typ": "JWT", "alg": "HS256" } + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.x5Fdll-kZBImOPtpT1fZH_8hDW01Ax3pbZx_EiljoLk" + ] + + XCTAssertTrue(expected.contains(jwt)) } func testEncodingClaimsWithHeaders() { let algorithm = Algorithm.hs256("secret".data(using: .utf8)!) let jwt = JWT.encode(claims: ClaimSet(), algorithm: algorithm, headers: ["kid": "x"]) + + let expected = [ + // { "alg": "HS256", "typ": "JWT", "kid": "x" } + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IngifQ.e30.ddEotxYYMMdat5HPgYFQnkHRdPXsxPG71ooyhIUoqGA", + // { "alg": "HS256", "kid": "x", "typ": "JWT" } + "eyJhbGciOiJIUzI1NiIsImtpZCI6IngiLCJ0eXAiOiJKV1QifQ.e30.xiT6fWe5dWGeuq8zFb0je_14Maa_9mHbVPSyJhUIJ54", + // { "typ": "JWT", "alg": "HS256", "kid": "x" } + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IngifQ.e30.5t6a61tpSXFo5QBHYCnKAz2mTHrW9kaQ9n_b7e-jWw0", + // { "typ": "JWT", "kid": "x", "alg": "HS256" } + "eyJ0eXAiOiJKV1QiLCJraWQiOiJ4IiwiYWxnIjoiSFMyNTYifQ.e30.DG5nmV2CVH6mV_iEm0xXZvL0DUJ22ek2xy6fNi_pGLc", + // { "kid": "x", "typ": "JWT", "alg": "HS256" } + "eyJraWQiOiJ4IiwidHlwIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.e30.h5ZvlqECBIvu9uocR5_5uF3wnhga8vTruvXpzaHpRdA", + // { "kid": "x", "alg": "HS256", "typ": "JWT" } + "eyJraWQiOiJ4IiwiYWxnIjoiSFMyNTYiLCJ0eXAiOiJKV1QifQ.e30.5KqN7N5a7Cfbe2eKN41FJIfgMjcdSZ7Nt16xqlyOeMo" + ] - XCTAssertEqual(jwt, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IngifQ.e30.ddEotxYYMMdat5HPgYFQnkHRdPXsxPG71ooyhIUoqGA") + XCTAssertTrue(expected.contains(jwt)) } } From 398c8254d3f0e75a067a3ac57526135545da4f45 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 18:27:09 -0500 Subject: [PATCH 42/62] Reindent to match existing style --- Tests/JWTTests/JWTEncodeTests.swift | 62 ++++++++++++++--------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Tests/JWTTests/JWTEncodeTests.swift b/Tests/JWTTests/JWTEncodeTests.swift index 08882a2..9ff7f14 100644 --- a/Tests/JWTTests/JWTEncodeTests.swift +++ b/Tests/JWTTests/JWTEncodeTests.swift @@ -6,53 +6,53 @@ class JWTEncodeTests: XCTestCase { func testEncodingJWT() { let payload = ["name": "Kyle"] as Payload let jwt = JWT.encode(claims: payload, algorithm: .hs256("secret".data(using: .utf8)!)) - + let expected = [ // { "alg": "HS256", "typ": "JWT" } "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS3lsZSJ9.zxm7xcp1eZtZhp4t-nlw09ATQnnFKIiSN83uG8u6cAg", - + // { "typ": "JWT", "alg": "HS256" } - "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiS3lsZSJ9.4tCpoxfyfjbUyLjm9_zu-r52Vxn6bFq9kp6Rt9xMs4A", + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiS3lsZSJ9.4tCpoxfyfjbUyLjm9_zu-r52Vxn6bFq9kp6Rt9xMs4A" ] - + XCTAssertTrue(expected.contains(jwt)) } - + func testEncodingWithBuilder() { let algorithm = Algorithm.hs256("secret".data(using: .utf8)!) let jwt = JWT.encode(algorithm) { builder in builder.issuer = "fuller.li" } - - let expected = [ - // { "alg": "HS256", "typ": "JWT" } - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.d7B7PAQcz1E6oNhrlxmHxHXHgg39_k7X7wWeahl8kSQ", - // { "typ": "JWT", "alg": "HS256" } - "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.x5Fdll-kZBImOPtpT1fZH_8hDW01Ax3pbZx_EiljoLk" - ] - - XCTAssertTrue(expected.contains(jwt)) + + let expected = [ + // { "alg": "HS256", "typ": "JWT" } + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.d7B7PAQcz1E6oNhrlxmHxHXHgg39_k7X7wWeahl8kSQ", + // { "typ": "JWT", "alg": "HS256" } + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.x5Fdll-kZBImOPtpT1fZH_8hDW01Ax3pbZx_EiljoLk" + ] + + XCTAssertTrue(expected.contains(jwt)) } - + func testEncodingClaimsWithHeaders() { let algorithm = Algorithm.hs256("secret".data(using: .utf8)!) let jwt = JWT.encode(claims: ClaimSet(), algorithm: algorithm, headers: ["kid": "x"]) - - let expected = [ - // { "alg": "HS256", "typ": "JWT", "kid": "x" } - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IngifQ.e30.ddEotxYYMMdat5HPgYFQnkHRdPXsxPG71ooyhIUoqGA", - // { "alg": "HS256", "kid": "x", "typ": "JWT" } - "eyJhbGciOiJIUzI1NiIsImtpZCI6IngiLCJ0eXAiOiJKV1QifQ.e30.xiT6fWe5dWGeuq8zFb0je_14Maa_9mHbVPSyJhUIJ54", - // { "typ": "JWT", "alg": "HS256", "kid": "x" } - "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IngifQ.e30.5t6a61tpSXFo5QBHYCnKAz2mTHrW9kaQ9n_b7e-jWw0", - // { "typ": "JWT", "kid": "x", "alg": "HS256" } - "eyJ0eXAiOiJKV1QiLCJraWQiOiJ4IiwiYWxnIjoiSFMyNTYifQ.e30.DG5nmV2CVH6mV_iEm0xXZvL0DUJ22ek2xy6fNi_pGLc", - // { "kid": "x", "typ": "JWT", "alg": "HS256" } - "eyJraWQiOiJ4IiwidHlwIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.e30.h5ZvlqECBIvu9uocR5_5uF3wnhga8vTruvXpzaHpRdA", - // { "kid": "x", "alg": "HS256", "typ": "JWT" } - "eyJraWQiOiJ4IiwiYWxnIjoiSFMyNTYiLCJ0eXAiOiJKV1QifQ.e30.5KqN7N5a7Cfbe2eKN41FJIfgMjcdSZ7Nt16xqlyOeMo" - ] - + + let expected = [ + // { "alg": "HS256", "typ": "JWT", "kid": "x" } + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IngifQ.e30.ddEotxYYMMdat5HPgYFQnkHRdPXsxPG71ooyhIUoqGA", + // { "alg": "HS256", "kid": "x", "typ": "JWT" } + "eyJhbGciOiJIUzI1NiIsImtpZCI6IngiLCJ0eXAiOiJKV1QifQ.e30.xiT6fWe5dWGeuq8zFb0je_14Maa_9mHbVPSyJhUIJ54", + // { "typ": "JWT", "alg": "HS256", "kid": "x" } + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IngifQ.e30.5t6a61tpSXFo5QBHYCnKAz2mTHrW9kaQ9n_b7e-jWw0", + // { "typ": "JWT", "kid": "x", "alg": "HS256" } + "eyJ0eXAiOiJKV1QiLCJraWQiOiJ4IiwiYWxnIjoiSFMyNTYifQ.e30.DG5nmV2CVH6mV_iEm0xXZvL0DUJ22ek2xy6fNi_pGLc", + // { "kid": "x", "typ": "JWT", "alg": "HS256" } + "eyJraWQiOiJ4IiwidHlwIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.e30.h5ZvlqECBIvu9uocR5_5uF3wnhga8vTruvXpzaHpRdA", + // { "kid": "x", "alg": "HS256", "typ": "JWT" } + "eyJraWQiOiJ4IiwiYWxnIjoiSFMyNTYiLCJ0eXAiOiJKV1QifQ.e30.5KqN7N5a7Cfbe2eKN41FJIfgMjcdSZ7Nt16xqlyOeMo" + ] + XCTAssertTrue(expected.contains(jwt)) } } From ec735aa8e5516f698540c013b57b4628a9ab9ffc Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 18:30:37 -0500 Subject: [PATCH 43/62] Fix warning about deallocate(capacity:) deprecation --- Sources/JWA/HMAC/HMACCommonCrypto.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JWA/HMAC/HMACCommonCrypto.swift b/Sources/JWA/HMAC/HMACCommonCrypto.swift index 299fd8a..6dffce0 100644 --- a/Sources/JWA/HMAC/HMACCommonCrypto.swift +++ b/Sources/JWA/HMAC/HMACCommonCrypto.swift @@ -5,7 +5,7 @@ import CommonCrypto extension HMACAlgorithm: SignAlgorithm, VerifyAlgorithm { public func sign(_ message: Data) -> Data { let context = UnsafeMutablePointer.allocate(capacity: 1) - defer { context.deallocate(capacity: 1) } + defer { context.deallocate() } key.withUnsafeBytes() { (buffer: UnsafePointer) in CCHmacInit(context, hash.commonCryptoAlgorithm, buffer, size_t(key.count)) From 264a622ddd48523a0827dc7932203a57902f41b2 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 18:44:21 -0500 Subject: [PATCH 44/62] Update many unit tests to stop using deprecated decode method --- Tests/JWTTests/JWTDecodeTests.swift | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Tests/JWTTests/JWTDecodeTests.swift b/Tests/JWTTests/JWTDecodeTests.swift index 24a17b3..3876301 100644 --- a/Tests/JWTTests/JWTDecodeTests.swift +++ b/Tests/JWTTests/JWTDecodeTests.swift @@ -18,7 +18,7 @@ class DecodeTests: XCTestCase { } func testFailsToDecodeInvalidStringWithoutThreeSegments() { - XCTAssertThrowsError(try decode("a.b", algorithm: .none), "Not enough segments") + XCTAssertThrowsError(try decode("a.b", algorithm: .none) as ClaimSet, "Not enough segments") } // MARK: Disable verify @@ -39,24 +39,24 @@ class DecodeTests: XCTestCase { func testIncorrectIssuerValidation() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.wOhJ9_6lx-3JGJPmJmtFCDI3kt7uMAMmhHIslti7ryI" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "querykit.org")) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "querykit.org") as ClaimSet) } func testMissingIssuerValidation() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "fuller.li")) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "fuller.li") as ClaimSet) } // MARK: Expiration claim func testExpiredClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0MjgxODg0OTF9.cy6b2szsNkKnHFnz2GjTatGjoHBTs8vBKnPGZgpp91I" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) } func testInvalidExpiaryClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOlsiMTQyODE4ODQ5MSJdfQ.OwF-wd3THjxrEGUhh6IdnNhxQZ7ydwJ3Z6J_dfl9MBs" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) } func testUnexpiredClaim() throws { @@ -99,7 +99,7 @@ class DecodeTests: XCTestCase { func testUnmetNotBeforeClaim() { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3MjgxODg0OTF9.Tzhu1tu-7BXcF5YEIFFE1Vmg4tEybUnaz58FR4PcblQ" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) } // MARK: Issued at claim @@ -121,7 +121,7 @@ class DecodeTests: XCTestCase { func testIssuedAtClaimInTheFuture() { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MjgxODg0OTF9.owHiJyJmTcW1lBW5y_Rz3iBfSbcNiXlbZ2fY9qR7-aU" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) } func testInvalidIssuedAtClaim() { @@ -149,12 +149,12 @@ class DecodeTests: XCTestCase { func testMismatchAudienceClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJreWxlIn0.VEB_n06pTSLlTXPFkc46ARADJ9HXNUBUPo3VhL9RDe4" // kyle - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine")) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine") as ClaimSet) } func testMissingAudienceClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle")) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle") as ClaimSet) } // MARK: Signature verification @@ -168,7 +168,7 @@ class DecodeTests: XCTestCase { func testNoneFailsWithSecretAlgorithm() { let jwt = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ0ZXN0IjoiaW5nIn0." - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) } func testMatchesAnyAlgorithm() { From 61e4cd73a19c957c52a407c6d99cd5ac378566de Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 19:01:34 -0500 Subject: [PATCH 45/62] Fix remaining unit tests --- Tests/JWTTests/JWTDecodeTests.swift | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Tests/JWTTests/JWTDecodeTests.swift b/Tests/JWTTests/JWTDecodeTests.swift index 3876301..cc4bf6d 100644 --- a/Tests/JWTTests/JWTDecodeTests.swift +++ b/Tests/JWTTests/JWTDecodeTests.swift @@ -1,6 +1,6 @@ import Foundation import XCTest -import JWT +@testable import JWT class DecodeTests: XCTestCase { func testDecodingValidJWTAsClaimSet() throws { @@ -93,7 +93,7 @@ class DecodeTests: XCTestCase { func testInvalidNotBeforeClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOlsxNDI4MTg5NzIwXX0.PUL1FQubzzJa4MNXe2D3d5t5cMaqFr3kYlzRUzly-C8" - assertDecodeError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)), error: "Not before claim (nbf) must be an integer") + assertDecodeError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet, error: "Not before claim (nbf) must be an integer") } func testUnmetNotBeforeClaim() { @@ -134,7 +134,7 @@ class DecodeTests: XCTestCase { func testAudiencesClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibWF4aW5lIiwia2F0aWUiXX0.-PKvdNLCClrWG7CvesHP6PB0-vxu-_IZcsYhJxBy5JM" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine")) { payload in + assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine") as ClaimSet) { payload in XCTAssertEqual(payload.count, 1) XCTAssertEqual(payload["aud"] as! [String], ["maxine", "katie"]) } @@ -142,7 +142,7 @@ class DecodeTests: XCTestCase { func testAudienceClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJreWxlIn0.dpgH4JOwueReaBoanLSxsGTc7AjKUvo7_M1sAfy_xVE" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle")) { payload in + assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle") as ClaimSet) { payload in XCTAssertEqual(payload as! [String: String], ["aud": "kyle"]) } } @@ -161,7 +161,7 @@ class DecodeTests: XCTestCase { func testNoneAlgorithm() { let jwt = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ0ZXN0IjoiaW5nIn0." - assertSuccess(try decode(jwt, algorithm: .none)) { payload in + assertSuccess(try decode(jwt, algorithm: .none) as ClaimSet) { payload in XCTAssertEqual(payload as! [String: String], ["test": "ing"]) } } @@ -173,36 +173,36 @@ class DecodeTests: XCTestCase { func testMatchesAnyAlgorithm() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w." - assertFailure(try decode(jwt, algorithms: [.hs256("anothersecret".data(using: .utf8)!), .hs256("secret".data(using: .utf8)!)])) + assertFailure(try decode(jwt, algorithms: [.hs256("anothersecret".data(using: .utf8)!), .hs256("secret".data(using: .utf8)!)]) as ClaimSet) } func testHS384Algorithm() { let jwt = "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.lddiriKLoo42qXduMhCTKZ5Lo3njXxOC92uXyvbLyYKzbq4CVVQOb3MpDwnI19u4" - assertSuccess(try decode(jwt, algorithm: .hs384("secret".data(using: .utf8)!))) { payload in + assertSuccess(try decode(jwt, algorithm: .hs384("secret".data(using: .utf8)!)) as ClaimSet) { payload in XCTAssertEqual(payload as! [String: String], ["some": "payload"]) } } func testHS512Algorithm() { let jwt = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.WTzLzFO079PduJiFIyzrOah54YaM8qoxH9fLMQoQhKtw3_fMGjImIOokijDkXVbyfBqhMo2GCNu4w9v7UXvnpA" - assertSuccess(try decode(jwt, algorithm: .hs512("secret".data(using: .utf8)!))) { payload in - XCTAssertEqual(payload as! [String: String], ["some": "payload"]) + assertSuccess(try decode(jwt, algorithm: .hs512("secret".data(using: .utf8)!)) as ClaimSet) { claims in + XCTAssertEqual(claims as! [String: String], ["some": "payload"]) } } } // MARK: Helpers -func assertSuccess(_ decoder: @autoclosure () throws -> Payload, closure: ((Payload) -> Void)? = nil) { +func assertSuccess(_ decoder: @autoclosure () throws -> ClaimSet, closure: (([String: Any]) -> Void)? = nil) { do { - let payload = try decoder() - closure?(payload) + let claims = try decoder() + closure?(claims.claims as [String: Any]) } catch { XCTFail("Failed to decode while expecting success. \(error)") } } -func assertFailure(_ decoder: @autoclosure () throws -> Payload, closure: ((InvalidToken) -> Void)? = nil) { +func assertFailure(_ decoder: @autoclosure () throws -> ClaimSet, closure: ((InvalidToken) -> Void)? = nil) { do { _ = try decoder() XCTFail("Decoding succeeded, expected a failure.") @@ -213,7 +213,7 @@ func assertFailure(_ decoder: @autoclosure () throws -> Payload, closure: ((Inva } } -func assertDecodeError(_ decoder: @autoclosure () throws -> Payload, error: String) { +func assertDecodeError(_ decoder: @autoclosure () throws -> ClaimSet, error: String) { assertFailure(try decoder()) { failure in switch failure { case .decodeError(let decodeError): From 14ddad4a6ca570757dbcf22fbd32451dfbe3f1d0 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 19:14:45 -0500 Subject: [PATCH 46/62] Bump CryptoSwift to 0.10.0 --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 7b5d1f1..7461b1a 100644 --- a/Package.swift +++ b/Package.swift @@ -9,7 +9,7 @@ let excludes = ["HMAC/HMACCryptoSwift.swift"] let targetDependencies: [Target.Dependency] = [] #else let dependencies = [ - Package.Dependency.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "0.8.0"), + Package.Dependency.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "0.10.0"), ] let excludes = ["HMAC/HMACCommonCrypto.swift"] let targetDependencies: [Target.Dependency] = ["CryptoSwift"] From 2ab9490a71f94ed8b1700cd42af478af186bc848 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 19:27:44 -0500 Subject: [PATCH 47/62] Correct misspelled method name for validateExpiry(leeway:), retain old method name as a deprecated method --- Sources/JWT/ClaimSet.swift | 9 +++++++-- Tests/JWTTests/ClaimSetTests.swift | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Sources/JWT/ClaimSet.swift b/Sources/JWT/ClaimSet.swift index 114c04e..08eeb9f 100644 --- a/Sources/JWT/ClaimSet.swift +++ b/Sources/JWT/ClaimSet.swift @@ -104,7 +104,7 @@ extension ClaimSet { try validateAudience(audience) } - try validateExpiary(leeway: leeway) + try validateExpiry(leeway: leeway) try validateNotBefore(leeway: leeway) try validateIssuedAt(leeway: leeway) } @@ -132,8 +132,13 @@ extension ClaimSet { throw InvalidToken.invalidIssuer } } - + + @available(*, deprecated, message: "This method's name is misspelled. Please instead use validateExpiry(leeway:).") public func validateExpiary(leeway: TimeInterval = 0) throws { + try validateExpiry(leeway: leeway) + } + + public func validateExpiry(leeway: TimeInterval = 0) throws { try validateDate(claims, key: "exp", comparison: .orderedAscending, leeway: (-1 * leeway), failure: .expiredSignature, decodeError: "Expiration time claim (exp) must be an integer") } diff --git a/Tests/JWTTests/ClaimSetTests.swift b/Tests/JWTTests/ClaimSetTests.swift index 594e648..aa8e8dd 100644 --- a/Tests/JWTTests/ClaimSetTests.swift +++ b/Tests/JWTTests/ClaimSetTests.swift @@ -7,7 +7,7 @@ class ValidationTests: XCTestCase { claims.expiration = Date().addingTimeInterval(-1) do { - try claims.validateExpiary() + try claims.validateExpiry() XCTFail("InvalidToken.expiredSignature error should have been thrown.") } catch InvalidToken.expiredSignature { // Correct error thrown @@ -21,7 +21,7 @@ class ValidationTests: XCTestCase { claims.expiration = Date().addingTimeInterval(-1) do { - try claims.validateExpiary(leeway: 2) + try claims.validateExpiry(leeway: 2) } catch { XCTFail("Unexpected error while validating exp claim that should be valid with leeway.") } From 312dce7d8007673275841b3f249f26210a3514b5 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 19:42:38 -0500 Subject: [PATCH 48/62] Remove deprecated encode/decode methods --- Sources/JWT/Decode.swift | 12 ------ Sources/JWT/Encode.swift | 11 ------ Tests/JWTTests/JWTDecodeTests.swift | 59 +++++++++++++---------------- 3 files changed, 26 insertions(+), 56 deletions(-) diff --git a/Sources/JWT/Decode.swift b/Sources/JWT/Decode.swift index 0e2b6d0..b6aa428 100644 --- a/Sources/JWT/Decode.swift +++ b/Sources/JWT/Decode.swift @@ -63,18 +63,6 @@ public func decode(_ jwt: String, algorithm: Algorithm, verify: Bool = true, aud return try decode(jwt, algorithms: [algorithm], verify: verify, audience: audience, issuer: issuer, leeway: leeway) } -/// Decode a JWT -@available(*, deprecated, message: "use decode that returns a ClaimSet instead") -public func decode(_ jwt: String, algorithms: [Algorithm], verify: Bool = true, audience: String? = nil, issuer: String? = nil) throws -> Payload { - return try decode(jwt, algorithms: algorithms, verify: verify, audience: audience, issuer: issuer).claims -} - -/// Decode a JWT -@available(*, deprecated, message: "use decode that returns a ClaimSet instead") -public func decode(_ jwt: String, algorithm: Algorithm, verify: Bool = true, audience: String? = nil, issuer: String? = nil) throws -> Payload { - return try decode(jwt, algorithms: [algorithm], verify: verify, audience: audience, issuer: issuer).claims -} - // MARK: Parsing a JWT func load(_ jwt: String) throws -> (header: JOSEHeader, payload: ClaimSet, signature: Data, signatureInput: String) { diff --git a/Sources/JWT/Encode.swift b/Sources/JWT/Encode.swift index 643c827..22d1960 100644 --- a/Sources/JWT/Encode.swift +++ b/Sources/JWT/Encode.swift @@ -38,14 +38,3 @@ public func encode(_ algorithm: Algorithm, closure: ((ClaimSetBuilder) -> Void)) closure(builder) return encode(claims: builder.claims, algorithm: algorithm) } - - -/*** Encode a payload - - parameter payload: The payload to sign - - parameter algorithm: The algorithm to sign the payload with - - returns: The JSON web token as a String - */ -@available(*, deprecated, message: "use encode(claims: algorithm:) instead") -public func encode(_ payload: Payload, algorithm: Algorithm) -> String { - return encode(claims: ClaimSet(claims: payload), algorithm: algorithm) -} diff --git a/Tests/JWTTests/JWTDecodeTests.swift b/Tests/JWTTests/JWTDecodeTests.swift index cc4bf6d..313b000 100644 --- a/Tests/JWTTests/JWTDecodeTests.swift +++ b/Tests/JWTTests/JWTDecodeTests.swift @@ -3,29 +3,22 @@ import XCTest @testable import JWT class DecodeTests: XCTestCase { - func testDecodingValidJWTAsClaimSet() throws { - let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS3lsZSJ9.zxm7xcp1eZtZhp4t-nlw09ATQnnFKIiSN83uG8u6cAg" - - let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) - XCTAssertEqual(claims["name"] as? String, "Kyle") - } - func testDecodingValidJWT() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS3lsZSJ9.zxm7xcp1eZtZhp4t-nlw09ATQnnFKIiSN83uG8u6cAg" - let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) XCTAssertEqual(claims["name"] as? String, "Kyle") } func testFailsToDecodeInvalidStringWithoutThreeSegments() { - XCTAssertThrowsError(try decode("a.b", algorithm: .none) as ClaimSet, "Not enough segments") + XCTAssertThrowsError(try decode("a.b", algorithm: .none), "Not enough segments") } // MARK: Disable verify func testDisablingVerify() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w" - _ = try decode(jwt, algorithm: .none, verify: false, issuer: "fuller.li") as ClaimSet + _ = try decode(jwt, algorithm: .none, verify: false, issuer: "fuller.li") } // MARK: Issuer claim @@ -33,37 +26,37 @@ class DecodeTests: XCTestCase { func testSuccessfulIssuerValidation() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.d7B7PAQcz1E6oNhrlxmHxHXHgg39_k7X7wWeahl8kSQ" - let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) XCTAssertEqual(claims.issuer, "fuller.li") } func testIncorrectIssuerValidation() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmdWxsZXIubGkifQ.wOhJ9_6lx-3JGJPmJmtFCDI3kt7uMAMmhHIslti7ryI" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "querykit.org") as ClaimSet) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "querykit.org")) } func testMissingIssuerValidation() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "fuller.li") as ClaimSet) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), issuer: "fuller.li")) } // MARK: Expiration claim func testExpiredClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0MjgxODg0OTF9.cy6b2szsNkKnHFnz2GjTatGjoHBTs8vBKnPGZgpp91I" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } func testInvalidExpiaryClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOlsiMTQyODE4ODQ5MSJdfQ.OwF-wd3THjxrEGUhh6IdnNhxQZ7ydwJ3Z6J_dfl9MBs" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } func testUnexpiredClaim() throws { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjgxODg0OTF9.EW7k-8Mvnv0GpvOKJalFRLoCB3a3xGG3i7hAZZXNAz0" - let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) XCTAssertEqual(claims.expiration?.timeIntervalSince1970, 1728188491) } @@ -71,7 +64,7 @@ class DecodeTests: XCTestCase { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNzI4MTg4NDkxIn0.y4w7lNLrfRRPzuNUfM-ZvPkoOtrTU_d8ZVYasLdZGpk" - let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) XCTAssertEqual(claims.expiration?.timeIntervalSince1970, 1728188491) } @@ -80,26 +73,26 @@ class DecodeTests: XCTestCase { func testNotBeforeClaim() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0MjgxODk3MjB9.jFT0nXAJvEwyG6R7CMJlzNJb7FtZGv30QRZpYam5cvs" - let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) XCTAssertEqual(claims.notBefore?.timeIntervalSince1970, 1428189720) } func testNotBeforeClaimString() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOiIxNDI4MTg5NzIwIn0.qZsj36irdmIAeXv6YazWDSFbpuxHtEh4Deof5YTpnVI" - let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) XCTAssertEqual(claims.notBefore?.timeIntervalSince1970, 1428189720) } func testInvalidNotBeforeClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOlsxNDI4MTg5NzIwXX0.PUL1FQubzzJa4MNXe2D3d5t5cMaqFr3kYlzRUzly-C8" - assertDecodeError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet, error: "Not before claim (nbf) must be an integer") + assertDecodeError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)), error: "Not before claim (nbf) must be an integer") } func testUnmetNotBeforeClaim() { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3MjgxODg0OTF9.Tzhu1tu-7BXcF5YEIFFE1Vmg4tEybUnaz58FR4PcblQ" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } // MARK: Issued at claim @@ -107,21 +100,21 @@ class DecodeTests: XCTestCase { func testIssuedAtClaimInThePast() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MjgxODk3MjB9.I_5qjRcCUZVQdABLwG82CSuu2relSdIyJOyvXWUAJh4" - let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) XCTAssertEqual(claims.issuedAt?.timeIntervalSince1970, 1428189720) } func testIssuedAtClaimInThePastString() throws { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNDI4MTg5NzIwIn0.M8veWtsY52oBwi7LRKzvNnzhjK0QBS8Su1r0atlns2k" - let claims: ClaimSet = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) + let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) XCTAssertEqual(claims.issuedAt?.timeIntervalSince1970, 1428189720) } func testIssuedAtClaimInTheFuture() { // If this just started failing, hello 2024! let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MjgxODg0OTF9.owHiJyJmTcW1lBW5y_Rz3iBfSbcNiXlbZ2fY9qR7-aU" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } func testInvalidIssuedAtClaim() { @@ -134,7 +127,7 @@ class DecodeTests: XCTestCase { func testAudiencesClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibWF4aW5lIiwia2F0aWUiXX0.-PKvdNLCClrWG7CvesHP6PB0-vxu-_IZcsYhJxBy5JM" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine") as ClaimSet) { payload in + assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine")) { payload in XCTAssertEqual(payload.count, 1) XCTAssertEqual(payload["aud"] as! [String], ["maxine", "katie"]) } @@ -142,50 +135,50 @@ class DecodeTests: XCTestCase { func testAudienceClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJreWxlIn0.dpgH4JOwueReaBoanLSxsGTc7AjKUvo7_M1sAfy_xVE" - assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle") as ClaimSet) { payload in + assertSuccess(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle")) { payload in XCTAssertEqual(payload as! [String: String], ["aud": "kyle"]) } } func testMismatchAudienceClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJreWxlIn0.VEB_n06pTSLlTXPFkc46ARADJ9HXNUBUPo3VhL9RDe4" // kyle - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine") as ClaimSet) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "maxine")) } func testMissingAudienceClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w" - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle") as ClaimSet) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!), audience: "kyle")) } // MARK: Signature verification func testNoneAlgorithm() { let jwt = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ0ZXN0IjoiaW5nIn0." - assertSuccess(try decode(jwt, algorithm: .none) as ClaimSet) { payload in + assertSuccess(try decode(jwt, algorithm: .none)) { payload in XCTAssertEqual(payload as! [String: String], ["test": "ing"]) } } func testNoneFailsWithSecretAlgorithm() { let jwt = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ0ZXN0IjoiaW5nIn0." - XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) as ClaimSet) + XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } func testMatchesAnyAlgorithm() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.2_8pWJfyPup0YwOXK7g9Dn0cF1E3pdn299t4hSeJy5w." - assertFailure(try decode(jwt, algorithms: [.hs256("anothersecret".data(using: .utf8)!), .hs256("secret".data(using: .utf8)!)]) as ClaimSet) + assertFailure(try decode(jwt, algorithms: [.hs256("anothersecret".data(using: .utf8)!), .hs256("secret".data(using: .utf8)!)])) } func testHS384Algorithm() { let jwt = "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.lddiriKLoo42qXduMhCTKZ5Lo3njXxOC92uXyvbLyYKzbq4CVVQOb3MpDwnI19u4" - assertSuccess(try decode(jwt, algorithm: .hs384("secret".data(using: .utf8)!)) as ClaimSet) { payload in + assertSuccess(try decode(jwt, algorithm: .hs384("secret".data(using: .utf8)!))) { payload in XCTAssertEqual(payload as! [String: String], ["some": "payload"]) } } func testHS512Algorithm() { let jwt = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.WTzLzFO079PduJiFIyzrOah54YaM8qoxH9fLMQoQhKtw3_fMGjImIOokijDkXVbyfBqhMo2GCNu4w9v7UXvnpA" - assertSuccess(try decode(jwt, algorithm: .hs512("secret".data(using: .utf8)!)) as ClaimSet) { claims in + assertSuccess(try decode(jwt, algorithm: .hs512("secret".data(using: .utf8)!))) { claims in XCTAssertEqual(claims as! [String: String], ["some": "payload"]) } } From 30677dfbb1c473b87ea55bc3775fed1fb6b3f5a7 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 20:14:48 -0500 Subject: [PATCH 49/62] Undo removal of CommonCrypto; will try to find compatible solution between Swift 4.0 and 4.2 --- CommonCrypto/module.modulemap | 4 ++++ CommonCrypto/shim.h | 1 + Package.swift | 4 +++- 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 CommonCrypto/module.modulemap create mode 100644 CommonCrypto/shim.h diff --git a/CommonCrypto/module.modulemap b/CommonCrypto/module.modulemap new file mode 100644 index 0000000..b70f7d6 --- /dev/null +++ b/CommonCrypto/module.modulemap @@ -0,0 +1,4 @@ +module CommonCrypto [system] { + header "shim.h" + export * +} diff --git a/CommonCrypto/shim.h b/CommonCrypto/shim.h new file mode 100644 index 0000000..c332624 --- /dev/null +++ b/CommonCrypto/shim.h @@ -0,0 +1 @@ +#include diff --git a/Package.swift b/Package.swift index 7461b1a..36bc2f2 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,9 @@ import PackageDescription #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) -let dependencies: [Package.Dependency] = [] +let dependencies = [ + Package.Dependency.package(url: "https://github.com/kylef-archive/CommonCrypto.git", from: "1.0.0"), +] let excludes = ["HMAC/HMACCryptoSwift.swift"] let targetDependencies: [Target.Dependency] = [] #else From 662871d1b9a4c4ba2642ac6f08237ecfed4b5dd0 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 21:33:46 -0500 Subject: [PATCH 50/62] see if stripping down the Travis config gets builds working on macOS at least --- .travis.yml | 86 ++++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/.travis.yml b/.travis.yml index 225f25f..701dcfa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,44 +1,48 @@ -os: - - osx - - linux -osx_image: xcode9 -language: generic -sudo: required -dist: trusty -env: - global: - - SWIFT_VERSION=4.0 - matrix: - - SWIFTPM_BUILD=true - - SWIFTPM_TEST=true - - XCODE_TEST_SDK=macosx - - XCODE_BUILD_SDK=iphonesimulator - - XCODE_BUILD_SDK=appletvsimulator - - XCODE_BUILD_SDK=watchsimulator +os: osx +osx_image: xcode9.4 +script: swift build -matrix: - exclude: - # No need to build and test on macOS - - os: osx - env: SWIFTPM_BUILD=true - # LinuxMain.swift is out of sync - - os: linux - env: SWIFTPM_TEST=true - - os: linux - env: XCODE_TEST_SDK=macosx - - os: linux - env: XCODE_BUILD_SDK=iphonesimulator - - os: linux - env: XCODE_BUILD_SDK=appletvsimulator - - os: linux - env: XCODE_BUILD_SDK=watchsimulator +# os: +# - osx +# - linux +# osx_image: xcode9 +# language: generic +# sudo: required +# dist: trusty +# env: +# global: +# - SWIFT_VERSION=4.0 +# matrix: +# - SWIFTPM_BUILD=true +# - SWIFTPM_TEST=true +# - XCODE_TEST_SDK=macosx +# - XCODE_BUILD_SDK=iphonesimulator +# - XCODE_BUILD_SDK=appletvsimulator +# - XCODE_BUILD_SDK=watchsimulator -install: - - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" +# matrix: +# exclude: +# # No need to build and test on macOS +# - os: osx +# env: SWIFTPM_BUILD=true +# # LinuxMain.swift is out of sync +# - os: linux +# env: SWIFTPM_TEST=true +# - os: linux +# env: XCODE_TEST_SDK=macosx +# - os: linux +# env: XCODE_BUILD_SDK=iphonesimulator +# - os: linux +# env: XCODE_BUILD_SDK=appletvsimulator +# - os: linux +# env: XCODE_BUILD_SDK=watchsimulator -script: -- if [ -n "$SWIFTPM_BUILD" ]; then swift build; fi -- if [ -n "$SWIFTPM_TEST" ]; then swift test; fi -- if [ -n "$XCODE_BUILD_SDK" ] || [ -n "$XCODE_TEST_SDK" ]; then swift package generate-xcodeproj; fi -- if [ -n "$XCODE_BUILD_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk $XCODE_BUILD_SDK; fi -- if [ -n "$XCODE_TEST_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package test -sdk $XCODE_TEST_SDK; fi +# install: +# - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" + +# script: +# - if [ -n "$SWIFTPM_BUILD" ]; then swift build; fi +# - if [ -n "$SWIFTPM_TEST" ]; then swift test; fi +# - if [ -n "$XCODE_BUILD_SDK" ] || [ -n "$XCODE_TEST_SDK" ]; then swift package generate-xcodeproj; fi +# - if [ -n "$XCODE_BUILD_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk $XCODE_BUILD_SDK; fi +# - if [ -n "$XCODE_TEST_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package test -sdk $XCODE_TEST_SDK; fi From 47a8b7f6f8c0523202f9d468eab1b0dd69b26fdf Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 21:44:27 -0500 Subject: [PATCH 51/62] try adding Ubuntu back into Travis builds --- .travis.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 701dcfa..a50c6e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,20 @@ -os: osx +os: + - osx + - linux osx_image: xcode9.4 script: swift build +language: generic +sudo: required +dist: xenial + +env: + global: + - SWIFT_VERSION=4.1.2 + +install: + - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" +script: + - swift build # os: # - osx @@ -10,8 +24,6 @@ script: swift build # sudo: required # dist: trusty # env: -# global: -# - SWIFT_VERSION=4.0 # matrix: # - SWIFTPM_BUILD=true # - SWIFTPM_TEST=true From 11351084b4cd4eb7a9558b5c109ab5be361fccb5 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 22:20:33 -0500 Subject: [PATCH 52/62] =?UTF-8?q?Travis=20doesn=E2=80=99t=20support=20Xeni?= =?UTF-8?q?al,=20back=20to=20Trusty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a50c6e2..8d4abdd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ osx_image: xcode9.4 script: swift build language: generic sudo: required -dist: xenial +dist: trusty env: global: From a50823d3c9c85a6f70fd162e7043610ca098a037 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 22:43:44 -0500 Subject: [PATCH 53/62] getting closer to original config --- .travis.yml | 69 +++++++++++++++++++++-------------------------------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8d4abdd..6a5dca8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,7 @@ os: - - osx - - linux + - osx + - linux osx_image: xcode9.4 -script: swift build language: generic sudo: required dist: trusty @@ -10,51 +9,37 @@ dist: trusty env: global: - SWIFT_VERSION=4.1.2 + matrix: + - SWIFTPM_BUILD=true + - SWIFTPM_TEST=true + - XCODE_TEST_SDK=macosx + - XCODE_BUILD_SDK=iphonesimulator + - XCODE_BUILD_SDK=appletvsimulator + - XCODE_BUILD_SDK=watchsimulator -install: - - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" -script: - - swift build - -# os: -# - osx -# - linux -# osx_image: xcode9 -# language: generic -# sudo: required -# dist: trusty -# env: -# matrix: -# - SWIFTPM_BUILD=true -# - SWIFTPM_TEST=true -# - XCODE_TEST_SDK=macosx -# - XCODE_BUILD_SDK=iphonesimulator -# - XCODE_BUILD_SDK=appletvsimulator -# - XCODE_BUILD_SDK=watchsimulator - -# matrix: -# exclude: +matrix: + exclude: # # No need to build and test on macOS # - os: osx # env: SWIFTPM_BUILD=true # # LinuxMain.swift is out of sync # - os: linux # env: SWIFTPM_TEST=true -# - os: linux -# env: XCODE_TEST_SDK=macosx -# - os: linux -# env: XCODE_BUILD_SDK=iphonesimulator -# - os: linux -# env: XCODE_BUILD_SDK=appletvsimulator -# - os: linux -# env: XCODE_BUILD_SDK=watchsimulator + - os: linux + env: XCODE_TEST_SDK=macosx + - os: linux + env: XCODE_BUILD_SDK=iphonesimulator + - os: linux + env: XCODE_BUILD_SDK=appletvsimulator + - os: linux + env: XCODE_BUILD_SDK=watchsimulator -# install: -# - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" +install: + - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" -# script: -# - if [ -n "$SWIFTPM_BUILD" ]; then swift build; fi -# - if [ -n "$SWIFTPM_TEST" ]; then swift test; fi -# - if [ -n "$XCODE_BUILD_SDK" ] || [ -n "$XCODE_TEST_SDK" ]; then swift package generate-xcodeproj; fi -# - if [ -n "$XCODE_BUILD_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk $XCODE_BUILD_SDK; fi -# - if [ -n "$XCODE_TEST_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package test -sdk $XCODE_TEST_SDK; fi +script: +- if [ -n "$SWIFTPM_BUILD" ]; then swift build; fi +- if [ -n "$SWIFTPM_TEST" ]; then swift test; fi +- if [ -n "$XCODE_BUILD_SDK" ] || [ -n "$XCODE_TEST_SDK" ]; then swift package generate-xcodeproj; fi +- if [ -n "$XCODE_BUILD_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk $XCODE_BUILD_SDK; fi +- if [ -n "$XCODE_TEST_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package test -sdk $XCODE_TEST_SDK; fi From 44d6d594da50911cddf3792e004b48d11c5f4908 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 23:03:52 -0500 Subject: [PATCH 54/62] Sync up LinuxMain.swift (hopefully) --- Tests/LinuxMain.swift | 89 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 9 deletions(-) diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 8488183..b12a121 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -1,18 +1,51 @@ import XCTest +@testable import JWATests @testable import JWTTests +extension HMACAlgorithmTests { + static var allTests: [(String, (HMACAlgorithmTests) -> () throws -> Void)] { + return [ + ("testSHA256Name", testSHA256Name), + ("testSHA384Name", testSHA384Name), + ("testSHA512Name", testSHA512Name), + ("testSHA256Sign", testSHA256Sign), + ("testSHA384Sign", testSHA384Sign), + ("testSHA512Sign", testSHA512Sign), + ("testSHA256Verify", testSHA256Verify), + ("testSHA384Verify", testSHA384Verify), + ("testSHA512Verify", testSHA512Verify) + ] + } +} -extension EncodeTests { - static var allTests: [(String, (EncodeTests) -> (Void) throws -> Void)] { +extension NoneAlgorithmTests { + static var allTests: [(String, (NoneAlgorithmTests) -> () throws -> Void)] { return [ - ("testEncodingJWT", testEncodingJWT), - ("testEncodingWithBuilder", testEncodingWithBuilder), + ("testName", testName), + ("testSign", testSign), + ("testVerify", testVerify) ] } } +extension CompactJSONDecoderTests { + static var allTests: [(String, (CompactJSONDecoderTests) -> () throws -> Void)] { + return [ + ("testDecoder", testDecoder) + ] + } +} + +extension CompactJSONEncoderTests { + static var allTests: [(String, (CompactJSONEncoderTests) -> () throws -> Void)] { + return [ + ("testEncode", testEncode) + ] + } +} + extension DecodeTests { - static var allTests: [(String, (DecodeTests) -> (Void) throws -> Void)] { + static var allTests: [(String, (DecodeTests) -> () throws -> Void)] { return [ ("testDecodingValidJWT", testDecodingValidJWT), ("testFailsToDecodeInvalidStringWithoutThreeSegments", testFailsToDecodeInvalidStringWithoutThreeSegments), @@ -40,26 +73,64 @@ extension DecodeTests { ("testNoneFailsWithSecretAlgorithm", testNoneFailsWithSecretAlgorithm), ("testMatchesAnyAlgorithm", testMatchesAnyAlgorithm), ("testHS384Algorithm", testHS384Algorithm), - ("testHS512Algorithm", testHS512Algorithm), + ("testHS512Algorithm", testHS512Algorithm) ] } } +extension IntegrationTests { + static var allTests: [(String, (IntegrationTests) -> () throws -> Void)] { + return [ + ("testVerificationFailureWithoutLeeway", testVerificationFailureWithoutLeeway), + ("testVerificationSuccessWithLeeway", testVerificationSuccessWithLeeway) + ] + } +} + +extension JWTEncodeTests { + static var allTests: [(String, (JWTEncodeTests) -> () throws -> Void)] { + return [ + ("testEncodingJWT", testEncodingJWT), + ("testEncodingWithBuilder", testEncodingWithBuilder), + ("testEncodingClaimsWithHeaders", testEncodingClaimsWithHeaders) + ] + } +} + extension PayloadTests { - static var allTests: [(String, (PayloadTests) -> (Void) throws -> Void)] { + static var allTests: [(String, (PayloadTests) -> () throws -> Void)] { return [ ("testIssuer", testIssuer), ("testAudience", testAudience), ("testExpiration", testExpiration), ("testNotBefore", testNotBefore), ("testIssuedAt", testIssuedAt), - ("testCustomAttributes", testCustomAttributes), + ("testCustomAttributes", testCustomAttributes) ] } } +extension ValidationTests { + static var allTests: [(String, (ValidationTests) -> () throws -> Void)] { + return [ + ("testClaimJustExpiredWithoutLeeway", testClaimJustExpiredWithoutLeeway), + ("testClaimJustNotExpiredWithoutLeeway", testClaimJustNotExpiredWithoutLeeway), + ("testNotBeforeIsImmatureSignatureWithoutLeeway", testNotBeforeIsImmatureSignatureWithoutLeeway), + ("testNotBeforeIsValidWithLeeway", testNotBeforeIsValidWithLeeway), + ("testIssuedAtIsInFutureWithoutLeeway", testIssuedAtIsInFutureWithoutLeeway), + ("testIssuedAtIsValidWithLeeway", testIssuedAtIsValidWithLeeway) + ] + } +} + XCTMain([ - testCase(EncodeTests.allTests), + testCase(HMACAlgorithmTests.allTests), + testCase(NoneAlgorithmTests.allTests), + testCase(CompactJSONDecoder.allTests), + testCase(CompactJSONEncoder.allTests), testCase(DecodeTests.allTests), + testCase(IntegrationTests.allTests), + testCase(JWTEncodeTests.allTests), testCase(PayloadTests.allTests), + testCase(ValidationTests.allTests) ]) From 32b7b6e5db2edd889bd9e3a6c2c2d15f1d42390b Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 23 Jul 2018 23:15:30 -0500 Subject: [PATCH 55/62] Fix LinuxMain.swift typo --- Tests/LinuxMain.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index b12a121..3f3b768 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -126,8 +126,8 @@ extension ValidationTests { XCTMain([ testCase(HMACAlgorithmTests.allTests), testCase(NoneAlgorithmTests.allTests), - testCase(CompactJSONDecoder.allTests), - testCase(CompactJSONEncoder.allTests), + testCase(CompactJSONDecoderTests.allTests), + testCase(CompactJSONEncoderTests.allTests), testCase(DecodeTests.allTests), testCase(IntegrationTests.allTests), testCase(JWTEncodeTests.allTests), From 65dfb1a9f61a76f55bb9c23ff272ed1443a954dc Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Tue, 24 Jul 2018 12:49:03 -0500 Subject: [PATCH 56/62] See if converting TimeInterval/Double to Int might help Travis builds pass --- Tests/JWTTests/JWTDecodeTests.swift | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Tests/JWTTests/JWTDecodeTests.swift b/Tests/JWTTests/JWTDecodeTests.swift index 313b000..adca9ab 100644 --- a/Tests/JWTTests/JWTDecodeTests.swift +++ b/Tests/JWTTests/JWTDecodeTests.swift @@ -57,7 +57,12 @@ class DecodeTests: XCTestCase { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjgxODg0OTF9.EW7k-8Mvnv0GpvOKJalFRLoCB3a3xGG3i7hAZZXNAz0" let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) - XCTAssertEqual(claims.expiration?.timeIntervalSince1970, 1728188491) + + if let expirationClaim = claims.expiration?.timeIntervalSince1970 { + XCTAssertEqual(Int(expirationClaim), 1728188491) + } else { + XCTFail() + } } func testUnexpiredClaimString() throws { @@ -74,7 +79,11 @@ class DecodeTests: XCTestCase { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0MjgxODk3MjB9.jFT0nXAJvEwyG6R7CMJlzNJb7FtZGv30QRZpYam5cvs" let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) - XCTAssertEqual(claims.notBefore?.timeIntervalSince1970, 1428189720) + if let notBeforeClaim = claims.notBefore?.timeIntervalSince1970 { + XCTAssertEqual(Int(notBeforeClaim), 1428189720) + } else { + XCTFail() + } } func testNotBeforeClaimString() throws { @@ -101,7 +110,11 @@ class DecodeTests: XCTestCase { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MjgxODk3MjB9.I_5qjRcCUZVQdABLwG82CSuu2relSdIyJOyvXWUAJh4" let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) - XCTAssertEqual(claims.issuedAt?.timeIntervalSince1970, 1428189720) + if let issuedAtClaim = claims.issuedAt?.timeIntervalSince1970 { + XCTAssertEqual(Int(issuedAtClaim), 1428189720) + } else { + XCTFail() + } } func testIssuedAtClaimInThePastString() throws { From f2bbd1d8dbf2e53234f9d632c5a8808aaaf9b0db Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Tue, 24 Jul 2018 12:59:51 -0500 Subject: [PATCH 57/62] See if explicitly handling Ints in parsing JWT times fixes Ubuntu builds --- Sources/JWT/ClaimSet.swift | 5 +++++ Tests/JWTTests/JWTDecodeTests.swift | 19 +++---------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Sources/JWT/ClaimSet.swift b/Sources/JWT/ClaimSet.swift index 08eeb9f..4b253be 100644 --- a/Sources/JWT/ClaimSet.swift +++ b/Sources/JWT/ClaimSet.swift @@ -6,6 +6,11 @@ func parseTimeInterval(_ value: Any?) -> Date? { if let string = value as? String, let interval = TimeInterval(string) { return Date(timeIntervalSince1970: interval) } + + if let interval = value as? Int { + let double = Double(interval) + return Date(timeIntervalSince1970: double) + } if let interval = value as? TimeInterval { return Date(timeIntervalSince1970: interval) diff --git a/Tests/JWTTests/JWTDecodeTests.swift b/Tests/JWTTests/JWTDecodeTests.swift index adca9ab..7cfe348 100644 --- a/Tests/JWTTests/JWTDecodeTests.swift +++ b/Tests/JWTTests/JWTDecodeTests.swift @@ -57,12 +57,7 @@ class DecodeTests: XCTestCase { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjgxODg0OTF9.EW7k-8Mvnv0GpvOKJalFRLoCB3a3xGG3i7hAZZXNAz0" let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) - - if let expirationClaim = claims.expiration?.timeIntervalSince1970 { - XCTAssertEqual(Int(expirationClaim), 1728188491) - } else { - XCTFail() - } + XCTAssertEqual(claims.expiration?.timeIntervalSince1970, 1728188491) } func testUnexpiredClaimString() throws { @@ -79,11 +74,7 @@ class DecodeTests: XCTestCase { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0MjgxODk3MjB9.jFT0nXAJvEwyG6R7CMJlzNJb7FtZGv30QRZpYam5cvs" let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) - if let notBeforeClaim = claims.notBefore?.timeIntervalSince1970 { - XCTAssertEqual(Int(notBeforeClaim), 1428189720) - } else { - XCTFail() - } + XCTAssertEqual(claims.notBefore?.timeIntervalSince1970, 1428189720) } func testNotBeforeClaimString() throws { @@ -110,11 +101,7 @@ class DecodeTests: XCTestCase { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MjgxODk3MjB9.I_5qjRcCUZVQdABLwG82CSuu2relSdIyJOyvXWUAJh4" let claims = try JWT.decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!)) - if let issuedAtClaim = claims.issuedAt?.timeIntervalSince1970 { - XCTAssertEqual(Int(issuedAtClaim), 1428189720) - } else { - XCTFail() - } + XCTAssertEqual(claims.issuedAt?.timeIntervalSince1970, 1428189720) } func testIssuedAtClaimInThePastString() throws { From 4b83583095569f47751f97832f990933c113d7f8 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Tue, 24 Jul 2018 16:16:47 -0500 Subject: [PATCH 58/62] simplify Travis config to use swift test only swift test builds JWT and JWA, so compilation errors for those will otherwise just result in two jobs that fail for the same reason; one can still check the Travis output to see where exactly the failure is occurring --- .travis.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6a5dca8..2c00dc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,9 +8,9 @@ dist: trusty env: global: + - SWIFT_VERSION=4.0 - SWIFT_VERSION=4.1.2 matrix: - - SWIFTPM_BUILD=true - SWIFTPM_TEST=true - XCODE_TEST_SDK=macosx - XCODE_BUILD_SDK=iphonesimulator @@ -19,12 +19,6 @@ env: matrix: exclude: -# # No need to build and test on macOS -# - os: osx -# env: SWIFTPM_BUILD=true -# # LinuxMain.swift is out of sync -# - os: linux -# env: SWIFTPM_TEST=true - os: linux env: XCODE_TEST_SDK=macosx - os: linux @@ -38,7 +32,6 @@ install: - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" script: -- if [ -n "$SWIFTPM_BUILD" ]; then swift build; fi - if [ -n "$SWIFTPM_TEST" ]; then swift test; fi - if [ -n "$XCODE_BUILD_SDK" ] || [ -n "$XCODE_TEST_SDK" ]; then swift package generate-xcodeproj; fi - if [ -n "$XCODE_BUILD_SDK" ]; then xcodebuild -project JWT.xcodeproj -scheme JWT-Package build -sdk $XCODE_BUILD_SDK; fi From 708c7a75e38d689c27e6fec1b6bc18a251455559 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Tue, 24 Jul 2018 16:48:23 -0500 Subject: [PATCH 59/62] Correct misspelled unit test method name --- Tests/JWTTests/JWTDecodeTests.swift | 2 +- Tests/LinuxMain.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/JWTTests/JWTDecodeTests.swift b/Tests/JWTTests/JWTDecodeTests.swift index 7cfe348..cde1a10 100644 --- a/Tests/JWTTests/JWTDecodeTests.swift +++ b/Tests/JWTTests/JWTDecodeTests.swift @@ -47,7 +47,7 @@ class DecodeTests: XCTestCase { XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } - func testInvalidExpiaryClaim() { + func testInvalidExpiryClaim() { let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOlsiMTQyODE4ODQ5MSJdfQ.OwF-wd3THjxrEGUhh6IdnNhxQZ7ydwJ3Z6J_dfl9MBs" XCTAssertThrowsError(try decode(jwt, algorithm: .hs256("secret".data(using: .utf8)!))) } diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 3f3b768..492555b 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -54,7 +54,7 @@ extension DecodeTests { ("testIncorrectIssuerValidation", testIncorrectIssuerValidation), ("testMissingIssuerValidation", testMissingIssuerValidation), ("testExpiredClaim", testExpiredClaim), - ("testInvalidExpiaryClaim", testInvalidExpiaryClaim), + ("testInvalidExpiryClaim", testInvalidExpiryClaim), ("testUnexpiredClaim", testUnexpiredClaim), ("testUnexpiredClaimString", testUnexpiredClaimString), ("testNotBeforeClaim", testNotBeforeClaim), From 44f4b7a4ed7c1d2a165e106f2eb236ad199a54be Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Tue, 24 Jul 2018 17:41:02 -0500 Subject: [PATCH 60/62] Fix for CommonCrypto inclusion in Swift 4.2 --- Package.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Package.swift b/Package.swift index 36bc2f2..01b5e95 100644 --- a/Package.swift +++ b/Package.swift @@ -4,9 +4,13 @@ import PackageDescription #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) +#if canImport(CommonCrypto) +let dependencies: [Package.Dependency] = [] +#else let dependencies = [ Package.Dependency.package(url: "https://github.com/kylef-archive/CommonCrypto.git", from: "1.0.0"), ] +#endif let excludes = ["HMAC/HMACCryptoSwift.swift"] let targetDependencies: [Target.Dependency] = [] #else From 898f0c8ef842134c585cd5d0bc5dc0eb5dd878ed Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 6 Aug 2018 19:11:16 -0500 Subject: [PATCH 61/62] Add podspec --- JSONWebToken.podspec | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 JSONWebToken.podspec diff --git a/JSONWebToken.podspec b/JSONWebToken.podspec new file mode 100644 index 0000000..3e885ae --- /dev/null +++ b/JSONWebToken.podspec @@ -0,0 +1,32 @@ +Pod::Spec.new do |spec| + spec.name = 'JSONWebToken' + spec.version = '3.0.0' + spec.summary = 'Swift library for JSON Web Tokens (JWT).' + spec.homepage = 'https://github.com/kylef/JSONWebToken.swift' + spec.license = { :type => 'BSD', :file => 'LICENSE' } + spec.author = { 'Kyle Fuller' => 'kyle@fuller.li' } + spec.source = { :git => 'https://github.com/kylef/JSONWebToken.swift.git' } + spec.source_files = 'Sources/JWT/*.swift', 'Build-Phases/common-crypto.sh' + spec.ios.deployment_target = '8.0' + spec.osx.deployment_target = '10.9' + spec.tvos.deployment_target = '9.0' + spec.watchos.deployment_target = '2.0' + spec.requires_arc = true + spec.module_name = 'JWT' + spec.exclude_files = ['Sources/JWT/HMACCryptoSwift.swift'] + + spec.swift_version = '4.0' + + if ARGV.include?('lint') + spec.pod_target_xcconfig = { + 'SWIFT_INCLUDE_PATHS' => Dir.pwd, + } + else + spec.pod_target_xcconfig = { + 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/JSONWebToken/', + } + end + + spec.preserve_paths = 'Build-Phases/*.sh' + spec.script_phase = { :name => 'CommonCrypto', :script => 'sh $SRCROOT/JSONWebToken/Build-Phases/common-crypto.sh', :execution_position => :before_compile } +end From 50b7757bec445b2bd2d2cccdfc18d2ade912d940 Mon Sep 17 00:00:00 2001 From: Jonathan Thornton Date: Mon, 6 Aug 2018 21:26:28 -0500 Subject: [PATCH 62/62] Delete JSONWebToken.podspec --- JSONWebToken.podspec | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 JSONWebToken.podspec diff --git a/JSONWebToken.podspec b/JSONWebToken.podspec deleted file mode 100644 index 3e885ae..0000000 --- a/JSONWebToken.podspec +++ /dev/null @@ -1,32 +0,0 @@ -Pod::Spec.new do |spec| - spec.name = 'JSONWebToken' - spec.version = '3.0.0' - spec.summary = 'Swift library for JSON Web Tokens (JWT).' - spec.homepage = 'https://github.com/kylef/JSONWebToken.swift' - spec.license = { :type => 'BSD', :file => 'LICENSE' } - spec.author = { 'Kyle Fuller' => 'kyle@fuller.li' } - spec.source = { :git => 'https://github.com/kylef/JSONWebToken.swift.git' } - spec.source_files = 'Sources/JWT/*.swift', 'Build-Phases/common-crypto.sh' - spec.ios.deployment_target = '8.0' - spec.osx.deployment_target = '10.9' - spec.tvos.deployment_target = '9.0' - spec.watchos.deployment_target = '2.0' - spec.requires_arc = true - spec.module_name = 'JWT' - spec.exclude_files = ['Sources/JWT/HMACCryptoSwift.swift'] - - spec.swift_version = '4.0' - - if ARGV.include?('lint') - spec.pod_target_xcconfig = { - 'SWIFT_INCLUDE_PATHS' => Dir.pwd, - } - else - spec.pod_target_xcconfig = { - 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/JSONWebToken/', - } - end - - spec.preserve_paths = 'Build-Phases/*.sh' - spec.script_phase = { :name => 'CommonCrypto', :script => 'sh $SRCROOT/JSONWebToken/Build-Phases/common-crypto.sh', :execution_position => :before_compile } -end