An example on how to authorize JWT in a micro-service.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Public
Sources
Tests
.gitignore
Package.swift
README.md
circle.yml
cloud.yml

README.md

JWTAuthExample

In this project you can see an example implementation of JWTMiddleware. The approach can be used in micro-services or webpages that need to verify incoming JWTs and use the data somehow.

Install

You will need to add the following two packages to your Package.swift:

.package(url: "https://github.com/vapor/jwt.git", from: "3.1.0"),
.package(url: "https://github.com/skelpo/JWTMiddleware.git", from: "0.8.1"),

And add JWTMiddleware as well as JWT to all the target dependency arrays you want to access the package in.

Complete the installation by running vapor update or swift package update.

Configuration

You will need to register two services in your configure.swift:

/// We need this for the JWTProvider, coming from Vapor
try services.register(StorageProvider())
/// Adding the JWTProvider for us to validate JWTs
try services.register(JWTProvider { n, d in
guard let d = d else { throw Abort(.internalServerError, reason: "Could not find environment variable 'JWT_SECRET'", identifier: "missingEnvVar") }

let headers = JWTHeader(alg: "RS256", crit: ["exp", "aud"], kid: "")
return try RSAService(n: n, e: "AQAB", d: d, header: headers)
})

Models

To work with the payload from the JWT you will need a payload model:

import Foundation
import JWT
import JWTMiddleware

/// A representation of the payload used in the access tokens
/// for this service's authentication.
struct Payload: IdentifiableJWTPayload {
    let exp: TimeInterval
    let iat: TimeInterval
    
    // These two are to be customized according to what is in the JWT
    let email: String
    let id: Int
    
    
    func verify(using signer: JWTSigner) throws {
        let expiration = Date(timeIntervalSince1970: self.exp)
        try ExpirationClaim(value: expiration).verifyNotExpired()
    }
}

Routes

Routes can look any way you like but here are two examples:

// This simple validates the request, no payload data is used
let protected = router.grouped(JWTVerificationMiddleware()).grouped("protected")
protected.get("test") { req in
    return "You need to have a valid JWT for this!"
}

// Here we are using the data
let user = router.grouped(JWTStorageMiddleware<Payload>()).grouped("user")
user.get("me") { req -> String in
    let payload:Payload = try req.get("skelpo-payload")!
    // You can now use the payload and do with it whatever you like.
    // For example you can use the user id to load related data or save data.
    return "This is the ID from the JWT: \(payload.id)"
}