package authn import ( "encoding/base64" "errors" "testing" "time" "sourcecraft.dev/bigbes/sr-ht-core/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) } }) } }