Perfect Local Authentication

This package provides Local Authentication libraries for projects that require locally stored and handled authentication.

Relevant Templates & Examples

A template application can be found at, providing a fully functional starting point, as well as demonstrating the usage of the system.

Adding to your project

Add this project as a dependency in your Package.swift file.

PostgreSQL Driver:

.Package(url: "", majorVersion: 1)

MySQL Driver:

.Package(url: "", majorVersion: 1)

To then use the LocalAuthentication module in your code:

import LocalAuthentication


It is important to configure the following in main.swift to set up database and session configuration:

Import the required modules:

import PerfectSession
import PerfectSessionPostgreSQL // Or PerfectSessionMySQL
import PerfectCrypto
import LocalAuthentication

Initialize PerfectCrypto:

let _ = PerfectCrypto.isInitialized

Now set some defaults:

// Used in email communications
// The Base link to your system, such as
var baseURL = ""

// Configuration of Session = "perfectSession" // <-- change
SessionConfig.idle = 86400
SessionConfig.cookieDomain = "localhost" //<-- change
SessionConfig.IPAddressLock = false
SessionConfig.userAgentLock = false
SessionConfig.CSRF.checkState = true
SessionConfig.CORS.enabled = true
SessionConfig.cookieSameSite = .lax

Detailed Session configuration documentation can be dound at

The database and email configurations should be set as follows (if using JSON file config):

let opts = initializeSchema("./config/ApplicationConfiguration.json") // <-- loads base config like db and email configuration
httpPort = opts["httpPort"] as? Int ?? httpPort
baseURL = opts["baseURL"] as? String ?? baseURL

Otherwise, these will need to be set equivalent to one of these functions:

Set the session driver


let sessionDriver = SessionPostgresDriver()


let sessionDriver = SessionMySQLDriver()

Request & Response Filters

The following two session filters need to be added to your server config:

PostgreSQL Driver:

// (where filter is a [[String: Any]] object)

MySQL Driver:

// (where filter is a [[String: Any]] object)

For example, see

Add routes for login, register etc

The following routes can be added as needed or customized to add login, logout, register:

// Login
routes.append(["method":"get", "uri":"/login", "handler":Handlers.login]) // simply a serving of the login GET
routes.append(["method":"post", "uri":"/login", "handler":LocalAuthWebHandlers.login])
routes.append(["method":"get", "uri":"/logout", "handler":LocalAuthWebHandlers.logout])

// Register
routes.append(["method":"get", "uri":"/register", "handler":LocalAuthWebHandlers.register])
routes.append(["method":"post", "uri":"/register", "handler":LocalAuthWebHandlers.registerPost])
routes.append(["method":"get", "uri":"/verifyAccount/{passvalidation}", "handler":LocalAuthWebHandlers.registerVerify])
routes.append(["method":"post", "uri":"/registrationCompletion", "handler":LocalAuthWebHandlers.registerCompletion])

routes.append(["method":"get", "uri":"/api/v1/session", "handler":LocalAuthJSONHandlers.session])
routes.append(["method":"get", "uri":"/api/v1/logout", "handler":LocalAuthJSONHandlers.logout])
routes.append(["method":"post", "uri":"/api/v1/register", "handler":LocalAuthJSONHandlers.register])
routes.append(["method":"login", "uri":"/api/v1/login", "handler":LocalAuthJSONHandlers.login])

An example can be found at

Testing for authentication:

The user id can be accessed as follows:

request.session?.userid ?? ""

If a user id (i.e. logged in state) is required to access a page, code such as this could be used to detect and redirect:

let contextAuthenticated = !(request.session?.userid ?? "").isEmpty
if !contextAuthenticated { response.redirect(path: "/login") }