Skip to content

Commit

Permalink
Update auth-otp for Authentication context identity
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-fowler committed Oct 16, 2024
1 parent c03259b commit ddbc030
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 17 deletions.
2 changes: 1 addition & 1 deletion auth-otp/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0"),
.package(url: "https://github.com/hummingbird-project/hummingbird-auth.git", branch: "session-middleware"),
.package(url: "https://github.com/hummingbird-project/hummingbird-auth.git", branch: "main"),
.package(url: "https://github.com/hummingbird-project/hummingbird-postgres.git", from: "0.5.0"),
.package(url: "https://github.com/hummingbird-project/swift-mustache.git", from: "2.0.0-rc"),
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.3.0"),
Expand Down
11 changes: 6 additions & 5 deletions auth-otp/Sources/App/Controllers/TOTPController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ struct TOTPController<Users: UserRepository, Storage: PersistDriver> {
let code = try context.parameters.require("code", as: Int.self)
guard let otpSession = request.headers[.otpSession] else { return .badRequest }
guard var otpVerificationSession = try await self.storage.get(key: otpSession, as: TOTPVerificationSession.self) else { return .notFound }
let computedTOTP = TOTP(secret: otpVerificationSession.secret).compute(date: .now - 15.0)
let computedTOTP2 = TOTP(secret: otpVerificationSession.secret).compute(date: .now + 15.0)
let now = Date.now
let computedTOTP = TOTP(secret: otpVerificationSession.secret).compute(date: now - 15.0)
let computedTOTP2 = TOTP(secret: otpVerificationSession.secret).compute(date: now + 15.0)
guard code == computedTOTP || code == computedTOTP2 else {
return .unauthorized
}
Expand All @@ -43,7 +44,7 @@ struct TOTPController<Users: UserRepository, Storage: PersistDriver> {
return .ok
}
.post("complete") { request, context -> HTTPResponse.Status in
let user = try context.auth.require(User.self)
guard let user = context.identity else { throw HTTPError(.unauthorized) }
guard let otpSession = request.headers[.otpSession] else { return .badRequest }
guard let otpVerificationSession = try await self.storage.get(key: otpSession, as: TOTPVerificationSession.self) else {
return .notFound
Expand All @@ -55,13 +56,13 @@ struct TOTPController<Users: UserRepository, Storage: PersistDriver> {
return .ok
}
.delete { request, context -> HTTPResponse.Status in
let user = try context.auth.require(User.self)
guard let user = context.identity else { throw HTTPError(.unauthorized) }
guard user.otpSecret != nil else { return .ok }
try await self.users.removeTOTP(userID: user.id, logger: context.logger)
return .ok
}
.get { request, context in
let user = try context.auth.require(User.self)
guard let user = context.identity else { throw HTTPError(.unauthorized) }
guard let secret = user.otpSecret else { throw HTTPError(.noContent) }
return TOTP(secret: secret).createAuthenticatorURL(label: "auth-otp")
}
Expand Down
2 changes: 1 addition & 1 deletion auth-otp/Sources/App/Controllers/UserController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct UserController<Users: UserRepository, Storage: PersistDriver>: Sendable {
TOTPAuthenticator(users: self.users)
}
.post { _, context in
let user = try context.auth.require(User.self)
guard let user = context.identity else { throw HTTPError(.unauthorized) }
let session = context.sessions.session
if user.otpSecret != nil {
switch session {
Expand Down
8 changes: 4 additions & 4 deletions auth-otp/Sources/App/Controllers/WebController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ struct WebController<Users: UserRepository, Storage: PersistDriver> {
routes.group("", context: AppSessionRequestContext.self)
.addMiddleware {
SessionMiddleware(storage: self.storage)
SessionAuthenticator(users: users)
SessionAuthenticator(users: self.users)
RedirectMiddleware(to: "/login.html")
}
.get { _, context in
let user = try context.auth.require(User.self)
guard let user = context.identity else { throw HTTPError(.unauthorized) }
let context: [String: Any] = [
"name": user.name,
"addOTP": user.otpSecret == nil
"name": user.name,
"addOTP": user.otpSecret == nil,
]
return HTML(self.indexTemplate.render(context, library: self.mustacheLibrary))
}
Expand Down
2 changes: 1 addition & 1 deletion auth-otp/Sources/App/Middleware/RedirectMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct RedirectMiddleware<Context: AuthRequestContext>: RouterMiddleware {
context: Context,
next: (Request, Context) async throws -> Output
) async throws -> Response {
if context.auth.has(User.self) {
if context.identity != nil {
return try await next(request, context)
} else {
return .redirect(to: "\(self.to)?from=\(request.uri)", type: .found)
Expand Down
7 changes: 4 additions & 3 deletions auth-otp/Sources/App/Models/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import Foundation
import HummingbirdAuth
import HummingbirdBasicAuth

struct User: Authenticatable, PasswordAuthenticatable {
struct User: PasswordAuthenticatable {
struct Flags: OptionSet {
let rawValue: Int

init(rawValue: Int) {
self.rawValue = rawValue
}

static var requiresOTP: Flags { .init(rawValue: 1<<0) }
static var requiresOTP: Flags { .init(rawValue: 1 << 0) }
}

let id: UUID
let name: String
let email: String
let passwordHash: String?
let otpSecret: String?
}
}
4 changes: 2 additions & 2 deletions auth-otp/Sources/App/RequestContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ struct AppSessionRequestContext: SessionRequestContext, AuthRequestContext {
typealias Source = AppRequestContext

var sessions: SessionContext<Session>
var auth: LoginCache
var identity: User?
var coreContext: CoreRequestContextStorage

init(source: Source) {
self.coreContext = source.coreContext
self.auth = .init()
self.identity = nil
self.sessions = .init()
}
}

0 comments on commit ddbc030

Please sign in to comment.