VaporScope

VaporScope is a library to use Scope in Vapor.

Installation

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/Myoland/VaporScope.git", from: "0.1.0"),
]

Usage

Requirement

This library is built on the ScopeCarrier protocol which conforms to JWTPayload.

So, it is important that your project is using JWT for authentication.

Define a payload

To start, create a payload and let it conform to the ScopeCarrier.

For Example:

public struct User: ScopeCarrier {
    enum CodingKeys: String, CodingKey {...}
    
    public var subject: SubjectClaim
    public var expiration: ExpirationClaim
    public var scopes: [String]
    
    public func verify(using signer: JWTSigner) throws {...}
    
    public init(...) {...}
}

For more detail, go to ScopeCarrier+Testable.swift.

Tips

Encode and Decode

Based on JWTPayload, it’s for sure that you can encode or decode your payload for further transmission.

You should know how we get payload and decode it.

// Encode
let user = User(...)
let encode = try app.jwt.signers.sign(u)

// Decode
let payload = try request.jwt.verify(as:User.self)

Login

let user = User(...)
try await User.authenticator().authenticate(jwt: user, for: request)

// OR

let user = User(...)
try await user.authenticate(request: request)

Authenticator

We usually create a Middleware helping login a user.

It is how:

route.group(User.authenticator()) {
    $0.get(use: handler)
}

Scope

In this part we will show how to use VaporScope for Scope-based authentication.

In ScopeHandler.swift, we define the basic logic for assearting scopes. See ScopeHandler.assertScopes(_:carried:) for more detail.

As you can see, when we try to assert the scopes, we define that every required scope should be contained by carried scopes. Contained means a required scope should be satisfied by one of the carried scopes.

ScopeHandler

Every request has an independent authentication, so we need a method to check every request.

Use ScopeHandler to help you check every request.

try ScopeHandler(request: request).satisfied(with: ["all.part:read"], as: User.self)

// OR

try request.oauth.satisfied(with: self.scopes, as: User.self)

GuardMiddleware

We also provide a better way to use ScopeHandler.

route.routes.grouped([
    User.guardMiddleware(with: ["one", "two"])
]).get("action", use: handler)

GitHub

View Github