HexavilleAuth is an Authentication(OAuth, simple password based) framework for Hexaville.
HexavilleAuth recognizes that each application has unique authentication requirements. It allows individual authentication mechanisms to be packaged as plugins which it consumes.
Plugins can range from a simple password based authentication or, authentication using OAuth (via Facebook, Github OAuth provider, etc.).
HexavilleAuth automatically creates resources for authorize/callback for each sns platforms, So you can embed sns authentication features into your Hexaville application very quickly.
- Email+password
- OAuth1
- OAuth2
- Github
Just add .Package(url: "https://github.com/Hexaville/HexavilleAuth.git", majorVersion: 0, minor: 1)
into your Package.swift
import PackageDescription
let package = Package(
name: "MyHexavilleApplication",
dependencies: [
.Package(url: "https://github.com/Hexaville/HexavilleAuth.git", majorVersion: 0, minor: 1)
]
)
Here is an example code for facebook oauth authorization with HexavilleFramework
import Foundation
import HexavilleAuth
import HexavilleFramework
let app = HexavilleFramework()
var auth = HexavilleAuth()
let APP_URL = ProcessInfo.processInfo.environment["APP_URL"] ?? "http://localhost:3000"
let facebookProvider = FacebookAuthorizationProvider(
path: "/auth/facebook",
consumerKey: ProcessInfo.processInfo.environment["FACEBOOK_APP_ID"] ?? "",
consumerSecret: ProcessInfo.processInfo.environment["FACEBOOK_APP_SECRET"] ?? "",
callbackURL: CallbackURL(baseURL: APP_URL, path: "/auth/facebook/callback"),
scope: "public_profile"
) { credential, user, request, context in
// here is called when the access_token got successfully from sns.
return Response(body: "\(user)")
}
auth.add(facebookProvider)
app.use(auth)
app.catch { error in
switch error {
case HexavilleAuthError.responseError(let response):
return Response(body: response.body.asData())
default:
return Response(body: "\(error)")
}
}
try app.run()
If you register HexavilleAuth.AuthenticationMiddleware
and loginUser information is stored in the session, You can get it from ApplicationContext
as LoginUser
Object.
public struct LoginUser {
public let id: String
public let name: String
public let screenName: String?
public let email: String?
public let picture: String?
public let raw: [String: Any]
}
import Foundation
import HexavilleAuth
import HexavilleFramework
let app = HexavilleFramework()
var auth = HexavilleAuth()
let APP_URL = ProcessInfo.processInfo.environment["APP_URL"] ?? "http://localhost:3000"
let twitterProvider = TwitterAuthorizationProvider(
path: "/auth/twitter",
consumerKey: ProcessInfo.processInfo.environment["TWITTER_APP_ID"] ?? "",
consumerSecret: ProcessInfo.processInfo.environment["TWITTER_APP_SECRET"] ?? "",
callbackURL: CallbackURL(baseURL: APP_URL, path: "/auth/twitter/callback"),
scope: ""
) { credential, user, request, context in
return Response(body: "\(user)")
}
app.use(HexavilleAuth.AuthenticationMiddleware()) // register to get loginUser Object
app.use { req, context in
print(context.isAuthenticated()) // => true
print(context.loginUser) // Get the loginUser object
return .next(req)
}
auth.add(twitterProvider)
app.use(auth)
try app.run()
Here is an official full example code.
git clone https://github.com/Hexaville/HexavilleAuth.git
cd HexavilleAuth
cd swift build
./.build/debug/HexavilleAuthExample
# => Hexaville Builtin Server started at 0.0.0.0:3000
Try to access following resources to authentication/authorization with Browser!
- Facebook: http://yourlocaldomain:3000/auth/facebook
- Github: http://yourlocaldomain:3000/auth/github
- Instagram: http://yourlocaldomain:3000/auth/instagram
- Google: http://yourlocaldomain:3000/auth/google
You can create Custom Authorization/Authentication Provider with OAuthXAuthorizationProvidable
/ AuthenticationProvidable
public protocol OAuth2AuthorizationProvidable {
var path: String { get } // path for authorize
var oauth: OAuth2 { get }
var callback: RespodWithCredential { get } // callback for success handler
init(path: String, consumerKey: String, consumerSecret: String, callbackURL: CallbackURL, scope: String, callback: @escaping RespodWithCredential)
func getAccessToken(request: Request) throws -> Credential
}
here is an example for Salesforce Authorization.
public struct SalesforceAuthorizationProvider: OAuth2AuthorizationProvidable {
public let path: String
public let oauth: OAuth2
public let callback: RespodWithCredential
public init(path: String, consumerKey: String, consumerSecret: String, callbackURL: CallbackURL, scope: String, callback: @escaping RespodWithCredential) {
self.path = path
self.oauth = OAuth2(
consumerKey: consumerKey,
consumerSecret: consumerSecret,
authorizeURL: "https://login.salesforce.com/services/oauth2/authorize",
accessTokenURL: "https://login.salesforce.com/services/oauth2/token",
callbackURL: callbackURL,
scope: scope
)
self.callback = callback
}
}
Use it!
var auth = HexavilleAuth()
let salesforceProvider = SalesforceAuthorizationProvider(
path: "/auth/salesforce",
consumerKey: "consumer",
consumerSecret: "secret",
callbackURL: CallbackURL(baseURL: APP_URL, path: "/auth/salesforce/callback"),
scope: "public_profile"
) { credential, user, request, context in
try DB.save(token: credential.accessToken)
return Response(body: "\(user)")
}
auth.add(salesforceProvider)
HexavilleAuth is released under the MIT license. See LICENSE for details.