Fix tests
This commit is contained in:
@@ -1,8 +1,7 @@
|
|||||||
require "test_helper"
|
require "test_helper"
|
||||||
|
|
||||||
# Note: This file tests API endpoints directly (post/get/assert_response)
|
# Advanced integration tests for Forward Auth API
|
||||||
# so it should use IntegrationTest, not SystemTestCase
|
class ForwardAuthAdvancedTest < ActionDispatch::IntegrationTest
|
||||||
class ForwardAuthSystemTest < ActionDispatch::IntegrationTest
|
|
||||||
setup do
|
setup do
|
||||||
@user = users(:one)
|
@user = users(:one)
|
||||||
@admin_user = users(:two)
|
@admin_user = users(:two)
|
||||||
@@ -54,45 +54,39 @@ class WebauthnSecurityTest < ActionDispatch::IntegrationTest
|
|||||||
end
|
end
|
||||||
|
|
||||||
# ====================
|
# ====================
|
||||||
# USER HANDLE BINDING TESTS
|
# USER HANDLE SECURITY TESTS
|
||||||
# ====================
|
# ====================
|
||||||
|
|
||||||
test "user handle is properly bound to WebAuthn credential" do
|
test "WebAuthn challenge includes authenticated user's handle (not another user's)" do
|
||||||
user = User.create!(email_address: "webauthn_handle_test@example.com", password: "password123")
|
# Create two users
|
||||||
|
user_a = User.create!(email_address: "usera@example.com", password: "password123")
|
||||||
|
user_b = User.create!(email_address: "userb@example.com", password: "password123")
|
||||||
|
|
||||||
# Create a WebAuthn credential with user handle
|
# Generate handles for both users
|
||||||
user_handle = SecureRandom.uuid
|
handle_a = user_a.webauthn_user_handle
|
||||||
credential = user.webauthn_credentials.create!(
|
handle_b = user_b.webauthn_user_handle
|
||||||
external_id: Base64.urlsafe_encode64("fake_credential_id"),
|
|
||||||
public_key: Base64.urlsafe_encode64("fake_public_key"),
|
|
||||||
sign_count: 0,
|
|
||||||
nickname: "Test Key",
|
|
||||||
user_handle: user_handle
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify user handle is associated with the credential
|
# Sign in as User A
|
||||||
assert_equal user_handle, credential.user_handle
|
post signin_path, params: {email_address: user_a.email_address, password: "password123"}
|
||||||
|
assert_response :redirect
|
||||||
|
|
||||||
user.destroy
|
# Request WebAuthn challenge (for registration)
|
||||||
end
|
post webauthn_challenge_path, params: {email: user_a.email_address}
|
||||||
|
assert_response :success
|
||||||
|
|
||||||
test "WebAuthn authentication validates user handle" do
|
# Parse the JSON response
|
||||||
user = User.create!(email_address: "webauthn_handle_auth_test@example.com", password: "password123")
|
challenge_data = JSON.parse(response.body)
|
||||||
|
|
||||||
user_handle = SecureRandom.uuid
|
# SECURITY: Verify challenge includes User A's handle
|
||||||
user.webauthn_credentials.create!(
|
assert challenge_data.key?("user")
|
||||||
external_id: Base64.urlsafe_encode64("fake_credential_id"),
|
assert_equal handle_a, challenge_data["user"]["id"], "Challenge should include authenticated user's handle"
|
||||||
public_key: Base64.urlsafe_encode64("fake_public_key"),
|
assert_equal user_a.email_address, challenge_data["user"]["name"]
|
||||||
sign_count: 0,
|
|
||||||
nickname: "Test Key",
|
|
||||||
user_handle: user_handle
|
|
||||||
)
|
|
||||||
|
|
||||||
# Sign in with WebAuthn
|
# SECURITY: Verify challenge does NOT include User B's handle
|
||||||
# The implementation should verify the user handle matches
|
assert_not_equal handle_b, challenge_data["user"]["id"], "Challenge should NOT include another user's handle"
|
||||||
# This test documents the expected behavior
|
|
||||||
|
|
||||||
user.destroy
|
user_a.destroy
|
||||||
|
user_b.destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
# ====================
|
# ====================
|
||||||
@@ -316,7 +310,7 @@ class WebauthnSecurityTest < ActionDispatch::IntegrationTest
|
|||||||
|
|
||||||
test "WebAuthn can be required for authentication" do
|
test "WebAuthn can be required for authentication" do
|
||||||
user = User.create!(email_address: "webauthn_required_test@example.com", password: "password123")
|
user = User.create!(email_address: "webauthn_required_test@example.com", password: "password123")
|
||||||
user.update!(webauthn_enabled: true)
|
user.update!(webauthn_required: true)
|
||||||
|
|
||||||
# Sign in with password should still work
|
# Sign in with password should still work
|
||||||
post signin_path, params: {email_address: "webauthn_required_test@example.com", password: "password123"}
|
post signin_path, params: {email_address: "webauthn_required_test@example.com", password: "password123"}
|
||||||
@@ -329,7 +323,7 @@ class WebauthnSecurityTest < ActionDispatch::IntegrationTest
|
|||||||
|
|
||||||
test "WebAuthn can be used for passwordless authentication" do
|
test "WebAuthn can be used for passwordless authentication" do
|
||||||
user = User.create!(email_address: "webauthn_passwordless_test@example.com", password: "password123")
|
user = User.create!(email_address: "webauthn_passwordless_test@example.com", password: "password123")
|
||||||
user.update!(webauthn_enabled: true)
|
user.update!(webauthn_required: true)
|
||||||
|
|
||||||
user.webauthn_credentials.create!(
|
user.webauthn_credentials.create!(
|
||||||
external_id: Base64.urlsafe_encode64("passwordless_credential"),
|
external_id: Base64.urlsafe_encode64("passwordless_credential"),
|
||||||
|
|||||||
@@ -319,4 +319,35 @@ class UserTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
# Note: parsed_backup_codes method and legacy tests removed
|
# Note: parsed_backup_codes method and legacy tests removed
|
||||||
# All users now use BCrypt hashes stored in JSON column
|
# All users now use BCrypt hashes stored in JSON column
|
||||||
|
|
||||||
|
# WebAuthn user handle tests
|
||||||
|
test "generates and persists unique webauthn user handle" do
|
||||||
|
user = User.create!(email_address: "webauthn_test@example.com", password: "password123")
|
||||||
|
|
||||||
|
# User should not have a webauthn_id initially
|
||||||
|
assert_nil user.webauthn_id
|
||||||
|
|
||||||
|
# Getting the user handle should generate and persist it
|
||||||
|
handle = user.webauthn_user_handle
|
||||||
|
assert_not_nil handle
|
||||||
|
assert_equal 86, handle.length # Base64-urlsafe-encoded 64 bytes (no padding)
|
||||||
|
|
||||||
|
# Reload and verify it was persisted
|
||||||
|
user.reload
|
||||||
|
assert_equal handle, user.webauthn_id
|
||||||
|
|
||||||
|
# Subsequent calls should return the same handle (stable)
|
||||||
|
assert_equal handle, user.webauthn_user_handle
|
||||||
|
end
|
||||||
|
|
||||||
|
test "webauthn user handles are unique across users" do
|
||||||
|
user1 = User.create!(email_address: "user1@example.com", password: "password123")
|
||||||
|
user2 = User.create!(email_address: "user2@example.com", password: "password123")
|
||||||
|
|
||||||
|
handle1 = user1.webauthn_user_handle
|
||||||
|
handle2 = user2.webauthn_user_handle
|
||||||
|
|
||||||
|
# Each user should get a unique handle
|
||||||
|
assert_not_equal handle1, handle2
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user