Skip to content

Commit

Permalink
Merge pull request #5 from brokenhandsio/remoteTokenSupport
Browse files Browse the repository at this point in the history
Add default implementations for the Resource Server
  • Loading branch information
0xTim authored Sep 27, 2017
2 parents 72c7c62 + a10c97d commit 294295c
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import VaporOAuth

public struct FluentResourceServerRetriever: ResourceServerRetriever {

public init() { }

public func getServer(_ username: String) -> OAuthResourceServer? {
return (try? OAuthResourceServer.makeQuery().filter(OAuthResourceServer.Properties.username, username).first()) ?? nil
}

}
49 changes: 49 additions & 0 deletions Sources/VaporOAuthFluent/Models/OAuthResourceServer+Fluent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import VaporOAuth
import FluentProvider

extension OAuthResourceServer: Model {

struct Properties {
static let username = "username"
static let password = "password"
}

public var storage: Storage {
if let storage = extend["fluent-storage"] as? Storage {
return storage
} else {
let storage = Storage()
extend["fluent-storage"] = storage
return storage
}
}

public convenience init(row: Row) throws {
let username: String = try row.get(Properties.username)
let passwordAsString: String = try row.get(Properties.password)
self.init(username: username, password: passwordAsString.makeBytes())
}

public func makeRow() throws -> Row {
var row = Row()
try row.set(Properties.username, username)
try row.set(Properties.password, password.makeString())
return row
}
}

extension OAuthResourceServer: Preparation {
public static func prepare(_ database: Database) throws {
try database.create(self) { builder in
builder.id()
builder.string(Properties.username)
builder.string(Properties.password)
}

try database.index(Properties.username, for: OAuthResourceServer.self)
}

public static func revert(_ database: Database) throws {
try database.delete(self)
}
}
51 changes: 49 additions & 2 deletions Tests/VaporOAuthFluentTests/VaporOAuthFluentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class VaporOAuthFluentTests: XCTestCase {
("testLinuxTestSuiteIncludesAllTests", testLinuxTestSuiteIncludesAllTests),
("testThatAuthCodeFlowWorksAsExpectedWithFluentModels", testThatAuthCodeFlowWorksAsExpectedWithFluentModels),
("testThatPasswordCredentialsWorksAsExpectedWithFluentModel", testThatPasswordCredentialsWorksAsExpectedWithFluentModel),
("testThatRemoteTokenIntrospectWorksAsExpectedWithFluentModel", testThatRemoteTokenIntrospectWorksAsExpectedWithFluentModel),
]


Expand All @@ -31,11 +32,12 @@ class VaporOAuthFluentTests: XCTestCase {
var user: OAuthUser!
var oauthClient: OAuthClient!
var passwordClient: OAuthClient!
var resourceServer: OAuthResourceServer!

// MARK: - Overrides

override func setUp() {
let provider = VaporOAuth.Provider(codeManager: FluentCodeManager(), tokenManager: FluentTokenManager(), clientRetriever: FluentClientRetriever(), authorizeHandler: capturingAuthHandler, userManager: FluentUserManager(), validScopes: [scope])
let provider = VaporOAuth.Provider(codeManager: FluentCodeManager(), tokenManager: FluentTokenManager(), clientRetriever: FluentClientRetriever(), authorizeHandler: capturingAuthHandler, userManager: FluentUserManager(), validScopes: [scope], resourceServerRetriever: FluentResourceServerRetriever())

var config = Config([:])

Expand All @@ -53,6 +55,7 @@ class VaporOAuthFluentTests: XCTestCase {
config.preparations.append(OAuthCode.self)
config.preparations.append(AccessToken.self)
config.preparations.append(RefreshToken.self)
config.preparations.append(OAuthResourceServer.self)

drop = try! Droplet(config)

Expand All @@ -68,10 +71,13 @@ class VaporOAuthFluentTests: XCTestCase {

passwordClient = OAuthClient(clientID: passwordClientID, redirectURIs: [redirectURI], clientSecret: clientSecret, validScopes: [scope], confidential: true, firstParty: true, allowedGrantType: .password)
try! passwordClient.save()

resourceServer = OAuthResourceServer(username: username, password: password.makeBytes())
try! resourceServer.save()
}

override func tearDown() {
try! drop.database?.revertAll([OAuthClient.self, OAuthUser.self, OAuthCode.self, AccessToken.self, RefreshToken.self])
try! drop.database?.revertAll([OAuthClient.self, OAuthUser.self, OAuthCode.self, AccessToken.self, RefreshToken.self, OAuthResourceServer.self])
}

// MARK: - Tests
Expand Down Expand Up @@ -281,6 +287,47 @@ class VaporOAuthFluentTests: XCTestCase {
XCTAssertEqual(userResponse.json?["email"]?.string, email)
}

func testThatRemoteTokenIntrospectWorksAsExpectedWithFluentModel() throws {
let tokenString = "ABCDEFGH"
let expiryDate = Date().addingTimeInterval(3600)
let token = AccessToken(tokenString: tokenString, clientID: clientID, userID: user.id, scopes: [scope], expiryTime: expiryDate)
try token.save()

let credentials = "\(username):\(password)".makeBytes().base64Encoded.makeString()
let authHeader = "Basic \(credentials)"

let request = Request(method: .post, uri: "/oauth/token_info")
request.headers[.authorization] = authHeader

var json = JSON()
try json.set("token", tokenString)
request.json = json

let response = try drop.respond(to: request)

XCTAssertEqual(response.status, .ok)

guard let responseJSON = response.json else {
XCTFail()
return
}

XCTAssertEqual(responseJSON["active"]?.bool, true)
XCTAssertEqual(responseJSON["exp"]?.int, Int(expiryDate.timeIntervalSince1970))
XCTAssertEqual(responseJSON["username"]?.string, username)
XCTAssertEqual(responseJSON["client_id"]?.string, clientID)
XCTAssertEqual(responseJSON["scope"]?.string, scope)

let failingRequest = Request(method: .post, uri: "/oauth/token_info")
let wrongCredentials = "unknown:\(password)".makeBytes().base64Encoded.makeString()
let wongAuthHeader = "Basic \(wrongCredentials)"

failingRequest.headers[.authorization] = wongAuthHeader

let failingResponse = try drop.respond(to: failingRequest)

XCTAssertEqual(failingResponse.status, .unauthorized)
}
}

class CapturingAuthHandler: AuthorizeHandler {
Expand Down

0 comments on commit 294295c

Please sign in to comment.