~bigbes/sourcehut-dolt

ref: 5e555bac101b4a9a43a25941bc8c0fd9f8aecd03 sourcehut-dolt/authn/grpc_test.go -rw-r--r-- 2.8 KiB
5e555bac — Eugene Blikh authn: cookie, PAT, and dolt-JWT caller resolution 30 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package authn

import (
	"encoding/base64"
	"errors"
	"testing"
	"time"

	"git.sr.ht/~sircmpwn/core-go/auth"
	"github.com/dolthub/dolt/go/libraries/doltcore/creds"
)

func basicHeader(user, pass string) string {
	return "Basic " + base64.StdEncoding.EncodeToString([]byte(user+":"+pass))
}

func TestResolveGRPCAuth_Empty(t *testing.T) {
	withStubBackend(t, &stubBackend{})
	ac, err := ResolveGRPCAuth(testCtx(), "", testAud, &stubKeyStore{})
	if err != nil {
		t.Fatalf("empty header must be anonymous (no error), got %v", err)
	}
	if ac != nil {
		t.Fatalf("empty header must resolve to nil caller, got %+v", ac)
	}
}

func TestResolveGRPCAuth_Basic(t *testing.T) {
	withStubBackend(t, &stubBackend{users: map[string]auth.AuthContext{
		"bigbes": sampleUser(1, "bigbes", auth.USER_TYPE_USER),
	}})
	pat := forgePAT("bigbes", "", time.Now().Add(time.Hour))

	ac, err := ResolveGRPCAuth(testCtx(), basicHeader("bigbes", pat), testAud, &stubKeyStore{})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if ac == nil || ac.Username != "bigbes" {
		t.Fatalf("expected bigbes, got %+v", ac)
	}
}

func TestResolveGRPCAuth_Bearer(t *testing.T) {
	withStubBackend(t, &stubBackend{users: map[string]auth.AuthContext{
		"bigbes": sampleUser(1, "bigbes", auth.USER_TYPE_USER),
	}})
	priv, kid, ks := doltKeypair(t, "bigbes")
	raw := mintDoltJWT(t, priv, kid, testAud, creds.ClientIssuer, validSub(kid), time.Now().Add(30*time.Second))

	ac, err := ResolveGRPCAuth(testCtx(), "Bearer "+raw, testAud, ks)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if ac == nil || ac.Username != "bigbes" {
		t.Fatalf("expected bigbes, got %+v", ac)
	}
	if ac.AuthMethod != AuthMethodDoltKey {
		t.Fatalf("AuthMethod = %q, want %q", ac.AuthMethod, AuthMethodDoltKey)
	}
}

func TestResolveGRPCAuth_SchemeIsCaseInsensitive(t *testing.T) {
	withStubBackend(t, &stubBackend{users: map[string]auth.AuthContext{
		"bigbes": sampleUser(1, "bigbes", auth.USER_TYPE_USER),
	}})
	pat := forgePAT("bigbes", "", time.Now().Add(time.Hour))
	header := "basic " + base64.StdEncoding.EncodeToString([]byte("bigbes:"+pat))

	if _, err := ResolveGRPCAuth(testCtx(), header, testAud, &stubKeyStore{}); err != nil {
		t.Fatalf("lowercase scheme must work, got %v", err)
	}
}

func TestResolveGRPCAuth_Malformed(t *testing.T) {
	withStubBackend(t, &stubBackend{})
	cases := map[string]string{
		"no space":        "Basicdeadbeef",
		"bad base64":      "Basic !!!not-base64!!!",
		"no colon":        "Basic " + base64.StdEncoding.EncodeToString([]byte("nocolon")),
		"unknown scheme":  "Digest abcdef",
		"scheme no value": "Bearer ",
	}
	for name, header := range cases {
		t.Run(name, func(t *testing.T) {
			_, err := ResolveGRPCAuth(testCtx(), header, testAud, &stubKeyStore{})
			if !errors.Is(err, ErrInvalidToken) {
				t.Fatalf("expected ErrInvalidToken, got %v", err)
			}
		})
	}
}