All Products
Search
Document Center

Alibaba Cloud Service Mesh:Develop a gRPC-based custom authorization service

Last Updated:Mar 11, 2026

When built-in RBAC policies are not flexible enough for your authorization requirements, Service Mesh (ASM) lets you delegate authorization decisions to an external service through Envoy's ext_authz filter. This topic explains how to build a gRPC-based authorization service that receives structured check requests from Envoy and returns allow or deny decisions.

For the HTTP-based approach, see Develop an HTTP-based custom authorization service.

How it works

When a sidecar proxy intercepts an incoming request, it forwards the request attributes to your external authorization service over gRPC. The authorization service inspects these attributes -- headers, source identity, request path, and more -- and returns an allow or deny decision. The sidecar proxy enforces this decision before forwarding the request upstream.

Client --> Sidecar Proxy --gRPC CheckRequest--> Authorization Service
                |                                       |
                |  <------- CheckResponse (allow/deny) --
                |
           (if allowed) --> Upstream Service

Unlike the HTTP-based approach, a gRPC-based authorization service receives a structured CheckRequest proto message rather than a raw HTTP request. All request headers and metadata are available directly in the proto fields, with no additional header-forwarding configuration required.

Prerequisites

Before you begin, make sure you have:

  • An ASM instance with an associated ACK cluster

  • Familiarity with gRPC and Protocol Buffers

  • A Go development environment (the examples in this topic use Go)

The AuthorizationServer gRPC API

Implement the Envoy AuthorizationServer interface, which defines a single Check method:

type AuthorizationServer interface {
	// Performs authorization check based on the attributes associated with the
	// incoming request, and returns status `OK` or not `OK`.
	Check(context.Context, *CheckRequest) (*CheckResponse, error)
}

Check receives a CheckRequest containing request attributes from Envoy and returns a CheckResponse with the authorization decision.

For the complete field reference of CheckRequest, see the Envoy <code data-tag="code" class="inline-code___exakR" id="code_65a45c82">ext_authz</code> proto definition or the go-control-plane API docs.

Build the authorization service

ASM is compatible with open-source Istio. The Istio project provides a reference implementation that handles both HTTP and gRPC authorization protocols. The gRPC logic is defined in the extAuthzServerV3 struct:

type extAuthzServerV3 struct{}
func (s *extAuthzServerV3) Check(_ context.Context, request *authv3.CheckRequest) (*authv3.CheckResponse, error)
func (s *extAuthzServerV3) allow(request *authv3.CheckRequest) *authv3.CheckResponse
func (s *extAuthzServerV3) deny(request *authv3.CheckRequest) *authv3.CheckResponse
func (s *extAuthzServerV3) logRequest(allow string, request *authv3.CheckRequest)

This struct implements AuthorizationServer. The four methods serve these purposes:

MethodPurpose
CheckCore logic -- inspects request attributes and returns allow or deny
allowBuilds a CheckResponse that permits the request
denyBuilds a CheckResponse that rejects the request
logRequestLogs the authorization decision for debugging

The Check function

Check contains the authorization decision logic. The reference implementation uses two criteria:

  1. Header check: If the request contains a specific header (checkHeader), the function compares its value against allowedValue.

  2. Identity check: If the header is absent, the function checks whether the source identity (attrs.Source.Principal) matches a preset service account.

// Check implements gRPC v3 check request.
func (s *extAuthzServerV3) Check(_ context.Context, request *authv3.CheckRequest) (*authv3.CheckResponse, error) {
	attrs := request.GetAttributes()

	// Determine whether to allow or deny the request.
	allow := false
	checkHeaderValue, contains := attrs.GetRequest().GetHttp().GetHeaders()[checkHeader]
	if contains {
		allow = checkHeaderValue == allowedValue
	} else {
		allow = attrs.Source != nil && strings.HasSuffix(attrs.Source.Principal, "/sa/"+*serviceAccount)
	}

	if allow {
		return s.allow(request), nil
	}

	return s.deny(request), nil
}

Decision flow:

  1. Extract request attributes from CheckRequest.

  2. Look up checkHeader in the HTTP headers.

  3. If the header exists and its value equals allowedValue, allow the request.

  4. If the header is absent, check whether the mTLS source identity (Source.Principal) ends with /sa/<service-account-name>.

  5. Return the corresponding allow or deny response.

API version

Envoy has deprecated V2-related APIs. Implement only the V3 gRPC API as shown in the Check function signature above. The extAuthzServerV2 struct in the Istio sample is retained for backward compatibility only.

Register and activate the authorization service

After you deploy the custom authorization service to your ACK cluster:

  1. Open the ASM console and navigate to the Define Custom Authorization Service page.

  2. Register the gRPC-based authorization service.

  3. Create or update an authorization policy to route authorization checks from specific sidecar proxies to your service.

For step-by-step instructions, see Implement custom authorization by using the gRPC protocol.

What to read next