Skip to content

Commit 0159803

Browse files
authored
Merge pull request #26 from vapor/unauth-protocol-refactor
adds unauth + protocol reqs
2 parents 93ab4ae + 959e8fd commit 0159803

17 files changed

+270
-242
lines changed

Sources/Authentication/Basic/Basic+Authenticate.swift

Lines changed: 0 additions & 31 deletions
This file was deleted.

Sources/Authentication/Basic/BasicAuthenticatable.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,45 @@ public protocol BasicAuthenticatable: Authenticatable {
1717
/// The key under which the user's password
1818
/// is stored.
1919
static var passwordKey: PasswordKey { get }
20+
21+
/// Authenticates using the supplied credentials, connection, and verifier.
22+
static func authenticate(
23+
using basic: BasicAuthorization,
24+
verifier: PasswordVerifier,
25+
on connection: DatabaseConnectable
26+
) -> Future<Self?>
2027
}
2128

29+
extension BasicAuthenticatable where Database: QuerySupporting {
30+
/// See `BasicAuthenticatable.authenticate(...)`
31+
public static func authenticate(
32+
using basic: BasicAuthorization,
33+
verifier: PasswordVerifier,
34+
on connection: DatabaseConnectable
35+
) -> Future<Self?> {
36+
return Self
37+
.query(on: connection)
38+
.filter(usernameKey == basic.username)
39+
.first()
40+
.map(to: Self?.self)
41+
{ user in
42+
guard let user = user else {
43+
return nil
44+
}
45+
46+
guard try verifier.verify(
47+
password: basic.password,
48+
matches: user.basicPassword
49+
) else {
50+
return nil
51+
}
52+
53+
return user
54+
}
55+
}
56+
}
57+
58+
2259
extension BasicAuthenticatable {
2360
/// Accesses the model's password
2461
public var basicPassword: String {

Sources/Authentication/Basic/BasicAuthenticationMiddleware.swift

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,13 @@ import Vapor
55
/// instance to pass through.
66
///
77
/// use `req.requireAuthenticated(A.self)` to fetch the instance.
8-
public final class BasicAuthenticationMiddleware<A>: Middleware
9-
where A: BasicAuthenticatable, A.Database: QuerySupporting
10-
{
8+
public final class BasicAuthenticationMiddleware<A>: Middleware where A: BasicAuthenticatable {
119
/// the required password verifier
1210
public let verifier: PasswordVerifier
1311

14-
/// The database identifier
15-
public let database: DatabaseIdentifier<A.Database>
16-
1712
/// create a new password auth middleware
18-
public init(
19-
authenticatable type: A.Type = A.self,
20-
verifier: PasswordVerifier,
21-
database: DatabaseIdentifier<A.Database>
22-
) {
13+
public init(authenticatable type: A.Type = A.self, verifier: PasswordVerifier) {
2314
self.verifier = verifier
24-
self.database = database
2515
}
2616

2717
/// See Middleware.respond
@@ -41,36 +31,27 @@ public final class BasicAuthenticationMiddleware<A>: Middleware
4131
)
4232
}
4333

44-
// get database connection
45-
return req.connect(to: self.database).flatMap(to: Response.self) { conn in
46-
// auth user on connection
47-
return A.authenticate(
48-
using: password,
49-
verifier: self.verifier,
50-
on: conn
51-
).flatMap(to: Response.self) { a in
52-
guard let a = a else {
53-
throw Abort(.unauthorized, reason: "Invalid credentials")
54-
}
55-
56-
// set authed on request
57-
try req.authenticate(a)
58-
return try next.respond(to: req)
34+
// auth user on connection
35+
return A.authenticate(
36+
using: password,
37+
verifier: self.verifier,
38+
on: req
39+
).flatMap(to: Response.self) { a in
40+
guard let a = a else {
41+
throw Abort(.unauthorized, reason: "Invalid credentials")
5942
}
43+
44+
// set authed on request
45+
try req.authenticate(a)
46+
return try next.respond(to: req)
6047
}
6148
}
6249
}
6350

6451
extension BasicAuthenticatable where Database: QuerySupporting {
6552
/// Creates a basic auth middleware for this model.
6653
/// See `BasicAuthenticationMiddleware`.
67-
public static func basicAuthMiddleware(
68-
using verifier: PasswordVerifier,
69-
database: DatabaseIdentifier<Database>? = nil
70-
) throws -> BasicAuthenticationMiddleware<Self> {
71-
return try BasicAuthenticationMiddleware(
72-
verifier: verifier,
73-
database: database ?? Self.requireDefaultDatabase()
74-
)
54+
public static func basicAuthMiddleware(using verifier: PasswordVerifier) -> BasicAuthenticationMiddleware<Self> {
55+
return BasicAuthenticationMiddleware(verifier: verifier)
7556
}
7657
}

Sources/Authentication/Bearer/Bearer+Authenticate.swift

Lines changed: 0 additions & 15 deletions
This file was deleted.

Sources/Authentication/Bearer/BearerAuthenticatable.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,28 @@ public protocol BearerAuthenticatable: Authenticatable {
99

1010
/// The key under which the model's unique token is stored.
1111
static var tokenKey: TokenKey { get }
12+
13+
/// Authenticates using the supplied credentials and connection.
14+
static func authenticate(
15+
using bearer: BearerAuthorization,
16+
on connection: DatabaseConnectable
17+
) -> Future<Self?>
1218
}
1319

20+
extension BearerAuthenticatable where Database: QuerySupporting {
21+
/// See `BearerAuthenticatable.authenticate(...)`
22+
public static func authenticate(
23+
using bearer: BearerAuthorization,
24+
on connection: DatabaseConnectable
25+
) -> Future<Self?> {
26+
return Self
27+
.query(on: connection)
28+
.filter(tokenKey == bearer.token)
29+
.first()
30+
}
31+
}
32+
33+
1434
extension BearerAuthenticatable {
1535
/// Accesses the model's token
1636
public var bearerToken: String {

Sources/Authentication/Bearer/BearerAuthenticationMiddleware.swift

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,9 @@ import Vapor
55
/// instance to pass through.
66
///
77
/// use `req.requireAuthenticated(A.self)` to fetch the instance.
8-
public final class BearerAuthenticationMiddleware<A>: Middleware
9-
where A: BearerAuthenticatable, A.Database: QuerySupporting
10-
{
11-
/// The database identifier
12-
public let database: DatabaseIdentifier<A.Database>
13-
8+
public final class BearerAuthenticationMiddleware<A>: Middleware where A: BearerAuthenticatable {
149
/// Creates a new `BearerAuthenticationMiddleware`.
15-
public init(
16-
_ type: A.Type = A.self,
17-
database: DatabaseIdentifier<A.Database>
18-
) {
19-
self.database = database
20-
}
10+
public init(_ type: A.Type = A.self) {}
2111

2212
/// See Middleware.respond
2313
public func respond(to req: Request, chainingTo next: Responder) throws -> Future<Response> {
@@ -35,33 +25,26 @@ public final class BearerAuthenticationMiddleware<A>: Middleware
3525
)
3626
}
3727

38-
// get database connection
39-
return req.connect(to: database).flatMap(to: Response.self) { conn in
40-
// auth user on connection
41-
return A.authenticate(
42-
using: token,
43-
on: conn
44-
).flatMap(to: Response.self) { a in
45-
guard let a = a else {
46-
throw Abort(.unauthorized, reason: "Invalid credentials")
47-
}
48-
49-
// set authed on request
50-
try req.authenticate(a)
51-
return try next.respond(to: req)
28+
// auth user on connection
29+
return A.authenticate(
30+
using: token,
31+
on: req
32+
).flatMap(to: Response.self) { a in
33+
guard let a = a else {
34+
throw Abort(.unauthorized, reason: "Invalid credentials")
5235
}
36+
37+
// set authed on request
38+
try req.authenticate(a)
39+
return try next.respond(to: req)
5340
}
5441
}
5542
}
5643

57-
extension BearerAuthenticatable where Database: QuerySupporting {
44+
extension BearerAuthenticatable {
5845
/// Creates a basic auth middleware for this model.
5946
/// See `BasicAuthenticationMiddleware`.
60-
public static func bearerAuthMiddleware(
61-
database: DatabaseIdentifier<Database>? = nil
62-
) throws -> BearerAuthenticationMiddleware<Self> {
63-
return try BearerAuthenticationMiddleware(
64-
database: database ?? Self.requireDefaultDatabase()
65-
)
47+
public static func bearerAuthMiddleware() -> BearerAuthenticationMiddleware<Self> {
48+
return BearerAuthenticationMiddleware()
6649
}
6750
}

Sources/Authentication/PasswordAuthenticatable.swift renamed to Sources/Authentication/Password/PasswordAuthenticatable.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@ import Service
44
import Vapor
55

66
/// Authenticatable using a username and password.
7-
public protocol PasswordAuthenticatable: BasicAuthenticatable { }
7+
public protocol PasswordAuthenticatable: BasicAuthenticatable {
8+
/// Authenticates using a username and password using the supplied
9+
/// verifier on the supplied connection.
10+
static func authenticate(
11+
username: String,
12+
password: String,
13+
using verifier: PasswordVerifier,
14+
on worker: DatabaseConnectable
15+
) -> Future<Self?>
16+
}
817

918
extension PasswordAuthenticatable where Database: QuerySupporting {
10-
/// Authenticates using a username and password using the supplied
11-
// verifier on the supplied connection.
19+
/// See `PasswordAuthenticatable.authenticate(...)`
1220
public static func authenticate(
1321
username: String,
1422
password: String,
File renamed without changes.

Sources/Authentication/Persist/AuthenticationSessionsMiddleware.swift

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,23 @@ import Vapor
33

44
/// Persists authentication done by another auth middleware
55
/// allowing the authentication to only be passed once.
6-
public final class AuthenticationSessionsMiddleware<A>: Middleware
7-
where A: Authenticatable, A.Database: QuerySupporting, A.ID: StringConvertible
8-
{
9-
/// The database identifier
10-
public let database: DatabaseIdentifier<A.Database>
11-
6+
public final class AuthenticationSessionsMiddleware<A>: Middleware where A: SessionAuthenticatable {
127
/// create a new password auth middleware
13-
public init(
14-
authenticatable type: A.Type = A.self,
15-
database: DatabaseIdentifier<A.Database>
16-
) {
17-
self.database = database
18-
}
8+
public init(authenticatable type: A.Type = A.self) { }
199

2010
/// See Middleware.respond
2111
public func respond(to req: Request, chainingTo next: Responder) throws -> Future<Response> {
2212
let future: Future<Void>
2313
if let aID = try req.authenticatedSession(A.self) {
24-
// get database connection
25-
future = req.connect(to: database).flatMap(to: Void.self) { conn in
26-
// try to find user with id from session
27-
return A.find(aID, on: conn).flatMap(to: Void.self) { a in
28-
// if the user was found, auth it
29-
if let a = a {
30-
try req.authenticate(a)
31-
}
32-
33-
// return done
34-
return .done
14+
// try to find user with id from session
15+
future = A.authenticate(id: aID, on: req).flatMap(to: Void.self) { a in
16+
// if the user was found, auth it
17+
if let a = a {
18+
try req.authenticate(a)
3519
}
20+
21+
// return done
22+
return .done
3623
}
3724
} else {
3825
// no need to authenticate
@@ -53,26 +40,10 @@ public final class AuthenticationSessionsMiddleware<A>: Middleware
5340
}
5441
}
5542

56-
extension Request {
57-
/// Authenticates the model into the session.
58-
public func authenticateSession<A>(_ a: A) throws where A: Authenticatable, A.ID: StringConvertible {
59-
try session()["_" + A.name + "Session"] = try a.requireID().convertToString()
60-
}
61-
62-
/// Returns the authenticatable type's ID if it exists
63-
/// in the session data.
64-
public func authenticatedSession<A>(_ a: A.Type) throws -> A.ID? where A: Authenticatable, A.ID: StringConvertible {
65-
guard let idString = try session()["_" + A.name + "Session"] else {
66-
return nil
67-
}
68-
return try A.ID.convertFromString(idString)
69-
}
70-
}
71-
72-
extension Authenticatable where Database: QuerySupporting, Self.ID: StringConvertible {
43+
extension SessionAuthenticatable {
7344
/// Create a `AuthenticationSessionsMiddleware` for this model.
7445
/// See `AuthenticationSessionsMiddleware`.
75-
public static func authSessionsMiddleware() throws -> AuthenticationSessionsMiddleware<Self> {
76-
return try .init(database: Self.requireDefaultDatabase())
46+
public static func authSessionsMiddleware() -> AuthenticationSessionsMiddleware<Self> {
47+
return .init()
7748
}
7849
}

0 commit comments

Comments
 (0)