60 lines
1.7 KiB
Elixir
60 lines
1.7 KiB
Elixir
alias Towerops.Accounts
|
|
alias Towerops.Accounts.User
|
|
|
|
# Simulate enrollment flow
|
|
secret = Accounts.generate_totp_secret()
|
|
user = %User{email: "test@example.com"}
|
|
|
|
IO.puts("=== TOTP Enrollment Flow Test ===")
|
|
IO.puts("")
|
|
IO.puts("1. Generated secret:")
|
|
IO.puts(" Bytes: #{byte_size(secret)}")
|
|
IO.puts(" Type: #{inspect(:io_lib.printable_list(secret))}")
|
|
|
|
# Generate URI (what goes in QR code)
|
|
uri = Accounts.generate_totp_uri(user, secret)
|
|
IO.puts("")
|
|
IO.puts("2. Generated URI:")
|
|
IO.puts(" #{uri}")
|
|
|
|
# Extract the Base32 secret from the URI
|
|
case Regex.run(~r/secret=([A-Z2-7]+)/, uri) do
|
|
[_, base32] ->
|
|
IO.puts("")
|
|
IO.puts("3. Extracted Base32 from URI:")
|
|
IO.puts(" Base32: #{base32}")
|
|
IO.puts(" Length: #{String.length(base32)} characters")
|
|
|
|
# Verify the Base32 can be decoded back
|
|
try do
|
|
decoded = Base.decode32!(base32, padding: false)
|
|
IO.puts("")
|
|
IO.puts("4. Decode verification:")
|
|
IO.puts(" Decoded bytes: #{byte_size(decoded)}")
|
|
IO.puts(" Matches original: #{decoded == secret}")
|
|
|
|
if decoded != secret do
|
|
IO.puts(" ERROR: Decoded secret doesn't match!")
|
|
IO.puts(" Original bytes: #{byte_size(secret)}")
|
|
IO.puts(" Decoded bytes: #{byte_size(decoded)}")
|
|
end
|
|
rescue
|
|
e ->
|
|
IO.puts("")
|
|
IO.puts("4. Decode ERROR: #{inspect(e)}")
|
|
end
|
|
|
|
_ ->
|
|
IO.puts("")
|
|
IO.puts("ERROR: Failed to extract Base32 from URI")
|
|
end
|
|
|
|
# Test verification
|
|
current_time = System.system_time(:second)
|
|
code = NimbleTOTP.verification_code(secret, time: current_time)
|
|
valid = Accounts.verify_totp(secret, code)
|
|
|
|
IO.puts("")
|
|
IO.puts("5. Verification test:")
|
|
IO.puts(" Generated code: #{code}")
|
|
IO.puts(" Validates: #{valid}")
|