1
0
mirror of https://github.com/H0llyW00dzZ/fiber2fa.git synced 2025-02-06 11:02:32 +00:00
fiber2fa/benchmark_test.go
H0llyW00dzZ 0d47e07cc0
Improve [HOTP & TOTP] Separate signature verification logic (#94)
- [+] refactor(otpverifier): separate signature verification logic and add GenerateToken method
- [+] feat(otpverifier): add support for verifying token without signature
- [+] test(otpverifier): add tests for missing signature and signature mismatch scenarios
2024-05-30 21:40:48 +07:00

401 lines
10 KiB
Go

// Copyright (c) 2024 H0llyW00dz All rights reserved.
//
// License: BSD 3-Clause License
package twofa_test
import (
"encoding/json"
"net/http/httptest"
"testing"
"time"
twofa "github.com/H0llyW00dzZ/fiber2fa"
otp "github.com/H0llyW00dzZ/fiber2fa/internal/otpverifier"
"github.com/bytedance/sonic"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
"github.com/gofiber/storage/memory/v2"
"github.com/xlzd/gotp"
)
func BenchmarkJSONSonicMiddlewareWithInvalidCookie(b *testing.B) {
// Set up the storage with an in-memory store for simplicity
store := memory.New()
secret := gotp.RandomSecret(16)
app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
c.Locals("sonic_benchmark", "sonic_benchmark1234")
return c.Next()
})
app.Use(twofa.New(twofa.Config{
Secret: secret,
Issuer: "gopher",
ContextKey: "sonic_benchmark",
CookieMaxAge: 86400,
Storage: store,
JSONMarshal: sonic.Marshal,
JSONUnmarshal: sonic.Unmarshal,
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Set(fiber.HeaderCookie, "twofa_cookie=invalid-cookie-value")
b.ResetTimer()
for i := 0; i < b.N; i++ {
resp, _ := app.Test(req)
utils.AssertEqual(b, fiber.StatusUnauthorized, resp.StatusCode)
}
}
func BenchmarkJSONSonicWithValid2FA(b *testing.B) {
// Set up the storage with an in-memory store for simplicity
store := memory.New()
secret := gotp.RandomSecret(16)
app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
c.Locals("sonic_benchmark", "sonic_benchmark1234")
return c.Next()
})
twoFAConfig := twofa.Config{
Secret: secret,
Issuer: "gopher",
ContextKey: "sonic_benchmark",
CookieMaxAge: 86400,
Storage: store,
JSONMarshal: sonic.Marshal,
JSONUnmarshal: sonic.Unmarshal,
TokenLookup: "query:token",
}
twoFAMiddleware := &twofa.Middleware{Config: &twoFAConfig}
app.Use(twoFAMiddleware.Handle)
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
// Generate a valid 2FA token
totp := otp.NewTOTPVerifier(otp.Config{
Secret: twoFAConfig.Secret,
})
token := totp.GenerateToken()
totp.Verify(token)
// Create a valid 2FA cookie
cookieValue := twoFAMiddleware.GenerateCookieValue(time.Now().Add(time.Duration(86400) * time.Second))
// Store the 2FA information in the storage
info := &twofa.Info{
ContextKey: "sonic_benchmark1234",
Secret: secret,
CookieValue: cookieValue,
ExpirationTime: time.Time{},
}
infoJSON, _ := twoFAConfig.JSONMarshal(info)
err := store.Set("sonic_benchmark1234", infoJSON, 0)
if err != nil {
b.Fatalf("Failed to store 2FA information: %v", err)
}
req := httptest.NewRequest(fiber.MethodGet, "/?token="+token, nil)
b.ResetTimer()
for i := 0; i < b.N; i++ {
resp, _ := app.Test(req)
utils.AssertEqual(b, fiber.StatusOK, resp.StatusCode)
}
}
func BenchmarkJSONSonicWithValidCookie(b *testing.B) {
// Set up the storage with an in-memory store for simplicity
store := memory.New()
secret := gotp.RandomSecret(16)
app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
c.Locals("sonic_benchmark", "sonic_benchmark1234")
return c.Next()
})
twoFAConfig := twofa.Config{
Secret: secret,
Issuer: "gopher",
ContextKey: "sonic_benchmark",
CookieMaxAge: 86400,
Storage: store,
JSONMarshal: sonic.Marshal,
JSONUnmarshal: sonic.Unmarshal,
TokenLookup: "query:token",
}
twoFAMiddleware := &twofa.Middleware{Config: &twoFAConfig}
app.Use(twoFAMiddleware.Handle)
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
// Generate a valid 2FA token
totp := otp.NewTOTPVerifier(otp.Config{
Secret: twoFAConfig.Secret,
})
token := totp.GenerateToken()
totp.Verify(token)
// Create a valid 2FA cookie
cookieValue := twoFAMiddleware.GenerateCookieValue(time.Now().Add(time.Duration(86400) * time.Second))
// Store the 2FA information in the storage
info := &twofa.Info{
ContextKey: "sonic_benchmark1234",
Secret: secret,
CookieValue: cookieValue,
ExpirationTime: time.Time{},
}
infoJSON, _ := twoFAConfig.JSONMarshal(info)
err := store.Set("sonic_benchmark1234", infoJSON, 0)
if err != nil {
b.Fatalf("Failed to store 2FA information: %v", err)
}
// Create a request with the valid cookie
req := httptest.NewRequest(fiber.MethodGet, "/?token="+token, nil)
req.Header.Set(fiber.HeaderCookie, twoFAConfig.CookieName+"="+cookieValue)
// Perform the initial request to generate and store the 2FA information
resp, err := app.Test(req)
if err != nil {
b.Fatalf("Failed to perform initial request: %v", err)
}
defer resp.Body.Close()
// Extract the generated cookie from the response
cookies := resp.Cookies()
for _, cookie := range cookies {
if cookie.Name == twoFAConfig.CookieName {
cookieValue = cookie.Value
break
}
}
if cookieValue == "" {
b.Fatalf("Failed to retrieve the generated cookie")
}
// Create a new request with the valid cookie
req = httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Set(fiber.HeaderCookie, twoFAConfig.CookieName+"="+cookieValue)
b.ResetTimer()
for i := 0; i < b.N; i++ {
resp, _ := app.Test(req)
utils.AssertEqual(b, fiber.StatusOK, resp.StatusCode)
}
}
func BenchmarkJSONStdLibraryMiddlewareWithInvalidCookie(b *testing.B) {
// Set up the storage with an in-memory store for simplicity
store := memory.New()
secret := gotp.RandomSecret(16)
app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
c.Locals("stdlibrary_benchmark", "stdlibrary_benchmark1234")
return c.Next()
})
app.Use(twofa.New(twofa.Config{
Secret: secret,
Issuer: "gopher",
ContextKey: "stdlibrary_benchmark",
CookieMaxAge: 86400,
Storage: store,
JSONMarshal: json.Marshal,
JSONUnmarshal: json.Unmarshal,
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Set(fiber.HeaderCookie, "twofa_cookie=invalid-cookie-value")
b.ResetTimer()
for i := 0; i < b.N; i++ {
resp, _ := app.Test(req)
utils.AssertEqual(b, fiber.StatusUnauthorized, resp.StatusCode)
}
}
func BenchmarkJSONStdLibraryMiddlewareWithValid2FA(b *testing.B) {
// Set up the storage with an in-memory store for simplicity
store := memory.New()
secret := gotp.RandomSecret(16)
app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
c.Locals("stdlibrary_benchmark", "stdlibrary_benchmark1234")
return c.Next()
})
twoFAConfig := twofa.Config{
Secret: secret,
Issuer: "gopher",
ContextKey: "stdlibrary_benchmark",
CookieMaxAge: 86400,
Storage: store,
JSONMarshal: json.Marshal,
JSONUnmarshal: json.Unmarshal,
TokenLookup: "query:token",
}
twoFAMiddleware := &twofa.Middleware{Config: &twoFAConfig}
app.Use(twoFAMiddleware.Handle)
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
// Generate a valid 2FA token
totp := otp.NewTOTPVerifier(otp.Config{
Secret: twoFAConfig.Secret,
})
token := totp.GenerateToken()
totp.Verify(token)
// Create a valid 2FA cookie
cookieValue := twoFAMiddleware.GenerateCookieValue(time.Now().Add(time.Duration(86400) * time.Second))
// Store the 2FA information in the storage
info := &twofa.Info{
ContextKey: "stdlibrary_benchmark1234",
Secret: secret,
CookieValue: cookieValue,
ExpirationTime: time.Time{},
}
infoJSON, _ := twoFAConfig.JSONMarshal(info)
err := store.Set("stdlibrary_benchmark1234", infoJSON, 0)
if err != nil {
b.Fatalf("Failed to store 2FA information: %v", err)
}
req := httptest.NewRequest(fiber.MethodGet, "/?token="+token, nil)
b.ResetTimer()
for i := 0; i < b.N; i++ {
resp, _ := app.Test(req)
utils.AssertEqual(b, fiber.StatusOK, resp.StatusCode)
}
}
func BenchmarkJSONStdLibraryWithValidCookie(b *testing.B) {
// Set up the storage with an in-memory store for simplicity
store := memory.New()
secret := gotp.RandomSecret(16)
app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
c.Locals("stdlibrary_benchmark", "stdlibrary_benchmark1234")
return c.Next()
})
twoFAConfig := twofa.Config{
Secret: secret,
Issuer: "gopher",
ContextKey: "stdlibrary_benchmark",
CookieMaxAge: 86400,
Storage: store,
JSONMarshal: json.Marshal,
JSONUnmarshal: json.Unmarshal,
TokenLookup: "query:token",
}
twoFAMiddleware := &twofa.Middleware{Config: &twoFAConfig}
app.Use(twoFAMiddleware.Handle)
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
// Generate a valid 2FA token
totp := otp.NewTOTPVerifier(otp.Config{
Secret: twoFAConfig.Secret,
})
token := totp.GenerateToken()
totp.Verify(token)
// Create a valid 2FA cookie
cookieValue := twoFAMiddleware.GenerateCookieValue(time.Now().Add(time.Duration(86400) * time.Second))
// Store the 2FA information in the storage
info := &twofa.Info{
ContextKey: "stdlibrary_benchmark1234",
Secret: secret,
CookieValue: cookieValue,
ExpirationTime: time.Time{},
}
infoJSON, _ := twoFAConfig.JSONMarshal(info)
err := store.Set("stdlibrary_benchmark1234", infoJSON, 0)
if err != nil {
b.Fatalf("Failed to store 2FA information: %v", err)
}
// Create a request with the valid cookie
req := httptest.NewRequest(fiber.MethodGet, "/?token="+token, nil)
req.Header.Set(fiber.HeaderCookie, twoFAConfig.CookieName+"="+cookieValue)
// Perform the initial request to generate and store the 2FA information
resp, err := app.Test(req)
if err != nil {
b.Fatalf("Failed to perform initial request: %v", err)
}
defer resp.Body.Close()
// Extract the generated cookie from the response
cookies := resp.Cookies()
for _, cookie := range cookies {
if cookie.Name == twoFAConfig.CookieName {
cookieValue = cookie.Value
break
}
}
if cookieValue == "" {
b.Fatalf("Failed to retrieve the generated cookie")
}
// Create a new request with the valid cookie
req = httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Set(fiber.HeaderCookie, twoFAConfig.CookieName+"="+cookieValue)
b.ResetTimer()
for i := 0; i < b.N; i++ {
resp, _ := app.Test(req)
utils.AssertEqual(b, fiber.StatusOK, resp.StatusCode)
}
}