coverage~bigbes/sr-ht-dolt3523280cauthn/grpc.go

Coverage
100.0% 15/15 statements
Δ
+0.0
Blob
ea6f24b
Uncovered nothing — every instrumented line ran
1 package authn
2
3 import (
4 "context"
5 "encoding/base64"
6 "fmt"
7 "strings"
8
9 "sourcecraft.dev/bigbes/sr-ht-core/auth"
10 )
11
12 // ResolveGRPCAuth resolves the caller from a remotesapi gRPC "authorization"
13 // metadata header, dispatching on its scheme exactly as the dolt client sends
14 // it (see dolt's grpc_dial_provider):
15 //
16 // - "Basic <base64(user:pass)>" → ResolveBasic (meta personal access token);
17 // - "Bearer <jwt>" → ResolveDoltJWT (dolt keypair EdDSA JWT);
18 // - empty → (nil, nil): an anonymous request, which is
19 // valid for public clones.
20 //
21 // A malformed or unsupported header is a permanent rejection wrapping
22 // ErrInvalidToken. keys is only consulted for the Bearer path.
23 9 func ResolveGRPCAuth(ctx context.Context, authorizationHeader, expectedAud string, keys KeyStore) (*auth.AuthContext, error) {
24 9 if authorizationHeader == "" {
25 1 return nil, nil // anonymous
26 1 }
27
28 8 scheme, value, ok := strings.Cut(authorizationHeader, " ")
29 8 if !ok || value == "" {
30 2 return nil, fmt.Errorf("%w: malformed authorization header", ErrInvalidToken)
31 2 }
32
33 6 switch strings.ToLower(scheme) {
34 4 case "basic":
35 4 raw, err := base64.StdEncoding.DecodeString(value)
36 4 if err != nil {
37 1 return nil, fmt.Errorf("%w: Basic credentials are not valid base64: %v", ErrInvalidToken, err)
38 1 }
39 3 username, password, ok := strings.Cut(string(raw), ":")
40 3 if !ok {
41 1 return nil, fmt.Errorf("%w: Basic credentials missing ':' separator", ErrInvalidToken)
42 1 }
43 2 return ResolveBasic(ctx, username, password)
44 1 case "bearer":
45 1 return ResolveDoltJWT(ctx, value, expectedAud, keys)
46 1 default:
47 1 return nil, fmt.Errorf("%w: unsupported authorization scheme %q", ErrInvalidToken, scheme)
48 }
49 }