diff --git a/bin/evening_detective_server b/bin/evening_detective_server index 6185fec..e1284d7 100755 Binary files a/bin/evening_detective_server and b/bin/evening_detective_server differ diff --git a/internal/app/users_permissions_test.go b/internal/app/users_permissions_test.go index af96b55..9119f86 100644 --- a/internal/app/users_permissions_test.go +++ b/internal/app/users_permissions_test.go @@ -28,4 +28,13 @@ func TestGetPermissionsAllowsAnonymousUsers(t *testing.T) { if len(rsp.GetPermissions()) == 0 { t.Fatal("authenticated permissions are empty") } + + ctx = processor_jwt.ContextWithClaims(context.Background(), &processor_jwt.JWTClaims{Roles: []string{"admin"}}) + rsp, err = s.GetPermissions(ctx, &proto.GetPermissionsReq{}) + if err != nil { + t.Fatalf("GetPermissions() for admin error = %v", err) + } + if len(rsp.GetPermissions()) == 0 { + t.Fatal("admin permissions are empty") + } } diff --git a/internal/modules/processor_jwt/interceptor.go b/internal/modules/processor_jwt/interceptor.go index 366f38a..ae3c9d4 100644 --- a/internal/modules/processor_jwt/interceptor.go +++ b/internal/modules/processor_jwt/interceptor.go @@ -16,17 +16,19 @@ func NewAuthorizationInterceptor( processorJWT IProcessorJWT, ) grpc.UnaryServerInterceptor { return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { - if publicMethods[info.FullMethod] { - return handler(ctx, req) - } - md, ok := metadata.FromIncomingContext(ctx) if !ok { + if publicMethods[info.FullMethod] { + return handler(ctx, req) + } return nil, status.Errorf(codes.Unauthenticated, "metadata is not provided") } values := md.Get("authorization") if len(values) == 0 { + if publicMethods[info.FullMethod] { + return handler(ctx, req) + } return nil, status.Errorf(codes.Unauthenticated, "authorization token is not provided") } diff --git a/internal/modules/processor_jwt/interceptor_test.go b/internal/modules/processor_jwt/interceptor_test.go new file mode 100644 index 0000000..2fca5fc --- /dev/null +++ b/internal/modules/processor_jwt/interceptor_test.go @@ -0,0 +1,34 @@ +package processor_jwt + +import ( + "context" + "testing" + + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +type testProcessor struct{} + +func (testProcessor) GetClaims(string) (*JWTClaims, error) { + return &JWTClaims{Roles: []string{"admin"}}, nil +} + +func (testProcessor) GenerateAccessToken(int, string, []string) (string, error) { return "", nil } +func (testProcessor) GenerateRefreshToken(int) (string, error) { return "", nil } + +func TestAuthorizationInterceptorAddsClaimsToPublicMethod(t *testing.T) { + interceptor := NewAuthorizationInterceptor(map[string]bool{"/public": true}, testProcessor{}) + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "Bearer token")) + + _, err := interceptor(ctx, nil, &grpc.UnaryServerInfo{FullMethod: "/public"}, func(ctx context.Context, _ any) (any, error) { + claims, ok := ClaimsFromContext(ctx) + if !ok || !claims.HasRole("admin") { + t.Fatalf("claims = %#v, want admin claims", claims) + } + return nil, nil + }) + if err != nil { + t.Fatal(err) + } +}