Skip to content

Commit

Permalink
use ApplicationContext as session storage
Browse files Browse the repository at this point in the history
  • Loading branch information
noppoMan committed Jun 1, 2017
1 parent b16e824 commit 6409e25
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 6 deletions.
43 changes: 38 additions & 5 deletions Sources/HexavilleAuth/HexaviileAuth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,34 @@ public enum CredentialProviderType {
case oauth1(OAuth1AuthorizationProvidable)
}

extension ApplicationContext {
public func isAuthenticated() -> Bool {
return loginUser != nil
}

public var loginUser: LoginUser? {
get {
return memory[AuthenticationMiddleware.sessionKey] as? LoginUser
}
set {
return memory[AuthenticationMiddleware.sessionKey] = newValue
}
}
}

public struct AuthenticationMiddleware: Middleware {

static var sessionKey = "hexaville.auth.loginUser"

public func respond(to request: Request, context: ApplicationContext) throws -> Chainer {
if let dict = context.session?[AuthenticationMiddleware.sessionKey] as? [String: Any] {
context.loginUser = try LoginUser(fromDictionary: dict)
}

return .next(request)
}
}

public struct HexavilleAuth {
var providers: [CredentialProviderType] = []

Expand All @@ -25,27 +53,30 @@ public struct HexavilleAuth {
self.providers.append(.oauth2(provider))
}

public func authenticationMiddleware() -> Middleware {
return AuthenticationMiddleware()
}

public func asRouter() -> Router {
let router = Router()
for type in providers {
switch type {
case .oauth1(let provider):
router.use(.get, provider.path) { request, context in
var request = request
let requestToken = try provider.getRequestToken()
request.session?["hexaville.oauth_token_secret"] = requestToken.oauthTokenSecret
request.session?["hexaville.oauth_token"] = requestToken.oauthToken
context.session?["hexaville.oauth_token_secret"] = requestToken.oauthTokenSecret
context.session?["hexaville.oauth_token"] = requestToken.oauthToken
let location = try provider.createAuthorizeURL(requestToken: requestToken).absoluteString

return Response(status: .found, headers: ["Location": location])
}

router.use(.get, provider.oauth.callbackURL.path) { request, context in
guard let secret = request.session?["hexaville.oauth_token_secret"] as? String else {
guard let secret = context.session?["hexaville.oauth_token_secret"] as? String else {
throw OAuth1Error.accessTokenIsMissingInSession
}

guard let token = request.session?["hexaville.oauth_token"] as? String else {
guard let token = context.session?["hexaville.oauth_token"] as? String else {
throw OAuth1Error.accessTokenIsMissingInSession
}

Expand All @@ -56,6 +87,7 @@ public struct HexavilleAuth {
)

let (cred, user) = try provider.authorize(request: request, requestToken: requestToken)
context.session?[AuthenticationMiddleware.sessionKey] = user.serialize()
return try provider.callback(cred, user, request, context)
}

Expand All @@ -72,6 +104,7 @@ public struct HexavilleAuth {

router.use(.get, provider.oauth.callbackURL.path) { request, context in
let (cred, user) = try provider.authorize(request: request)
context.session?[AuthenticationMiddleware.sessionKey] = user.serialize()
return try provider.callback(cred, user, request, context)
}
}
Expand Down
43 changes: 43 additions & 0 deletions Sources/HexavilleAuth/LoginUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

import Foundation

public enum LoginUserError: Error {
case missingRequiredParam(String)
}

public struct LoginUser {
public let id: String
public let name: String
Expand All @@ -24,4 +28,43 @@ public struct LoginUser {
self.picture = picture
self.raw = raw
}

public init(fromDictionary dictionary: [String: Any]) throws {
guard let id = dictionary["id"] as? String else {
throw LoginUserError.missingRequiredParam("id")
}

guard let name = dictionary["name"] as? String else {
throw LoginUserError.missingRequiredParam("name")
}

self.id = id
self.name = name
self.screenName = dictionary["screenName"] as? String
self.email = dictionary["email"] as? String
self.picture = dictionary["picture"] as? String
self.raw = dictionary["raw"] as? [String: Any] ?? [:]
}

public func serialize() -> [String: Any] {
var serialized: [String: Any] = [
"id": id,
"name": name,
"raw": raw
]

if let screenName = screenName {
serialized["screenName"] = screenName
}

if let picture = picture {
serialized["picture"] = picture
}

if let email = email {
serialized["email"] = email
}

return serialized
}
}
5 changes: 4 additions & 1 deletion Sources/HexavilleAuthExample/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,14 @@ auth.add(googleProvider)
auth.add(instagramProvider)
auth.add(twitterProvider)

app.use(auth.authenticationMiddleware())

app.use(auth.asRouter())


let router = Router()

router.use(.get, "/") { _ in
router.use(.get, "/") { req, context in
return Response(body: "Welcome to Hexaville Auth")
}

Expand Down

0 comments on commit 6409e25

Please sign in to comment.