Skip to content
This repository was archived by the owner on Aug 15, 2019. It is now read-only.

Remove deprecated encode/decode, fix warnings, other fixes #1

Merged
merged 10 commits into from
Jul 24, 2018
Merged
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,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"]
Expand Down
2 changes: 1 addition & 1 deletion Sources/JWA/HMAC/HMACCommonCrypto.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import CommonCrypto
extension HMACAlgorithm: SignAlgorithm, VerifyAlgorithm {
public func sign(_ message: Data) -> Data {
let context = UnsafeMutablePointer<CCHmacContext>.allocate(capacity: 1)
defer { context.deallocate(capacity: 1) }
defer { context.deallocate() }

key.withUnsafeBytes() { (buffer: UnsafePointer<UInt8>) in
CCHmacInit(context, hash.commonCryptoAlgorithm, buffer, size_t(key.count))
Expand Down
9 changes: 7 additions & 2 deletions Sources/JWT/ClaimSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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")
}

Expand Down
12 changes: 0 additions & 12 deletions Sources/JWT/Decode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
11 changes: 0 additions & 11 deletions Sources/JWT/Encode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
4 changes: 2 additions & 2 deletions Tests/JWTTests/ClaimSetTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.")
}
Expand Down
41 changes: 17 additions & 24 deletions Tests/JWTTests/JWTDecodeTests.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import Foundation
import XCTest
import JWT
@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")
}

Expand All @@ -25,15 +18,15 @@ class DecodeTests: XCTestCase {

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

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")
}

Expand Down Expand Up @@ -63,15 +56,15 @@ class DecodeTests: XCTestCase {
// 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)
}

func testUnexpiredClaimString() throws {
// 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)
}

Expand All @@ -80,14 +73,14 @@ 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)
}

Expand All @@ -107,14 +100,14 @@ 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)
}

Expand Down Expand Up @@ -185,24 +178,24 @@ class DecodeTests: XCTestCase {

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)!))) { 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.")
Expand All @@ -213,7 +206,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):
Expand Down
42 changes: 32 additions & 10 deletions Tests/JWTTests/JWTEncodeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +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"
}

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"])

XCTAssertEqual(jwt, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IngifQ.e30.ddEotxYYMMdat5HPgYFQnkHRdPXsxPG71ooyhIUoqGA")

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))
}
}