Skip to content

Commit

Permalink
Merge pull request #2 from skelpo/develop
Browse files Browse the repository at this point in the history
Request Helpers
  • Loading branch information
calebkleveter authored Apr 20, 2018
2 parents dd47e20 + c0a5c36 commit 69c1e7e
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 1 deletion.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,10 @@ The JWTAuthenticatable module exports the following types:

- `associatedtype Payload: IdentifiableJWTPayload`: A type that the payload of a JWT token can be converted to. This type is used to authorize requests.
- `usernameKey: KeyPath<Self, String>`: The key-path for the property that will be checked against the `body.username` value during authentication. This will usually be either an email or username. This property can be either a variable or constant.
- `var password: String` The hashed password of the model, used to verify the request'c credibility. This properties value _must_ be hash using BCrypt.
- `var password: String` The hashed password of the model, used to verify the request'c credibility. This properties value _must_ be hash using BCrypt.

This module also adds some helper methods to the `Request` type:

- `accessToken()throws -> String`: Gets the value of the `Authorization: Bearer ...` header.
- `payload<Payload: Decodable>(as payloadType: Payload.Type = Payload.self)throws -> Payload`: Gets the payload of a JWT token the was previously stored in the request by a middleware.
- `payloadData<Payload, Object>(storedAs stored: Payload.Type, convertedTo objectType: Object.Type = Object.self)throws -> Object`: Gets the payload of a JWT token stored in the request and converts it to a different type.
60 changes: 60 additions & 0 deletions Sources/JWTMiddleware/Request+JWT.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import VaporRequestStorage
import Vapor

extension Request {

/// Gets the value of the `Authorization: Bearer ...` header.
///
/// - Returns: The `Authorization` header value, removing
/// the 'Bearer ' sub-string.
/// - Throws: 401 (Unauthorized) if no token is found.
public func accessToken()throws -> String {
guard let bearer = self.http.headers.bearerAuthorization?.token else {
throw Abort(.unauthorized)
}
return bearer
}

/// Gets the payload of a JWT token the was previously stored in
/// the request by a middleware.
///
/// - Parameter payloadType: The type that represents the payload. This parameter
/// defaults to `Payload.self`, meaning it can be set through type-casting
/// and left out of the parameter list.
///
/// - Returns: The stored payload, converted to the `Payload` type.
/// - Throws: An internal server error if the payload is not found in the
/// 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<Payload: Decodable>(as payloadType: Payload.Type = Payload.self)throws -> Payload {
guard let payload = try self.get("skelpo-payload", as: Payload .self) else {
throw Abort(.internalServerError, reason: "No JWTMiddleware has been registered for the current route.")
}
return payload
}

/// Gets the payload of a JWT token stored in the
/// request and converts it to a different type.
///
/// - Parameters:
/// - stored: The type payload is that is stored
/// In the request.
/// - objectType: The type you want the payload as.
///
/// - Returns: The stored payload, converted to the `Object` type.
/// - Throws: An internal server error if the payload is not found
/// or some other error from encoding and decoding the payload.
public func payloadData<Payload, Object>(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 {
throw Abort(.internalServerError, reason: "No JWTMiddleware has been registered for the current route.")
}

// We convert the payload type from `Payload` to `Object`
// by encoding it to JSON and back to `Object`.
// If you have a better idea that works, open an
// issue or PR on GitHub.
let data: Data = try JSONEncoder().encode(payload)
return try JSONDecoder().decode(Object.self, from: data)
}
}

0 comments on commit 69c1e7e

Please sign in to comment.