Skip to content

Commit f208afc

Browse files
authored
Update for JWTKit v5 (#157)
* Update for JWTKit v5 * Add lint job * Update v5 * Update to swift 6 * Update to swift 6 again * Update to swift-testing * Make `withApp` return `Void` * Fix warnings * Format * Try use reusable workflow for linting * Use main branch test workflow
1 parent f240c5f commit f208afc

18 files changed

+349
-390
lines changed

.github/workflows/test.yml

+3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ on:
44
push:
55
branches:
66
- main
7+
78
jobs:
89
unit-tests:
910
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
1011
with:
1112
with_coverage: false
1213
with_tsan: true
14+
warnings_as_errors: true
15+
with_linting: true

Package.swift

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.10
1+
// swift-tools-version:6.0
22
import PackageDescription
33

44
let package = Package(
@@ -10,10 +10,10 @@ let package = Package(
1010
.watchOS(.v9),
1111
],
1212
products: [
13-
.library(name: "JWT", targets: ["JWT"]),
13+
.library(name: "JWT", targets: ["JWT"])
1414
],
1515
dependencies: [
16-
.package(url: "https://github.com/vapor/jwt-kit.git", from: "5.0.0-rc.1"),
16+
.package(url: "https://github.com/vapor/jwt-kit.git", from: "5.0.0"),
1717
.package(url: "https://github.com/vapor/vapor.git", from: "4.101.0"),
1818
],
1919
targets: [
@@ -22,16 +22,14 @@ let package = Package(
2222
dependencies: [
2323
.product(name: "JWTKit", package: "jwt-kit"),
2424
.product(name: "Vapor", package: "vapor"),
25-
],
26-
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
25+
]
2726
),
2827
.testTarget(
2928
name: "JWTTests",
3029
dependencies: [
3130
.target(name: "JWT"),
3231
.product(name: "XCTVapor", package: "vapor"),
33-
],
34-
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
32+
]
3533
),
3634
]
3735
)

README.md

+13-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,18 @@
2525
<br>
2626

2727
Support for JWT (JSON Web Tokens) in Vapor.
28+
This package integrates [JWTKit](https://github.com/vapor/jwt-kit.git) with Vapor.
2829

29-
**Original author**
30+
### Installation
3031

31-
- Siemen Sikkema, [@siemensikkema](http://github.com/siemensikkema)
32+
Use the SPM string to easily include the package in your `Package.swift` file.
33+
34+
```swift
35+
.package(url: "https://github.com/vapor/jwt.git", from: "5.0.0")
36+
```
37+
38+
and add it to your target's dependencies:
39+
40+
```swift
41+
.product(name: "JWT", package: "jwt")
42+
```

Sources/JWT/Application+JWT.swift

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import JWTKit
2-
import Vapor
32
import NIOConcurrencyHelpers
3+
import Vapor
44

5-
public extension Application {
6-
var jwt: JWT {
5+
extension Application {
6+
public var jwt: JWT {
77
.init(_application: self)
88
}
99

10-
struct JWT: Sendable {
10+
public struct JWT: Sendable {
1111
private final class Storage: Sendable {
1212
private struct SendableBox: Sendable {
1313
var keys: JWTKeyCollection
1414
}
15-
15+
1616
private let sendableBox: NIOLockedValueBox<SendableBox>
17-
17+
1818
var keys: JWTKeyCollection {
1919
get {
2020
self.sendableBox.withLockedValue { box in
@@ -27,7 +27,7 @@ public extension Application {
2727
}
2828
}
2929
}
30-
30+
3131
init() {
3232
let box = SendableBox(keys: .init())
3333
self.sendableBox = .init(box)

Sources/JWT/JWT+Apple.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import NIOConcurrencyHelpers
22
import Vapor
33

4-
public extension Request.JWT {
5-
var apple: Apple {
4+
extension Request.JWT {
5+
public var apple: Apple {
66
.init(_jwt: self)
77
}
88

9-
struct Apple: Sendable {
9+
public struct Apple: Sendable {
1010
public let _jwt: Request.JWT
1111

1212
public func verify(
@@ -40,12 +40,12 @@ public extension Request.JWT {
4040
}
4141
}
4242

43-
public extension Application.JWT {
44-
var apple: Apple {
43+
extension Application.JWT {
44+
public var apple: Apple {
4545
.init(_jwt: self)
4646
}
4747

48-
struct Apple: Sendable {
48+
public struct Apple: Sendable {
4949
public let _jwt: Application.JWT
5050

5151
public func keys(on request: Request) async throws -> JWTKeyCollection {

Sources/JWT/JWT+Google.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import NIOConcurrencyHelpers
22
import Vapor
33

4-
public extension Request.JWT {
5-
var google: Google {
4+
extension Request.JWT {
5+
public var google: Google {
66
.init(_jwt: self)
77
}
88

9-
struct Google: Sendable {
9+
public struct Google: Sendable {
1010
public let _jwt: Request.JWT
1111

1212
public func verify(
@@ -51,12 +51,12 @@ public extension Request.JWT {
5151
}
5252
}
5353

54-
public extension Application.JWT {
55-
var google: Google {
54+
extension Application.JWT {
55+
public var google: Google {
5656
.init(_jwt: self)
5757
}
5858

59-
struct Google: Sendable {
59+
public struct Google: Sendable {
6060
public let _jwt: Application.JWT
6161

6262
public func keys(on request: Request) async throws -> JWTKeyCollection {

Sources/JWT/JWT+Microsoft.swift

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import NIOConcurrencyHelpers
22
import Vapor
33

4-
public extension Request.JWT {
5-
var microsoft: Microsoft {
4+
extension Request.JWT {
5+
public var microsoft: Microsoft {
66
.init(_jwt: self)
77
}
88

9-
struct Microsoft {
9+
public struct Microsoft {
1010
public let _jwt: Request.JWT
1111

1212
public func verify(
@@ -40,12 +40,12 @@ public extension Request.JWT {
4040
}
4141
}
4242

43-
public extension Application.JWT {
44-
var microsoft: Microsoft {
43+
extension Application.JWT {
44+
public var microsoft: Microsoft {
4545
.init(_jwt: self)
4646
}
4747

48-
struct Microsoft {
48+
public struct Microsoft {
4949
public let _jwt: Application.JWT
5050

5151
public func keys(on request: Request) async throws -> JWTKeyCollection {
@@ -55,7 +55,7 @@ public extension Application.JWT {
5555
public var jwks: EndpointCache<JWKS> {
5656
self.storage.jwks
5757
}
58-
58+
5959
public var jwksEndpoint: URI {
6060
get {
6161
self.storage.jwksEndpoint
@@ -87,7 +87,7 @@ public extension Application.JWT {
8787
}
8888

8989
private let sendableBox: NIOLockedValueBox<SendableBox>
90-
90+
9191
var jwks: EndpointCache<JWKS> {
9292
get {
9393
self.sendableBox.withLockedValue { box in
@@ -113,7 +113,7 @@ public extension Application.JWT {
113113
}
114114
}
115115
}
116-
116+
117117
var jwksEndpoint: URI {
118118
get {
119119
self.sendableBox.withLockedValue { box in

Sources/JWT/JWTAuthenticator.swift

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import Vapor
22

3-
public extension JWTPayload where Self: Authenticatable {
4-
static func authenticator() -> AsyncAuthenticator {
3+
extension JWTPayload where Self: Authenticatable {
4+
public static func authenticator() -> AsyncAuthenticator {
55
JWTPayloadAuthenticator<Self>()
66
}
77
}
88

99
private struct JWTPayloadAuthenticator<Payload>: JWTAuthenticator
10-
where Payload: JWTPayload & Authenticatable
11-
{
10+
where Payload: JWTPayload & Authenticatable {
1211
func authenticate(jwt: Payload, for request: Request) async throws {
1312
request.auth.login(jwt)
1413
}
@@ -19,8 +18,8 @@ public protocol JWTAuthenticator: AsyncBearerAuthenticator {
1918
func authenticate(jwt: Payload, for request: Request) async throws
2019
}
2120

22-
public extension JWTAuthenticator {
23-
func authenticate(bearer: BearerAuthorization, for request: Request) async throws {
21+
extension JWTAuthenticator {
22+
public func authenticate(bearer: BearerAuthorization, for request: Request) async throws {
2423
try await self.authenticate(jwt: request.jwt.verify(bearer.token), for: request)
2524
}
2625
}

Sources/JWT/JWTError+Vapor.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Vapor
22

3-
extension JWTError: AbortError {
3+
extension JWTError: @retroactive AbortError {
44
public var status: HTTPResponseStatus {
55
.unauthorized
66
}

Sources/JWT/Request+JWT.swift

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
import JWTKit
22
import Vapor
33

4-
public extension Request {
5-
var jwt: JWT {
4+
extension Request {
5+
public var jwt: JWT {
66
.init(_request: self)
77
}
88

9-
struct JWT: Sendable {
9+
public struct JWT: Sendable {
1010
public let _request: Request
1111

1212
@discardableResult
1313
public func verify<Payload>(as _: Payload.Type = Payload.self) async throws -> Payload
14-
where Payload: JWTPayload
15-
{
14+
where Payload: JWTPayload {
1615
guard let token = self._request.headers.bearerAuthorization?.token else {
1716
self._request.logger.error("Request is missing JWT bearer header")
1817
throw Abort(.unauthorized)
@@ -22,21 +21,18 @@ public extension Request {
2221

2322
@discardableResult
2423
public func verify<Payload>(_ message: String, as _: Payload.Type = Payload.self) async throws -> Payload
25-
where Payload: JWTPayload
26-
{
24+
where Payload: JWTPayload {
2725
try await self.verify([UInt8](message.utf8), as: Payload.self)
2826
}
2927

3028
@discardableResult
3129
public func verify<Payload>(_ message: some DataProtocol & Sendable, as _: Payload.Type = Payload.self) async throws -> Payload
32-
where Payload: JWTPayload
33-
{
30+
where Payload: JWTPayload {
3431
try await self._request.application.jwt.keys.verify(message, as: Payload.self)
3532
}
3633

3734
public func sign<Payload>(_ jwt: Payload, kid: JWKIdentifier? = nil, header: JWTHeader = .init()) async throws -> String
38-
where Payload: JWTPayload
39-
{
35+
where Payload: JWTPayload {
4036
return try await self._request.application.jwt.keys.sign(jwt, kid: kid, header: header)
4137
}
4238
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Vapor
2+
3+
extension ByteBuffer {
4+
var string: String {
5+
.init(decoding: self.readableBytesView, as: UTF8.self)
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Vapor
2+
3+
let isLoggingConfigured: Bool = {
4+
LoggingSystem.bootstrap { label in
5+
var handler = StreamLogHandler.standardOutput(label: label)
6+
handler.logLevel = .debug
7+
return handler
8+
}
9+
return true
10+
}()

Tests/JWTTests/Helpers/withApp.swift

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Testing
2+
import Vapor
3+
4+
func withApp(_ body: (Application) async throws -> Void) async throws {
5+
let app = try await Application.make(.testing)
6+
try #require(isLoggingConfigured == true)
7+
try await body(app)
8+
try await app.asyncShutdown()
9+
}

0 commit comments

Comments
 (0)