Files
plainleaf/server/crypto_test.go
T
Zef HemelandGitHub a524c64884 Go backend (#1555)
* Replaces old Deno server with a Go implementation
* Restructured the code base accordingly
2025-09-19 13:23:20 +02:00

260 lines
6.9 KiB
Go

package server
import (
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCreateAuthenticator_NewFile(t *testing.T) {
tmpDir := t.TempDir()
authFile := filepath.Join(tmpDir, "auth.json")
authOptions := &AuthOptions{
User: "testuser",
Pass: "testpass",
LockoutTime: 300,
LockoutLimit: 5,
}
auth, err := CreateAuthenticator(authFile, authOptions)
assert.NoError(t, err, "Should create new authenticator without error")
assert.NotNil(t, auth, "Authenticator should not be nil")
assert.NotEmpty(t, auth.SecretKey, "Secret key should be generated")
assert.NotEmpty(t, auth.AuthHash, "Auth hash should be generated")
// Verify file was created
_, err = os.Stat(authFile)
assert.False(t, os.IsNotExist(err), "Auth file should be created")
}
func TestCreateAuthenticator_ExistingFile(t *testing.T) {
tmpDir := t.TempDir()
authFile := filepath.Join(tmpDir, "auth.json")
// Create initial authenticator
authOptions := &AuthOptions{
User: "testuser",
Pass: "testpass",
LockoutTime: 300,
LockoutLimit: 5,
}
auth1, err := CreateAuthenticator(authFile, authOptions)
require.NoError(t, err)
originalKey := auth1.SecretKey
// Load from existing file with same options
auth2, err := CreateAuthenticator(authFile, authOptions)
assert.NoError(t, err, "Should load existing authenticator without error")
assert.Equal(t, originalKey, auth2.SecretKey, "Secret key should remain the same")
}
func TestCreateAuthenticator_AuthOptionsChanged(t *testing.T) {
tmpDir := t.TempDir()
authFile := filepath.Join(tmpDir, "auth.json")
// Create initial authenticator
authOptions1 := &AuthOptions{
User: "testuser",
Pass: "testpass",
LockoutTime: 300,
LockoutLimit: 5,
}
auth1, err := CreateAuthenticator(authFile, authOptions1)
require.NoError(t, err)
originalKey := auth1.SecretKey
// Load with different auth options
authOptions2 := &AuthOptions{
User: "testuser",
Pass: "newpass", // Changed password
LockoutTime: 300,
LockoutLimit: 5,
}
auth2, err := CreateAuthenticator(authFile, authOptions2)
assert.NoError(t, err, "Should load authenticator with changed options")
assert.NotEqual(t, originalKey, auth2.SecretKey, "Secret key should change when auth options change")
}
func TestAuthenticator_CreateJWT(t *testing.T) {
tmpDir := t.TempDir()
authFile := filepath.Join(tmpDir, "auth.json")
authOptions := &AuthOptions{
User: "testuser",
Pass: "testpass",
LockoutTime: 300,
LockoutLimit: 5,
}
auth, err := CreateAuthenticator(authFile, authOptions)
require.NoError(t, err)
payload := map[string]any{
"user": "testuser",
"role": "admin",
}
token, err := auth.CreateJWT(payload)
assert.NoError(t, err, "Should create JWT without error")
assert.NotEmpty(t, token, "Token should not be empty")
// Verify token structure (should have 3 parts separated by dots)
parts := len([]rune(token))
assert.Greater(t, parts, 0, "Token should not be empty")
}
func TestAuthenticator_CreateJWT_WithExpiry(t *testing.T) {
tmpDir := t.TempDir()
authFile := filepath.Join(tmpDir, "auth.json")
authOptions := &AuthOptions{
User: "testuser",
Pass: "testpass",
LockoutTime: 300,
LockoutLimit: 5,
}
auth, err := CreateAuthenticator(authFile, authOptions)
require.NoError(t, err)
payload := map[string]any{
"user": "testuser",
}
token, err := auth.CreateJWT(payload, 3600) // 1 hour expiry
assert.NoError(t, err, "Should create JWT with expiry without error")
assert.NotEmpty(t, token, "Token should not be empty")
// Verify the token and check expiry
claims, err := auth.VerifyAndDecodeJWT(token)
assert.NoError(t, err, "Should verify token")
exp, ok := claims["exp"]
assert.True(t, ok, "Token should have expiry claim")
assert.NotNil(t, exp, "Expiry should not be nil")
}
func TestAuthenticator_VerifyAndDecodeJWT(t *testing.T) {
tmpDir := t.TempDir()
authFile := filepath.Join(tmpDir, "auth.json")
authOptions := &AuthOptions{
User: "testuser",
Pass: "testpass",
LockoutTime: 300,
LockoutLimit: 5,
}
auth, err := CreateAuthenticator(authFile, authOptions)
require.NoError(t, err)
payload := map[string]any{
"user": "testuser",
"role": "admin",
"id": 123,
}
token, err := auth.CreateJWT(payload)
require.NoError(t, err)
// Verify and decode the token
claims, err := auth.VerifyAndDecodeJWT(token)
assert.NoError(t, err, "Should verify and decode JWT without error")
assert.Equal(t, "testuser", claims["user"], "Should preserve user claim")
assert.Equal(t, "admin", claims["role"], "Should preserve role claim")
assert.Equal(t, float64(123), claims["id"], "Should preserve id claim")
}
func TestAuthenticator_VerifyAndDecodeJWT_InvalidToken(t *testing.T) {
tmpDir := t.TempDir()
authFile := filepath.Join(tmpDir, "auth.json")
authOptions := &AuthOptions{
User: "testuser",
Pass: "testpass",
LockoutTime: 300,
LockoutLimit: 5,
}
auth, err := CreateAuthenticator(authFile, authOptions)
require.NoError(t, err)
// Test invalid token
_, err = auth.VerifyAndDecodeJWT("invalid.token.here")
assert.Error(t, err, "Should return error for invalid token")
// Test empty token
_, err = auth.VerifyAndDecodeJWT("")
assert.Error(t, err, "Should return error for empty token")
}
func TestAuthenticator_VerifyAndDecodeJWT_ExpiredToken(t *testing.T) {
tmpDir := t.TempDir()
authFile := filepath.Join(tmpDir, "auth.json")
authOptions := &AuthOptions{
User: "testuser",
Pass: "testpass",
LockoutTime: 300,
LockoutLimit: 5,
}
auth, err := CreateAuthenticator(authFile, authOptions)
require.NoError(t, err)
payload := map[string]any{
"user": "testuser",
}
// Create token with 1 second expiry
token, err := auth.CreateJWT(payload, 1)
require.NoError(t, err)
// Wait for token to expire
time.Sleep(2 * time.Second)
// Try to verify expired token
_, err = auth.VerifyAndDecodeJWT(token)
assert.Error(t, err, "Should return error for expired token")
}
func TestAuthenticator_VerifyAndDecodeJWT_WrongKey(t *testing.T) {
tmpDir := t.TempDir()
authFile1 := filepath.Join(tmpDir, "auth1.json")
authFile2 := filepath.Join(tmpDir, "auth2.json")
authOptions := &AuthOptions{
User: "testuser",
Pass: "testpass",
LockoutTime: 300,
LockoutLimit: 5,
}
// Create two different authenticators (different keys)
auth1, err := CreateAuthenticator(authFile1, authOptions)
require.NoError(t, err)
auth2, err := CreateAuthenticator(authFile2, authOptions)
require.NoError(t, err)
payload := map[string]any{
"user": "testuser",
}
// Create token with first authenticator
token, err := auth1.CreateJWT(payload)
require.NoError(t, err)
// Try to verify with second authenticator (different key)
_, err = auth2.VerifyAndDecodeJWT(token)
assert.Error(t, err, "Should return error when verifying token with wrong key")
}