How does gRPC handle authentication and TLS?
Learn how gRPC secures calls with TLS channel credentials and per-call token authentication, including mutual TLS, metadata tokens, and interceptor validation.
Expected Interview Answer
gRPC secures the transport with TLS (via channel credentials) to encrypt and authenticate the connection, and layers per-call authentication on top using call credentials such as bearer tokens, OAuth2/JWT, or API keys carried in metadata; mutual TLS can additionally authenticate the client itself.
gRPC separates two credential types: channel credentials establish the secure connection (server TLS or mTLS), while call credentials attach identity to each RPC, typically as an Authorization metadata header. These compose via composite credentials so a channel can be both encrypted and per-call authenticated. Because gRPC runs over HTTP/2, TLS is the standard transport layer, and interceptors on client and server let you inject and verify tokens centrally rather than in every handler.
- Encrypted, tamper-resistant transport via TLS
- Server (and optionally client) identity verified with certificates
- Per-call identity through token-based call credentials
- Composable channel plus call credentials
- Centralized enforcement using interceptors
AI Mentor Explanation
Entering a Test match ground needs two checks: the stadium's sealed, guarded perimeter that keeps the venue secure, and your personal ticket scanned at the turnstile that proves who you are. gRPC security mirrors this — TLS channel credentials are the secured perimeter, while call credentials like a token are the ticket authenticating each individual request you make inside.
Step-by-Step Explanation
Step 1
Establish TLS channel credentials
The client connects using server certificates so the connection is encrypted and the server's identity is verified.
Step 2
Optionally enable mTLS
Provide a client certificate so the server also authenticates the client, giving mutual TLS.
Step 3
Attach call credentials
Add per-RPC identity such as an OAuth2/JWT bearer token in the Authorization metadata header.
Step 4
Compose credentials
Combine channel and call credentials into composite credentials so the channel is both secure and per-call authenticated.
Step 5
Verify with interceptors
Server interceptors read and validate the token metadata centrally, rejecting unauthenticated calls with UNAUTHENTICATED or PERMISSION_DENIED.
What Interviewer Expects
- Distinction between channel credentials and call credentials
- Understanding that TLS provides transport encryption and server authentication
- Knowledge of mutual TLS for client authentication
- How tokens travel in metadata and are validated by interceptors
- Which status codes signal auth failures (UNAUTHENTICATED, PERMISSION_DENIED)
Common Mistakes
- Using insecure channels in production instead of TLS
- Confusing authentication (who you are) with authorization (what you may do)
- Putting tokens in the message body instead of metadata
- Assuming TLS alone authenticates the individual caller without call credentials
- Validating tokens per handler instead of centrally via interceptors
Best Answer (HR Friendly)
“gRPC keeps communication safe in two ways: it uses TLS to encrypt the connection and confirm you're talking to the right server, and it checks a security token on each request to confirm who the caller is. Together they ensure data stays private and only trusted users can access a service.”
Code Example
import grpc
with open("ca.pem", "rb") as f:
channel_creds = grpc.ssl_channel_credentials(f.read())
# per-call credentials: attach a bearer token as metadata
call_creds = grpc.access_token_call_credentials("eyJ...jwt")
composite = grpc.composite_channel_credentials(channel_creds, call_creds)
channel = grpc.secure_channel("api.example.com:443", composite)
stub = user_pb2_grpc.UserServiceStub(channel)class AuthInterceptor(grpc.ServerInterceptor):
def intercept_service(self, continuation, handler_call_details):
md = dict(handler_call_details.invocation_metadata)
token = md.get("authorization", "")
if not verify_jwt(token):
def deny(req, ctx):
ctx.abort(grpc.StatusCode.UNAUTHENTICATED, "invalid token")
return grpc.unary_unary_rpc_method_handler(deny)
return continuation(handler_call_details)Follow-up Questions
- What is the difference between one-way TLS and mutual TLS in gRPC?
- How do channel credentials and call credentials compose?
- Where should authentication tokens be placed in a gRPC call?
- How would you implement centralized auth without editing every handler?
- Which status code should a server return for an invalid token?
MCQ Practice
1. In gRPC, what do channel credentials primarily provide?
Channel credentials establish the secure connection via TLS, encrypting traffic and authenticating the server (and client under mTLS).
2. How are per-call bearer tokens typically transmitted in gRPC?
Call credentials attach identity as metadata, conventionally the Authorization header, kept separate from the message payload.
3. Which status code best signals a missing or invalid authentication token?
UNAUTHENTICATED indicates the request lacks valid authentication credentials for the operation.
Flash Cards
Channel vs call credentials? — Channel credentials secure the connection (TLS/mTLS); call credentials attach per-RPC identity like a bearer token.
What does mutual TLS add? — The client also presents a certificate, so the server authenticates the client, not just the reverse.
Where do auth tokens go? — In call metadata, conventionally the Authorization header — never in the message body.
Code for invalid token? — UNAUTHENTICATED for missing/invalid credentials; PERMISSION_DENIED when authenticated but not allowed.
Continue Learning
Related Interview Questions
How do you set up and operate mutual TLS for gRPC services, including rotation?
hard
How do you order and design a gRPC interceptor chain for auth, observability and resilience?
hard
How do you enforce per-method authorization in a gRPC service?
hard
What are gRPC interceptors and how are they used?
medium