From fb3bcb8a240e1a73dd46dfa33f06c2261a6057a6 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Thu, 15 Nov 2018 11:05:52 -0600 Subject: [PATCH 1/4] Replaced .badRequest error when Authorization header is not found with .unauthorized --- Sources/JWTMiddleware/JWTVerificationMiddleware.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/JWTMiddleware/JWTVerificationMiddleware.swift b/Sources/JWTMiddleware/JWTVerificationMiddleware.swift index 902d079..b4c5a46 100644 --- a/Sources/JWTMiddleware/JWTVerificationMiddleware.swift +++ b/Sources/JWTMiddleware/JWTVerificationMiddleware.swift @@ -24,7 +24,7 @@ public final class JWTStorageMiddleware: Middleware { // Extract the token from the request. It is expected to // be in the `Authorization` header as a bearer: `Bearer ...` guard let token = request.http.headers.bearerAuthorization?.token else { - throw Abort(.badRequest, reason: "'Authorization' header with bearer token is missing") + throw Abort(.unauthorized, reason: "'Authorization' header with bearer token is missing") } // Get JWT service to verify the token with @@ -56,7 +56,7 @@ public final class JWTVerificationMiddleware: Middleware { // Extract the token from the request. It is expected to // be in the `Authorization` header as a bearer: `Bearer ...` guard let token = request.http.headers.bearerAuthorization?.token else { - throw Abort(.badRequest, reason: "'Authorization' header with bearer token is missing") + throw Abort(.unauthorized, reason: "'Authorization' header with bearer token is missing") } // Get JWT service to verify the token with From ff3a46875f8447430d5a8519d64090d66350ef7f Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Thu, 15 Nov 2018 11:06:22 -0600 Subject: [PATCH 2/4] Renamed RouteRestrictionMiddleware.swift file to PermissionsMiddleware.swift --- ...uteRestrictionMiddleware.swift => PermissionsMiddleware.swift} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Sources/JWTMiddleware/{RouteRestrictionMiddleware.swift => PermissionsMiddleware.swift} (100%) diff --git a/Sources/JWTMiddleware/RouteRestrictionMiddleware.swift b/Sources/JWTMiddleware/PermissionsMiddleware.swift similarity index 100% rename from Sources/JWTMiddleware/RouteRestrictionMiddleware.swift rename to Sources/JWTMiddleware/PermissionsMiddleware.swift From 774fd0691706145fe2f1bf6d7d8021e71d627bd3 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 7 Dec 2018 08:31:29 -0600 Subject: [PATCH 3/4] Removed Status type requirment from PermissionsMiddleware type signiture We can get the Status type from Payload.Status --- Sources/JWTMiddleware/PermissionsMiddleware.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/JWTMiddleware/PermissionsMiddleware.swift b/Sources/JWTMiddleware/PermissionsMiddleware.swift index 5fcf194..fa7c28a 100644 --- a/Sources/JWTMiddleware/PermissionsMiddleware.swift +++ b/Sources/JWTMiddleware/PermissionsMiddleware.swift @@ -18,12 +18,12 @@ public protocol PermissionedUserPayload: IdentifiableJWTPayload { /// Verifies incoming request's authentication payload status /// against pre-defined allowed statuses. -public final class PermissionsMiddleware: Middleware where Payload: PermissionedUserPayload, Status == Payload.Status { +public final class PermissionsMiddleware: Middleware where Payload: PermissionedUserPayload { /// All the restrictions to check against the /// incoming request. Only one restriction must /// pass for the request to validated. - public let statuses: [Status] + public let statuses: [Payload.Status] /// The status code to throw if no restriction passes. public let failureError: HTTPStatus @@ -34,7 +34,7 @@ public final class PermissionsMiddleware: Middleware where Payl /// - statuses: An array of valid permission statuses. /// - failureError: The HTTP status to throw if all restrictions fail. The default /// value is `.notFound` (404). `.unauthorized` (401) would be another common option. - public init(allowed statuses: [Status], failureError: HTTPStatus = .notFound) { + public init(allowed statuses: [Payload.Status], failureError: HTTPStatus = .notFound) { self.statuses = statuses self.failureError = failureError } From 9de3e38ec7dc8b8550487d678d1011d22bd96e09 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 7 Dec 2018 08:39:52 -0600 Subject: [PATCH 4/4] Stored JWT payload key in String.payloadKey static property --- .../JWTAuthenticatable/BasicJWTAuthenticatable.swift | 10 ++++++++-- Sources/JWTMiddleware/JWTVerificationMiddleware.swift | 2 +- Sources/JWTMiddleware/Request+JWT.swift | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Sources/JWTAuthenticatable/BasicJWTAuthenticatable.swift b/Sources/JWTAuthenticatable/BasicJWTAuthenticatable.swift index 025e7e4..4eb9119 100644 --- a/Sources/JWTAuthenticatable/BasicJWTAuthenticatable.swift +++ b/Sources/JWTAuthenticatable/BasicJWTAuthenticatable.swift @@ -5,6 +5,12 @@ import Fluent import Crypto import Vapor +extension String { + + /// The key for the JWT payload when it is stored in a Vapor `Request` object. + public static let payloadKey: String = "skelpo-payload" +} + /// Used to decode a request body in /// `BasicJWTAuthenticatable.authBody(from:)`. /// @@ -95,7 +101,7 @@ extension BasicJWTAuthenticatable { // Store the model and payload in the request // using the request's `privateContainer`. try request.authenticate(model) - try request.set("skelpo-payload", to: payload) + try request.set(.payloadKey, to: payload) return model }) @@ -123,7 +129,7 @@ extension BasicJWTAuthenticatable { // Store the payload and the model in the request // for later access. - try request.set("skelpo-payload", to: authenticated.0) + try request.set(.payloadKey, to: authenticated.0) try request.authenticate(authenticated.1) return authenticated.1 diff --git a/Sources/JWTMiddleware/JWTVerificationMiddleware.swift b/Sources/JWTMiddleware/JWTVerificationMiddleware.swift index b4c5a46..f34d37c 100644 --- a/Sources/JWTMiddleware/JWTVerificationMiddleware.swift +++ b/Sources/JWTMiddleware/JWTVerificationMiddleware.swift @@ -33,7 +33,7 @@ public final class JWTStorageMiddleware: Middleware { // Verify to token and store the payload in the request's private container. let payload = try JWT(from: data, verifiedUsing: jwt.signer).payload - try request.set("skelpo-payload", to: payload) + try request.set(.payloadKey, to: payload) // Fire the next responder in the chain. return try next.respond(to: request) diff --git a/Sources/JWTMiddleware/Request+JWT.swift b/Sources/JWTMiddleware/Request+JWT.swift index bdbe510..02f55e1 100644 --- a/Sources/JWTMiddleware/Request+JWT.swift +++ b/Sources/JWTMiddleware/Request+JWT.swift @@ -27,7 +27,7 @@ extension Request { /// request storage. This is because this method should _only_ be called /// if a JWT compatible model has been authenticated through a `JWTMiddleware`. public func payload(as payloadType: Payload.Type = Payload.self)throws -> Payload { - guard let payload = try self.get("skelpo-payload", as: Payload .self) else { + guard let payload = try self.get(.payloadKey, as: Payload .self) else { throw Abort(.internalServerError, reason: "No JWTMiddleware has been registered for the current route.") } return payload @@ -46,7 +46,7 @@ extension Request { /// or some other error from encoding and decoding the payload. public func payloadData(storedAs stored: Payload.Type, convertedTo objectType: Object.Type = Object.self)throws -> Object where Payload: Encodable, Object: Decodable { - guard let payload = try self.get("skelpo-payload", as: Payload.self) else { + guard let payload = try self.get(.payloadKey, as: Payload.self) else { throw Abort(.internalServerError, reason: "No JWTMiddleware has been registered for the current route.") }