Skip to content

Commit

Permalink
Add JWTSigner.unsecuredNone (#79)
Browse files Browse the repository at this point in the history
* Allow empty signature

When encoding an Unsecured JWT with the "none" algorithm, the encoded signature is the empty string.

* Add JWTSigner.unsecuredNone

* Test that signature is empty when using `.unsecuredNone`

* Add decoding test for the "none" algorithm
  • Loading branch information
baarde authored Aug 2, 2022
1 parent aa7d9cd commit 87ce13a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Sources/JWTKit/JWTParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ struct JWTParser {
init<Token>(token: Token) throws
where Token: DataProtocol
{
let tokenParts = token.copyBytes().split(separator: .period)
let tokenParts = token.copyBytes()
.split(separator: .period, omittingEmptySubsequences: false)
guard tokenParts.count == 3 else {
throw JWTError.malformedToken
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/JWTKit/None/JWTSigner+UnsecuredNone.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
extension JWTSigner {
public static let unsecuredNone: JWTSigner = .init(algorithm: UnsecuredNoneSigner())
}
19 changes: 19 additions & 0 deletions Sources/JWTKit/None/UnsecuredNoneSigner.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Foundation

internal struct UnsecuredNoneSigner: JWTAlgorithm {
var name: String {
"none"
}

func sign<Plaintext>(_ plaintext: Plaintext) throws -> [UInt8]
where Plaintext: DataProtocol
{
[]
}

func verify<Signature, Plaintext>(_ signature: Signature, signs plaintext: Plaintext) throws -> Bool
where Signature: DataProtocol, Plaintext: DataProtocol
{
signature.isEmpty
}
}
16 changes: 16 additions & 0 deletions Tests/JWTKitTests/JWTKitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,22 @@ class JWTKitTests: XCTestCase {
let payload = try signers.verify(data, as: TestPayload.self)
XCTAssertEqual(payload.name, "John Doe")
}

func testUnsecuredNone() throws {
let data =
"eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMDAwMDAwMDAsImFkbWluIjpmYWxzZSwibmFtZSI6IkZvbyIsInN1YiI6InZhcG9yIn0."
let payload = TestPayload(
sub: "vapor",
name: "Foo",
admin: false,
exp: .init(value: .init(timeIntervalSince1970: 2_000_000_000))
)
let signer = JWTSigner.unsecuredNone
let token = try signer.sign(payload)
try XCTAssertEqual(signer.verify(token.bytes, as: TestPayload.self), payload)
try XCTAssertEqual(signer.verify(data.bytes, as: TestPayload.self), payload)
XCTAssertTrue(token.hasSuffix("."))
}

func testRSA() throws {
let privateSigner = try JWTSigner.rs256(key: .private(pem: rsaPrivateKey.bytes))
Expand Down

0 comments on commit 87ce13a

Please sign in to comment.