Skip to content

Commit

Permalink
HummingbirdTesting rename changes (#62)
Browse files Browse the repository at this point in the history
* HummingbirdTesting rename changes

* Update build script

* Update todos-postgres-tutorial, html-form

* auth-cognito update

* Update auth-jwt

* Update hello example

* Update HTTP2

* Update Sessions

* Updates tor todos-auth-fluent

* Convert Todos-dynamodb

* Update for todos-lambda

* Update upload

* Update webauthn

* Fix todos-auth-fluent

* Update packages to point to 2.0 beta
  • Loading branch information
adam-fowler authored Mar 14, 2024
1 parent a20ad5d commit 08e2074
Show file tree
Hide file tree
Showing 83 changed files with 584 additions and 630 deletions.
6 changes: 3 additions & 3 deletions auth-cognito/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ let package = Package(
name: "auth-cognito",
platforms: [.macOS(.v14)],
dependencies: [
.package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0-alpha.3"),
.package(url: "https://github.com/hummingbird-project/hummingbird-auth.git", from: "2.0.0-alpha.3"),
.package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0-beta.1"),
.package(url: "https://github.com/hummingbird-project/hummingbird-auth.git", from: "2.0.0-beta.1"),
.package(url: "https://github.com/adam-fowler/soto-cognito-authentication-kit.git", from: "5.0.0-alpha.1"),
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.0"),
],
Expand All @@ -34,7 +34,7 @@ let package = Package(
name: "AppTests",
dependencies: [
.byName(name: "App"),
.product(name: "HummingbirdXCT", package: "hummingbird"),
.product(name: "HummingbirdTesting", package: "hummingbird"),
]
),
]
Expand Down
8 changes: 4 additions & 4 deletions auth-cognito/Sources/App/Application+build.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ struct AWSClientService: Service {
}
}

func buildApplication(configuration: HBApplicationConfiguration) async throws -> some HBApplicationProtocol {
func buildApplication(configuration: ApplicationConfiguration) async throws -> some ApplicationProtocol {
// setup Soto
let awsClient = AWSClient(httpClientProvider: .createNew)
let cognitoIdentityProvider = CognitoIdentityProvider(client: awsClient, region: .euwest1)
// setup SotoCognitoAuthentication
let env = try await HBEnvironment().merging(with: .dotEnv())
let env = try await Environment().merging(with: .dotEnv())
guard let userPoolId = env.get("cognito_user_pool_id"),
let clientId = env.get("cognito_client_id")
else {
Expand All @@ -34,12 +34,12 @@ func buildApplication(configuration: HBApplicationConfiguration) async throws ->
)
let authenticatable = CognitoAuthenticatable(configuration: config)

let router = HBRouterBuilder(context: AuthCognitoRequestContext.self) {
let router = RouterBuilder(context: AuthCognitoRequestContext.self) {
AWSErrorMiddleware()
UserController(cognitoAuthenticatable: authenticatable, cognitoIdentityProvider: cognitoIdentityProvider).endpoints
}

var app = HBApplication(router: router)
var app = Application(router: router)
app.addServices(AWSClientService(client: awsClient))
return app
}
54 changes: 27 additions & 27 deletions auth-cognito/Sources/App/Controllers/UserController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ import HummingbirdRouter
import SotoCognitoAuthenticationKit
import SotoCognitoAuthenticationSRP

extension CognitoAccessToken: HBResponseEncodable {}
extension CognitoAuthenticateResponse: HBResponseEncodable {}
extension CognitoCreateUserResponse: HBResponseEncodable {}
extension CognitoAccessToken: ResponseEncodable {}
extension CognitoAuthenticateResponse: ResponseEncodable {}
extension CognitoCreateUserResponse: ResponseEncodable {}

struct UserController {
typealias Context = AuthCognitoRequestContext

let cognitoAuthenticatable: CognitoAuthenticatable
let cognitoIdentityProvider: CognitoIdentityProvider

var endpoints: some HBMiddlewareProtocol<Context> {
var endpoints: some RouterMiddleware<Context> {
RouteGroup("user") {
Put(handler: self.create)
Patch(handler: self.resend)
Expand Down Expand Up @@ -49,7 +49,7 @@ struct UserController {
}

/// create a user
@Sendable func create(_ request: HBRequest, context: Context) async throws -> CognitoCreateUserResponse {
@Sendable func create(_ request: Request, context: Context) async throws -> CognitoCreateUserResponse {
struct CreateUserRequest: Decodable {
var username: String
var attributes: [String: String]
Expand All @@ -59,7 +59,7 @@ struct UserController {
}

/// resend create user email
@Sendable func resend(_ request: HBRequest, context: Context) async throws -> CognitoCreateUserResponse {
@Sendable func resend(_ request: Request, context: Context) async throws -> CognitoCreateUserResponse {
struct ResendRequest: Decodable {
var username: String
var attributes: [String: String]
Expand All @@ -73,13 +73,13 @@ struct UserController {
}

/// response for signup
struct SignUpResponse: HBResponseEncodable {
struct SignUpResponse: ResponseEncodable {
var confirmed: Bool
var userSub: String
}

/// sign up instead of create user
@Sendable func signUp(_ request: HBRequest, context: Context) async throws -> SignUpResponse {
@Sendable func signUp(_ request: Request, context: Context) async throws -> SignUpResponse {
struct SignUpRequest: Decodable {
var username: String
var password: String
Expand All @@ -91,7 +91,7 @@ struct UserController {
}

/// confirm sign up with confirmation code
@Sendable func confirmSignUp(_ request: HBRequest, context: Context) async throws -> HTTPResponse.Status {
@Sendable func confirmSignUp(_ request: Request, context: Context) async throws -> HTTPResponse.Status {
struct ConfirmSignUpRequest: Decodable {
var username: String
var code: String
Expand All @@ -102,19 +102,19 @@ struct UserController {
}

/// Logs a user in, returning a token for accessing protected endpoints.
@Sendable func login(_ request: HBRequest, context: Context) throws -> CognitoAuthenticateResponse {
@Sendable func login(_ request: Request, context: Context) throws -> CognitoAuthenticateResponse {
let authenticateResponse = try context.auth.require(CognitoAuthenticateResponse.self)
return authenticateResponse
}

/// Logs a user in using Secure Remote Password, returning a token for accessing protected endpoints.
@Sendable func loginSRP(_ request: HBRequest, context: Context) throws -> CognitoAuthenticateResponse {
@Sendable func loginSRP(_ request: Request, context: Context) throws -> CognitoAuthenticateResponse {
let authenticateResponse = try context.auth.require(CognitoAuthenticateResponse.self)
return authenticateResponse
}

/// respond to authentication challenge
@Sendable func respond(_ request: HBRequest, context: Context) async throws -> CognitoAuthenticateResponse {
@Sendable func respond(_ request: Request, context: Context) async throws -> CognitoAuthenticateResponse {
struct ChallengeResponse: Codable {
let username: String
let name: CognitoChallengeName
Expand All @@ -131,7 +131,7 @@ struct UserController {
}

/// respond to new password authentication challenge
@Sendable func respondNewPassword(_ request: HBRequest, context: Context) async throws -> CognitoAuthenticateResponse {
@Sendable func respondNewPassword(_ request: Request, context: Context) async throws -> CognitoAuthenticateResponse {
struct ChallengeResponse: Codable {
let username: String
let password: String
Expand All @@ -146,13 +146,13 @@ struct UserController {
}

/// authenticate access token
@Sendable func authenticateAccess(_ request: HBRequest, context: Context) throws -> CognitoAccessToken {
@Sendable func authenticateAccess(_ request: Request, context: Context) throws -> CognitoAccessToken {
let token = try context.auth.require(CognitoAccessToken.self)
return token
}

/// get user attributes
@Sendable func attributes(_ request: HBRequest, context: Context) async throws -> String {
@Sendable func attributes(_ request: Request, context: Context) async throws -> String {
struct AttributesRequest: Codable {
let attributes: [String: String]
}
Expand All @@ -163,18 +163,18 @@ struct UserController {
}

/// authenticate id token
@Sendable func authenticateId(_ request: HBRequest, context: Context) throws -> User {
@Sendable func authenticateId(_ request: Request, context: Context) throws -> User {
let token = try context.auth.require(User.self)
return token
}

/// refresh tokens
@Sendable func refresh(_ request: HBRequest, context: Context) async throws -> CognitoAuthenticateResponse {
@Sendable func refresh(_ request: Request, context: Context) async throws -> CognitoAuthenticateResponse {
struct RefreshRequest: Decodable {
let username: String
}
let user = try await request.decode(as: RefreshRequest.self, context: context)
guard let refreshToken = request.headers.bearer?.token else { throw HBHTTPError(.badRequest) }
guard let refreshToken = request.headers.bearer?.token else { throw HTTPError(.badRequest) }
return try await self.cognitoAuthenticatable.refresh(
username: user.username,
refreshToken: refreshToken
Expand All @@ -183,31 +183,31 @@ struct UserController {

// MARK: MFA

struct MfaGetTokenResponse: HBResponseEncodable {
struct MfaGetTokenResponse: ResponseEncodable {
let authenticatorURL: String
let session: String?
}

/// Get MFA secret code
@Sendable func mfaGetSecretCode(_ request: HBRequest, context: Context) async throws -> MfaGetTokenResponse {
@Sendable func mfaGetSecretCode(_ request: Request, context: Context) async throws -> MfaGetTokenResponse {
let token = try context.auth.require(CognitoAccessToken.self)
guard let accessToken = request.headers.bearer else { throw HBHTTPError(.unauthorized) }
guard let accessToken = request.headers.bearer else { throw HTTPError(.unauthorized) }
let response = try await cognitoIdentityProvider.associateSoftwareToken(.init(accessToken: accessToken.token))
guard let secretCode = response.secretCode else {
throw HBHTTPError(.internalServerError)
throw HTTPError(.internalServerError)
}
let url = "otpauth://totp/\(token.username)?secret=\(secretCode)&issuer=hb-auth-cognito"
return MfaGetTokenResponse(authenticatorURL: url, session: response.session)
}

/// Verify MFA secret code
@Sendable func mfaVerifyToken(_ request: HBRequest, context: Context) async throws -> HTTPResponse.Status {
@Sendable func mfaVerifyToken(_ request: Request, context: Context) async throws -> HTTPResponse.Status {
struct VerifyRequest: Decodable {
let deviceName: String?
let session: String?
let userCode: String
}
guard let accessToken = request.headers.bearer else { throw HBHTTPError(.unauthorized) }
guard let accessToken = request.headers.bearer else { throw HTTPError(.unauthorized) }
let verify = try await request.decode(as: VerifyRequest.self, context: context)
let verifySoftwareTokenRequest = CognitoIdentityProvider.VerifySoftwareTokenRequest(
accessToken: accessToken.token,
Expand All @@ -225,7 +225,7 @@ struct UserController {
}

/// respond to software MFA authentication challenge
@Sendable func respondSoftwareMfa(_ request: HBRequest, context: Context) async throws -> CognitoAuthenticateResponse {
@Sendable func respondSoftwareMfa(_ request: Request, context: Context) async throws -> CognitoAuthenticateResponse {
struct MfaChallengeResponse: Codable {
let username: String
let code: String
Expand All @@ -241,7 +241,7 @@ struct UserController {
}

/// Enable MFA support
@Sendable func enableMfa(_ request: HBRequest, context: Context) async throws -> HTTPResponse.Status {
@Sendable func enableMfa(_ request: Request, context: Context) async throws -> HTTPResponse.Status {
let token = try context.auth.require(CognitoAccessToken.self)
let setUserMfaRequest = CognitoIdentityProvider.AdminSetUserMFAPreferenceRequest(
softwareTokenMfaSettings: .init(enabled: true, preferredMfa: true),
Expand All @@ -253,7 +253,7 @@ struct UserController {
}

/// Disable MFA support
@Sendable func disableMfa(_ request: HBRequest, context: Context) async throws -> HTTPResponse.Status {
@Sendable func disableMfa(_ request: Request, context: Context) async throws -> HTTPResponse.Status {
struct Password: Decodable {
let password: String
}
Expand Down
12 changes: 6 additions & 6 deletions auth-cognito/Sources/App/Middleware/AWSErrorMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ import SotoCognitoAuthenticationKit
import SotoCore

/// Output AWS error messages to user
struct AWSErrorMiddleware<Context: HBRequestContext>: HBMiddlewareProtocol {
func handle(_ request: HBRequest, context: Context, next: (HBRequest, Context) async throws -> HBResponse) async throws -> HBResponse {
struct AWSErrorMiddleware<Context: RequestContext>: RouterMiddleware {
func handle(_ request: Request, context: Context, next: (Request, Context) async throws -> Response) async throws -> Response {
do {
return try await next(request, context)
} catch let error as AWSErrorType {
throw HBHTTPError(.internalServerError, message: "Code: \(error.errorCode), Message: \(error.message ?? "No message")")
throw HTTPError(.internalServerError, message: "Code: \(error.errorCode), Message: \(error.message ?? "No message")")
} catch let error as SotoCognitoError {
throw switch error {
case .unexpectedResult(let message):
HBHTTPError(.internalServerError, message: "Unexpected result: \(message ?? "")")
HTTPError(.internalServerError, message: "Unexpected result: \(message ?? "")")
case .unauthorized(let message):
HBHTTPError(.internalServerError, message: "Unauthorized: \(message ?? "")")
HTTPError(.internalServerError, message: "Unauthorized: \(message ?? "")")
case .invalidPublicKey:
HBHTTPError(.internalServerError, message: "Invalid public key")
HTTPError(.internalServerError, message: "Invalid public key")
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions auth-cognito/Sources/App/Middleware/CognitoAuthenticators.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import Hummingbird
import HummingbirdAuth
import SotoCognitoAuthenticationKit

extension CognitoAuthenticateResponse: HBAuthenticatable {}
extension CognitoAccessToken: HBAuthenticatable {}
extension CognitoAuthenticateResponse: Authenticatable {}
extension CognitoAccessToken: Authenticatable {}

/// Authenticator for Cognito username and password
struct CognitoBasicAuthenticator: HBAuthenticator {
struct CognitoBasicAuthenticator: AuthenticatorMiddleware {
typealias Context = AuthCognitoRequestContext
let cognitoAuthenticatable: CognitoAuthenticatable

func authenticate(request: HBRequest, context: AuthCognitoRequestContext) async throws -> CognitoAuthenticateResponse? {
func authenticate(request: Request, context: AuthCognitoRequestContext) async throws -> CognitoAuthenticateResponse? {
guard let basic = request.headers.basic else { return nil }
return try? await self.cognitoAuthenticatable.authenticate(
username: basic.username,
Expand All @@ -21,11 +21,11 @@ struct CognitoBasicAuthenticator: HBAuthenticator {
}

/// Authenticator for Cognito username and password
struct CognitoBasicSRPAuthenticator: HBAuthenticator {
struct CognitoBasicSRPAuthenticator: AuthenticatorMiddleware {
typealias Context = AuthCognitoRequestContext
let cognitoAuthenticatable: CognitoAuthenticatable

func authenticate(request: HBRequest, context: AuthCognitoRequestContext) async throws -> CognitoAuthenticateResponse? {
func authenticate(request: Request, context: AuthCognitoRequestContext) async throws -> CognitoAuthenticateResponse? {
guard let basic = request.headers.basic else { return nil }
return try? await self.cognitoAuthenticatable.authenticateSRP(
username: basic.username,
Expand All @@ -36,11 +36,11 @@ struct CognitoBasicSRPAuthenticator: HBAuthenticator {
}

/// Authenticator for Cognito access tokens
struct CognitoAccessAuthenticator: HBAuthenticator {
struct CognitoAccessAuthenticator: AuthenticatorMiddleware {
typealias Context = AuthCognitoRequestContext
let cognitoAuthenticatable: CognitoAuthenticatable

func authenticate(request: HBRequest, context: AuthCognitoRequestContext) async throws -> CognitoAccessToken? {
func authenticate(request: Request, context: AuthCognitoRequestContext) async throws -> CognitoAccessToken? {
guard let bearer = request.headers.bearer else { return nil }
return try? await self.cognitoAuthenticatable.authenticate(accessToken: bearer.token)
}
Expand All @@ -49,11 +49,11 @@ struct CognitoAccessAuthenticator: HBAuthenticator {
/// Authenticator for Cognito id tokens. Can use this to extract information from Id Token into Payload struct. The list of standard list of claims found in an id token are
/// detailed in the [OpenID spec] (https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) . Your `Payload` type needs
/// to decode using these tags, plus the AWS specific "cognito:username" tag and any custom tags you have setup for the user pool.
struct CognitoIdAuthenticator<Payload: HBAuthenticatable & Codable>: HBAuthenticator {
struct CognitoIdAuthenticator<Payload: Authenticatable & Codable>: AuthenticatorMiddleware {
typealias Context = AuthCognitoRequestContext
let cognitoAuthenticatable: CognitoAuthenticatable

func authenticate(request: HBRequest, context: AuthCognitoRequestContext) async throws -> Payload? {
func authenticate(request: Request, context: AuthCognitoRequestContext) async throws -> Payload? {
guard let bearer = request.headers.bearer else { return nil }
return try? await self.cognitoAuthenticatable.authenticate(idToken: bearer.token)
}
Expand Down
5 changes: 2 additions & 3 deletions auth-cognito/Sources/App/Models/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import Hummingbird
import HummingbirdAuth
import SotoCognitoAuthenticationKit

struct User: HBResponseCodable & HBAuthenticatable {
struct User: ResponseCodable & Authenticatable {
let username: String
let email: String

private enum CodingKeys: String, CodingKey {
case username = "cognito:username"
case email = "email"
case email
}
}

10 changes: 5 additions & 5 deletions auth-cognito/Sources/App/RequestContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import NIOCore
import SotoCognitoAuthenticationKit

/// Request context
struct AuthCognitoRequestContext: HBAuthRequestContext, HBRemoteAddressRequestContext, HBRouterRequestContext {
var coreContext: HBCoreRequestContext
struct AuthCognitoRequestContext: AuthRequestContext, RemoteAddressRequestContext, RouterRequestContext {
var coreContext: CoreRequestContext
/// required by authentication framework
var auth: HBLoginCache
var auth: LoginCache
/// required by result builder router
var routerContext: HBRouterBuilderContext
var routerContext: RouterBuilderContext
let channel: Channel?
/// Connected host address
var remoteAddress: SocketAddress? {
Expand All @@ -30,7 +30,7 @@ struct AuthCognitoRequestContext: HBAuthRequestContext, HBRemoteAddressRequestCo

/// Wrapper for cognito context data
struct HBCognitoContextData: CognitoContextData {
let request: HBRequest
let request: Request
let context: AuthCognitoRequestContext

public var contextData: CognitoIdentityProvider.ContextDataType? {
Expand Down
5 changes: 2 additions & 3 deletions auth-cognito/Tests/AppTests/AppTests.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import App
import Hummingbird
import HummingbirdXCT
import HummingbirdTesting
import XCTest

final class AppTests: XCTestCase {
}
final class AppTests: XCTestCase {}
Loading

0 comments on commit 08e2074

Please sign in to comment.