From 2e165fec4395066496e048c69a7e597864a52b39 Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Wed, 16 Oct 2024 10:04:44 +0100 Subject: [PATCH] Update auth-otp for Authentication context identity --- auth-otp/Package.swift | 2 +- auth-otp/Sources/App/Controllers/TOTPController.swift | 11 ++++++----- auth-otp/Sources/App/Controllers/UserController.swift | 2 +- auth-otp/Sources/App/Controllers/WebController.swift | 8 ++++---- .../Sources/App/Middleware/RedirectMiddleware.swift | 2 +- auth-otp/Sources/App/Models/User.swift | 7 ++++--- auth-otp/Sources/App/RequestContext.swift | 4 ++-- 7 files changed, 19 insertions(+), 17 deletions(-) diff --git a/auth-otp/Package.swift b/auth-otp/Package.swift index d3a2f3ba..d5ebf72f 100644 --- a/auth-otp/Package.swift +++ b/auth-otp/Package.swift @@ -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"), diff --git a/auth-otp/Sources/App/Controllers/TOTPController.swift b/auth-otp/Sources/App/Controllers/TOTPController.swift index 61773beb..9d850771 100644 --- a/auth-otp/Sources/App/Controllers/TOTPController.swift +++ b/auth-otp/Sources/App/Controllers/TOTPController.swift @@ -33,8 +33,9 @@ struct TOTPController { 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 } @@ -43,7 +44,7 @@ struct TOTPController { 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 @@ -55,13 +56,13 @@ struct TOTPController { 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") } diff --git a/auth-otp/Sources/App/Controllers/UserController.swift b/auth-otp/Sources/App/Controllers/UserController.swift index 5e769abb..e3beb867 100644 --- a/auth-otp/Sources/App/Controllers/UserController.swift +++ b/auth-otp/Sources/App/Controllers/UserController.swift @@ -17,7 +17,7 @@ struct UserController: 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 { diff --git a/auth-otp/Sources/App/Controllers/WebController.swift b/auth-otp/Sources/App/Controllers/WebController.swift index 3f61b183..2b7e082d 100644 --- a/auth-otp/Sources/App/Controllers/WebController.swift +++ b/auth-otp/Sources/App/Controllers/WebController.swift @@ -25,14 +25,14 @@ struct WebController { 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)) } diff --git a/auth-otp/Sources/App/Middleware/RedirectMiddleware.swift b/auth-otp/Sources/App/Middleware/RedirectMiddleware.swift index 38d8e08c..436c1597 100644 --- a/auth-otp/Sources/App/Middleware/RedirectMiddleware.swift +++ b/auth-otp/Sources/App/Middleware/RedirectMiddleware.swift @@ -9,7 +9,7 @@ struct RedirectMiddleware: 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) diff --git a/auth-otp/Sources/App/Models/User.swift b/auth-otp/Sources/App/Models/User.swift index 6ff1e51a..4269a348 100644 --- a/auth-otp/Sources/App/Models/User.swift +++ b/auth-otp/Sources/App/Models/User.swift @@ -2,7 +2,7 @@ import Foundation import HummingbirdAuth import HummingbirdBasicAuth -struct User: Authenticatable, PasswordAuthenticatable { +struct User: PasswordAuthenticatable { struct Flags: OptionSet { let rawValue: Int @@ -10,11 +10,12 @@ struct User: Authenticatable, PasswordAuthenticatable { 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? -} \ No newline at end of file +} diff --git a/auth-otp/Sources/App/RequestContext.swift b/auth-otp/Sources/App/RequestContext.swift index 7fdcb2fb..60807be7 100644 --- a/auth-otp/Sources/App/RequestContext.swift +++ b/auth-otp/Sources/App/RequestContext.swift @@ -9,12 +9,12 @@ struct AppSessionRequestContext: SessionRequestContext, AuthRequestContext { typealias Source = AppRequestContext var sessions: SessionContext - 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() } }