auth_test.go
⎇
Raw
1package handler
2
3import "testing"
4
5// bcrypt hash of "test-password" at the minimum cost, so the test stays fast.
6const testHash = "$2a$04$6h5pthPxQs2muU4eCZjhReZlMvwf7XP9HUKCEubLMQZsR/84fHs0i"
7
8func TestVerifyPassword(t *testing.T) {
9 if !VerifyPassword(testHash, "test-password") {
10 t.Error("the right password did not verify")
11 }
12 for _, pw := range []string{"", "test-passwor", "test-password ", "Test-Password", testHash} {
13 if VerifyPassword(testHash, pw) {
14 t.Errorf("password %q verified against a hash of something else", pw)
15 }
16 }
17}
18
19func TestValidatePasswordHash(t *testing.T) {
20 if err := ValidatePasswordHash(testHash); err != nil {
21 t.Errorf("a valid hash was rejected: %v", err)
22 }
23 // htpasswd writes $2y$; the README tells operators to use it, so it has to work.
24 if err := ValidatePasswordHash("$2y$04$6h5pthPxQs2muU4eCZjhReZlMvwf7XP9HUKCEubLMQZsR/84fHs0i"); err != nil {
25 t.Errorf("a $2y$ hash was rejected: %v", err)
26 }
27
28 // Every one of these is a plausible misconfiguration that must fail at startup.
29 for name, encoded := range map[string]string{
30 "empty": "",
31 "plaintext": "test-password",
32 "argon2id": "$argon2id$v=19$m=4096,t=1,p=1$dmlkYXJjaGl2ZXRlc3QwMQ$+Y2TzOaB1vDgGkOgclcj+Q0xYIcRBZf5wh616yVaJCQ",
33 "truncated": "$2a$04$6h5pthPxQs2muU4eCZjhRe",
34 "no cost": "$2a$6h5pthPxQs2muU4eCZjhReZlMvwf7XP9HUKCEubLMQZsR/84fHs0i",
35 "bogus cost": "$2a$zz$6h5pthPxQs2muU4eCZjhReZlMvwf7XP9HUKCEubLMQZsR/84fHs0i",
36 // Accepted by bcrypt, but a login against it would take hours.
37 "absurd cost": "$2a$31$6h5pthPxQs2muU4eCZjhReZlMvwf7XP9HUKCEubLMQZsR/84fHs0i",
38 } {
39 if err := ValidatePasswordHash(encoded); err == nil {
40 t.Errorf("%s hash was accepted", name)
41 }
42 if VerifyPassword(encoded, "test-password") {
43 t.Errorf("%s hash verified a password", name)
44 }
45 }
46}
47
48func TestPublicPaths(t *testing.T) {
49 for _, path := range []string{"/login", "/healthz", "/static/style.css"} {
50 if !publicPath(path) {
51 t.Errorf("%s is guarded, so the login page cannot work", path)
52 }
53 }
54 for _, path := range []string{"/", "/library", "/queue", "/settings", "/media/item/x", "/logins"} {
55 if publicPath(path) {
56 t.Errorf("%s is reachable without a session", path)
57 }
58 }
59}
60