Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Make base64url Data extensions public #75

Merged
merged 4 commits into from
Sep 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Sources/SwiftJWT/BlueECDSA.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class BlueECSigner: SignerAlgorithm {
throw JWTError.invalidJWTString
}
let signature = try sign(unsignedData)
let signatureString = signature.base64urlEncodedString()
let signatureString = JWTEncoder.base64urlEncodedString(data: signature)
return header + "." + claims + "." + signatureString
}

Expand Down Expand Up @@ -76,7 +76,7 @@ class BlueECVerifier: VerifierAlgorithm {
func verify(jwt: String) -> Bool {
let components = jwt.components(separatedBy: ".")
if components.count == 3 {
guard let signature = Data(base64urlEncoded: components[2]),
guard let signature = JWTDecoder.data(base64urlEncoded: components[2]),
let jwtData = (components[0] + "." + components[1]).data(using: .utf8)
else {
return false
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftJWT/BlueHMAC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class BlueHMAC: SignerAlgorithm, VerifierAlgorithm {
throw JWTError.invalidJWTString
}
let signature = try sign(unsignedData)
let signatureString = signature.base64urlEncodedString()
let signatureString = JWTEncoder.base64urlEncodedString(data: signature)
return header + "." + claims + "." + signatureString
}

Expand All @@ -58,7 +58,7 @@ class BlueHMAC: SignerAlgorithm, VerifierAlgorithm {
func verify(jwt: String) -> Bool {
let components = jwt.components(separatedBy: ".")
if components.count == 3 {
guard let signature = Data(base64urlEncoded: components[2]),
guard let signature = JWTDecoder.data(base64urlEncoded: components[2]),
let jwtData = (components[0] + "." + components[1]).data(using: .utf8)
else {
return false
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftJWT/BlueRSA.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class BlueRSA: SignerAlgorithm, VerifierAlgorithm {
throw JWTError.invalidJWTString
}
let signature = try sign(unsignedData)
let signatureString = signature.base64urlEncodedString()
let signatureString = JWTEncoder.base64urlEncodedString(data: signature)
return header + "." + claims + "." + signatureString
}

Expand Down Expand Up @@ -76,7 +76,7 @@ class BlueRSA: SignerAlgorithm, VerifierAlgorithm {
func verify(jwt: String) -> Bool {
let components = jwt.components(separatedBy: ".")
if components.count == 3 {
guard let signature = Data(base64urlEncoded: components[2]),
guard let signature = JWTDecoder.data(base64urlEncoded: components[2]),
let jwtData = (components[0] + "." + components[1]).data(using: .utf8)
else {
return false
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftJWT/Claims.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ public extension Claims {
let jsonEncoder = JSONEncoder()
jsonEncoder.dateEncodingStrategy = .secondsSince1970
let data = try jsonEncoder.encode(self)
return data.base64urlEncodedString()
return JWTEncoder.base64urlEncodedString(data: data)
}
}
25 changes: 19 additions & 6 deletions Sources/SwiftJWT/Data+Base64URLEncoded.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corporation 2017
* Copyright IBM Corporation 2017-2019
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,22 +16,35 @@

import Foundation

/// Convenience extension for encoding a `Data` as a base64url-encoded `String`.
extension JWTEncoder {

extension Data {
func base64urlEncodedString() -> String {
let result = self.base64EncodedString()
/// Returns a `String` representation of this data, encoded in base64url format
/// as defined in RFC4648 (https://tools.ietf.org/html/rfc4648).
///
/// This is the appropriate format for encoding the header and claims of a JWT.
public static func base64urlEncodedString(data: Data) -> String {
let result = data.base64EncodedString()
return result.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
}
}

/// Convenience extension for decoding a `Data` from a base64url-encoded `String`.
extension JWTDecoder {

init?(base64urlEncoded: String) {
/// Initializes a new `Data` from the base64url-encoded `String` provided. The
/// base64url encoding is defined in RFC4648 (https://tools.ietf.org/html/rfc4648).
///
/// This is appropriate for reading the header or claims portion of a JWT string.
public static func data(base64urlEncoded: String) -> Data? {
let paddingLength = 4 - base64urlEncoded.count % 4
let padding = (paddingLength < 4) ? String(repeating: "=", count: paddingLength) : ""
let base64EncodedString = base64urlEncoded
.replacingOccurrences(of: "-", with: "+")
.replacingOccurrences(of: "_", with: "/")
+ padding
self.init(base64Encoded: base64EncodedString)
return Data(base64Encoded: base64EncodedString)
}
}
2 changes: 1 addition & 1 deletion Sources/SwiftJWT/Header.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,6 @@ public struct Header: Codable {
let jsonEncoder = JSONEncoder()
jsonEncoder.dateEncodingStrategy = .secondsSince1970
let data = try jsonEncoder.encode(self)
return data.base64urlEncodedString()
return JWTEncoder.base64urlEncodedString(data: data)
}
}
4 changes: 2 additions & 2 deletions Sources/SwiftJWT/JWT.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ public struct JWT<T: Claims>: Codable {
public init(jwtString: String, verifier: JWTVerifier = .none ) throws {
let components = jwtString.components(separatedBy: ".")
guard components.count == 2 || components.count == 3,
let headerData = Data(base64urlEncoded: components[0]),
let claimsData = Data(base64urlEncoded: components[1])
let headerData = JWTDecoder.data(base64urlEncoded: components[0]),
let claimsData = JWTDecoder.data(base64urlEncoded: components[1])
else {
throw JWTError.invalidJWTString
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftJWT/JWTDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public class JWTDecoder: BodyDecoder {
public func decode<T : Decodable>(_ type: T.Type, fromString: String) throws -> T {
// Seperate the JWT into the headers and claims.
let components = fromString.components(separatedBy: ".")
guard let headerData = Data(base64urlEncoded: components[0]),
let claimsData = Data(base64urlEncoded: components[1])
guard let headerData = JWTDecoder.data(base64urlEncoded: components[0]),
let claimsData = JWTDecoder.data(base64urlEncoded: components[1])
else {
throw JWTError.invalidJWTString
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftJWT/JWTEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ fileprivate class _JWTEncoder: Encoder {
}
_header.alg = encoder.jwtSigner?.name
let data = try jsonEncoder.encode(_header)
encoder.header = data.base64urlEncodedString()
encoder.header = JWTEncoder.base64urlEncodedString(data: data)
} else if fieldName == "claims" {
let data = try jsonEncoder.encode(value)
encoder.claims = data.base64urlEncodedString()
encoder.claims = JWTEncoder.base64urlEncodedString(data: data)
}
}

Expand Down
Loading