Skip to content

Commit 119e6dc

Browse files
authored
fix: skip inline auth check in GetTenantProvisioningStatus when no claims present (#1297)
GetTenantProvisioningStatus had an inline auth check that returned codes.Unauthenticated when no claims existed in context. In the unified binary (dev/CI mode) without auth middleware, claims are never present, so this endpoint always returned Unauthenticated. The frontend's global 401 handler (added in #1280) caught this and called logout(), redirecting all tenant detail page E2E tests to the login screen. The fix skips the authorization check when no claims are in context, consistent with other tenant endpoints like RetrieveTenant. Auth enforcement is handled by middleware when configured. Co-authored-by: Ben Coombs <bjcoombs@users.noreply.github.com>
1 parent 192de5e commit 119e6dc

2 files changed

Lines changed: 24 additions & 25 deletions

File tree

services/tenant/service/grpc_service.go

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -583,31 +583,30 @@ func (s *Service) GetTenantProvisioningStatus(ctx context.Context, req *pb.GetTe
583583
s.logger.Debug("getting tenant provisioning status",
584584
"tenant_id", req.TenantId)
585585

586-
// Authorization check - must be performed before any business logic.
586+
// Authorization check - when auth middleware is configured, enforce tenant isolation.
587+
// When no claims are present (e.g., unified binary without auth middleware), skip
588+
// authorization consistent with other tenant endpoints like RetrieveTenant.
587589
claims, ok := auth.GetClaimsFromContext(ctx)
588-
if !ok {
589-
s.logger.Warn("provisioning status query attempted without authentication claims")
590-
return nil, status.Error(codes.Unauthenticated, "authentication required")
591-
}
592-
593-
// Check authorization: either tenant-scoped access OR platform admin role
594-
hasAdminRole := claims.HasRole(auth.RolePlatformAdmin) || claims.HasRole(auth.RoleSuperAdmin)
595-
hasTenantAccess := claims.HasTenantID() && claims.TenantID == req.TenantId
590+
if ok {
591+
// Check authorization: either tenant-scoped access OR platform admin role
592+
hasAdminRole := claims.HasRole(auth.RolePlatformAdmin) || claims.HasRole(auth.RoleSuperAdmin)
593+
hasTenantAccess := claims.HasTenantID() && claims.TenantID == req.TenantId
594+
595+
if !hasAdminRole && !hasTenantAccess {
596+
s.logger.Warn("unauthorized provisioning status query attempt",
597+
"user_id", claims.UserID,
598+
"requested_tenant", req.TenantId,
599+
"user_tenant", claims.TenantID,
600+
"roles", claims.Roles)
601+
return nil, status.Error(codes.PermissionDenied, "access denied: must be tenant owner or platform administrator")
602+
}
596603

597-
if !hasAdminRole && !hasTenantAccess {
598-
s.logger.Warn("unauthorized provisioning status query attempt",
604+
s.logger.Debug("provisioning status query authorized",
599605
"user_id", claims.UserID,
600-
"requested_tenant", req.TenantId,
601-
"user_tenant", claims.TenantID,
602-
"roles", claims.Roles)
603-
return nil, status.Error(codes.PermissionDenied, "access denied: must be tenant owner or platform administrator")
606+
"tenant_id", req.TenantId,
607+
"admin_access", hasAdminRole)
604608
}
605609

606-
s.logger.Debug("provisioning status query authorized",
607-
"user_id", claims.UserID,
608-
"tenant_id", req.TenantId,
609-
"admin_access", hasAdminRole)
610-
611610
// Validate tenant ID
612611
tenantID, err := tenant.NewTenantID(req.TenantId)
613612
if err != nil {

services/tenant/service/grpc_service_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,20 +1560,20 @@ func TestGetTenantProvisioningStatus_MissingClaims(t *testing.T) {
15601560
svc, _, cleanup := setupTest(t)
15611561
defer cleanup()
15621562

1563-
// Context without claims
1563+
// Context without claims - should skip authorization (consistent with
1564+
// other tenant endpoints when running without auth middleware).
15641565
ctx := context.Background()
15651566

1566-
// Execute
1567+
// Execute - request proceeds without auth, but tenant doesn't exist
15671568
resp, err := svc.GetTenantProvisioningStatus(ctx, &pb.GetTenantProvisioningStatusRequest{
15681569
TenantId: "test_tenant",
15691570
})
15701571

1571-
// Assert
1572+
// Assert - should get NotFound (not Unauthenticated) since auth is skipped
15721573
require.Error(t, err)
15731574
st, ok := status.FromError(err)
15741575
require.True(t, ok, "error should be a gRPC status")
1575-
assert.Equal(t, codes.Unauthenticated, st.Code())
1576-
assert.Contains(t, st.Message(), "authentication required")
1576+
assert.Equal(t, codes.NotFound, st.Code())
15771577
assert.Nil(t, resp)
15781578
}
15791579

0 commit comments

Comments
 (0)