github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/auth/presharedkey.go (about)

     1  package auth
     2  
     3  import (
     4  	"context"
     5  	"crypto/subtle"
     6  
     7  	grpcauth "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
     8  	"google.golang.org/grpc/codes"
     9  	"google.golang.org/grpc/status"
    10  )
    11  
    12  const (
    13  	errInvalidPresharedKey = "invalid preshared key: %s"
    14  	errMissingPresharedKey = "missing preshared key"
    15  )
    16  
    17  var errInvalidToken = "invalid token"
    18  
    19  // MustRequirePresharedKey requires that gRPC requests have a Bearer Token value
    20  // equivalent to one of the provided preshared key(s).
    21  func MustRequirePresharedKey(presharedKeys []string) grpcauth.AuthFunc {
    22  	if len(presharedKeys) == 0 {
    23  		panic("RequirePresharedKey was given an empty preshared keys slice")
    24  	}
    25  
    26  	for _, presharedKey := range presharedKeys {
    27  		if len(presharedKey) == 0 {
    28  			panic("RequirePresharedKey was given an empty preshared key")
    29  		}
    30  	}
    31  
    32  	return func(ctx context.Context) (context.Context, error) {
    33  		token, err := grpcauth.AuthFromMD(ctx, "bearer")
    34  		if err != nil {
    35  			return nil, status.Errorf(codes.Unauthenticated, errInvalidPresharedKey, err.Error())
    36  		}
    37  
    38  		if token == "" {
    39  			return nil, status.Errorf(codes.Unauthenticated, errMissingPresharedKey)
    40  		}
    41  
    42  		for _, presharedKey := range presharedKeys {
    43  			if match := subtle.ConstantTimeCompare([]byte(presharedKey), []byte(token)); match == 1 {
    44  				return ctx, nil
    45  			}
    46  		}
    47  
    48  		return nil, status.Errorf(codes.PermissionDenied, errInvalidPresharedKey, errInvalidToken)
    49  	}
    50  }