Skip to content

Commit

Permalink
refactor: Make internal validators throwing
Browse files Browse the repository at this point in the history
  • Loading branch information
kylef committed Dec 2, 2016
1 parent 1e3d591 commit a6574d5
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 28 deletions.
37 changes: 16 additions & 21 deletions Sources/Claims.swift
Original file line number Diff line number Diff line change
@@ -1,53 +1,48 @@
import Foundation

func validateClaims(_ payload:Payload, audience:String?, issuer:String?) -> InvalidToken? {
return validateIssuer(payload, issuer: issuer) ?? validateAudience(payload, audience: audience) ??
validateDate(payload, key: "exp", comparison: .orderedAscending, failure: .expiredSignature, decodeError: "Expiration time claim (exp) must be an integer") ??
validateDate(payload, key: "nbf", comparison: .orderedDescending, failure: .immatureSignature, decodeError: "Not before claim (nbf) must be an integer") ??
validateDate(payload, key: "iat", comparison: .orderedDescending, failure: .invalidIssuedAt, decodeError: "Issued at claim (iat) must be an integer")
func validateClaims(_ payload:Payload, audience:String?, issuer:String?) throws {
try validateIssuer(payload, issuer: issuer)
try validateAudience(payload, audience: audience)
try validateDate(payload, key: "exp", comparison: .orderedAscending, failure: .expiredSignature, decodeError: "Expiration time claim (exp) must be an integer")
try validateDate(payload, key: "nbf", comparison: .orderedDescending, failure: .immatureSignature, decodeError: "Not before claim (nbf) must be an integer")
try validateDate(payload, key: "iat", comparison: .orderedDescending, failure: .invalidIssuedAt, decodeError: "Issued at claim (iat) must be an integer")
}

func validateAudience(_ payload:Payload, audience:String?) -> InvalidToken? {
func validateAudience(_ payload:Payload, audience:String?) throws {
if let audience = audience {
if let aud = payload["aud"] as? [String] {
if !aud.contains(audience) {
return .invalidAudience
throw InvalidToken.invalidAudience
}
} else if let aud = payload["aud"] as? String {
if aud != audience {
return .invalidAudience
throw InvalidToken.invalidAudience
}
} else {
return .decodeError("Invalid audience claim, must be a string or an array of strings")
throw InvalidToken.decodeError("Invalid audience claim, must be a string or an array of strings")
}
}

return nil
}

func validateIssuer(_ payload:Payload, issuer:String?) -> InvalidToken? {
func validateIssuer(_ payload:Payload, issuer:String?) throws {
if let issuer = issuer {
if let iss = payload["iss"] as? String {
if iss != issuer {
return .invalidIssuer
throw InvalidToken.invalidIssuer
}
} else {
return .invalidIssuer
throw InvalidToken.invalidIssuer
}
}

return nil
}

func validateDate(_ payload:Payload, key:String, comparison:ComparisonResult, failure:InvalidToken, decodeError:String) -> InvalidToken? {
func validateDate(_ payload:Payload, key:String, comparison:ComparisonResult, failure:InvalidToken, decodeError:String) throws {
if let timestamp = payload[key] as? TimeInterval ?? (payload[key] as? NSString)?.doubleValue as TimeInterval? {
let date = Date(timeIntervalSince1970: timestamp)
if date.compare(Date()) == comparison {
return failure
throw failure
}
} else if payload[key] != nil {
return .decodeError(decodeError)
throw InvalidToken.decodeError(decodeError)
}

return nil
}
13 changes: 6 additions & 7 deletions Sources/Decode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,8 @@ public func decode(_ jwt:String, algorithms:[Algorithm], verify:Bool = true, aud
switch load(jwt) {
case let .success(header, payload, signature, signatureInput):
if verify {
if let failure = validateClaims(payload, audience: audience, issuer: issuer) ?? verifySignature(algorithms, header: header, signingInput: signatureInput, signature: signature) {
throw failure
}
try validateClaims(payload, audience: audience, issuer: issuer)
try verifySignature(algorithms, header: header, signingInput: signatureInput, signature: signature)
}

return payload
Expand Down Expand Up @@ -115,17 +114,17 @@ func load(_ jwt:String) -> LoadResult {

// MARK: Signature Verification

func verifySignature(_ algorithms:[Algorithm], header:Payload, signingInput:String, signature:Data) -> InvalidToken? {
func verifySignature(_ algorithms:[Algorithm], header:Payload, signingInput:String, signature:Data) throws {
if let alg = header["alg"] as? String {
let matchingAlgorithms = algorithms.filter { algorithm in algorithm.description == alg }
let results = matchingAlgorithms.map { algorithm in algorithm.verify(signingInput, signature: signature) }
let successes = results.filter { $0 }
if successes.count > 0 {
return nil
return
}

return .invalidAlgorithm
throw InvalidToken.invalidAlgorithm
}

return .decodeError("Missing Algorithm")
throw InvalidToken.decodeError("Missing Algorithm")
}

0 comments on commit a6574d5

Please sign in to comment.