0
# Context and Authorization
1
2
Runtime context access for service identity verification and authorization checks in ALTS-secured gRPC communications.
3
4
## Capabilities
5
6
### ALTS Context
7
8
Provides access to ALTS authentication context information including peer service accounts and security levels.
9
10
```java { .api }
11
/**
12
* Contains ALTS authentication context information
13
*/
14
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7864")
15
public final class AltsContext {
16
17
/**
18
* Creates a test instance of AltsContext for testing purposes
19
* @param peerServiceAccount the peer service account
20
* @param localServiceAccount the local service account
21
* @return AltsContext test instance
22
*/
23
public static AltsContext createTestInstance(String peerServiceAccount, String localServiceAccount);
24
25
/**
26
* Returns the security level of this context
27
* @return the SecurityLevel
28
*/
29
public SecurityLevel getSecurityLevel();
30
31
/**
32
* Returns the peer service account from the ALTS handshake
33
* @return the peer service account string
34
*/
35
public String getPeerServiceAccount();
36
37
/**
38
* Returns the local service account from the ALTS handshake
39
* @return the local service account string
40
*/
41
public String getLocalServiceAccount();
42
43
/**
44
* Security levels supported by ALTS
45
*/
46
public enum SecurityLevel {
47
/** Unknown security level */
48
UNKNOWN,
49
/** No security applied */
50
SECURITY_NONE,
51
/** Integrity protection only */
52
INTEGRITY_ONLY,
53
/** Both integrity and privacy protection */
54
INTEGRITY_AND_PRIVACY
55
}
56
}
57
```
58
59
**Usage Examples:**
60
61
```java
62
import io.grpc.alts.AltsContext;
63
import io.grpc.alts.AltsContextUtil;
64
import io.grpc.ServerCall;
65
66
// In a server interceptor or service method
67
public void handleRequest(ServerCall<?, ?> call) {
68
if (AltsContextUtil.check(call)) {
69
AltsContext context = AltsContextUtil.createFrom(call);
70
71
String peerAccount = context.getPeerServiceAccount();
72
String localAccount = context.getLocalServiceAccount();
73
AltsContext.SecurityLevel level = context.getSecurityLevel();
74
75
System.out.println("Peer: " + peerAccount);
76
System.out.println("Local: " + localAccount);
77
System.out.println("Security: " + level);
78
79
// Verify expected peer
80
if ("expected-client@project.iam.gserviceaccount.com".equals(peerAccount)) {
81
// Process request
82
} else {
83
// Reject request
84
}
85
}
86
}
87
88
// Testing context
89
AltsContext testContext = AltsContext.createTestInstance(
90
"test-peer@project.iam.gserviceaccount.com",
91
"test-local@project.iam.gserviceaccount.com"
92
);
93
```
94
95
### ALTS Context Utilities
96
97
Utility methods for extracting and checking ALTS context from gRPC calls.
98
99
```java { .api }
100
/**
101
* Utility methods for working with ALTS context
102
*/
103
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7864")
104
public final class AltsContextUtil {
105
106
/**
107
* Creates AltsContext from a server call
108
* @param call the server call
109
* @return AltsContext or null if not available
110
*/
111
public static AltsContext createFrom(ServerCall<?, ?> call);
112
113
/**
114
* Creates AltsContext from a client call
115
* @param call the client call
116
* @return AltsContext or null if not available
117
*/
118
public static AltsContext createFrom(ClientCall<?, ?> call);
119
120
/**
121
* Creates AltsContext from transport attributes
122
* @param attributes the transport attributes
123
* @return AltsContext or null if not available
124
*/
125
public static AltsContext createFrom(Attributes attributes);
126
127
/**
128
* Checks if a server call contains ALTS information
129
* @param call the server call
130
* @return true if ALTS context is available
131
*/
132
public static boolean check(ServerCall<?, ?> call);
133
134
/**
135
* Checks if a client call contains ALTS information
136
* @param call the client call
137
* @return true if ALTS context is available
138
*/
139
public static boolean check(ClientCall<?, ?> call);
140
141
/**
142
* Checks if transport attributes contain ALTS information
143
* @param attributes the transport attributes
144
* @return true if ALTS context is available
145
*/
146
public static boolean check(Attributes attributes);
147
}
148
```
149
150
**Usage Examples:**
151
152
```java
153
import io.grpc.alts.AltsContextUtil;
154
import io.grpc.alts.AltsContext;
155
import io.grpc.ServerCall;
156
import io.grpc.ClientCall;
157
import io.grpc.Attributes;
158
159
// Server-side context extraction
160
public class AltsServerInterceptor implements ServerInterceptor {
161
@Override
162
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
163
ServerCall<ReqT, RespT> call,
164
Metadata headers,
165
ServerCallHandler<ReqT, RespT> next) {
166
167
if (AltsContextUtil.check(call)) {
168
AltsContext context = AltsContextUtil.createFrom(call);
169
if (context != null) {
170
// Log or validate the peer service account
171
System.out.println("ALTS peer: " + context.getPeerServiceAccount());
172
}
173
} else {
174
System.out.println("No ALTS context available");
175
}
176
177
return next.startCall(call, headers);
178
}
179
}
180
181
// Client-side context extraction
182
public class AltsClientInterceptor implements ClientInterceptor {
183
@Override
184
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
185
MethodDescriptor<ReqT, RespT> method,
186
CallOptions callOptions,
187
Channel next) {
188
189
ClientCall<ReqT, RespT> call = next.newCall(method, callOptions);
190
191
// Check context after call completion
192
if (AltsContextUtil.check(call)) {
193
AltsContext context = AltsContextUtil.createFrom(call);
194
if (context != null) {
195
System.out.println("Server identity: " + context.getPeerServiceAccount());
196
}
197
}
198
199
return call;
200
}
201
}
202
203
// Transport attributes context extraction
204
public void handleTransportReady(Attributes attributes) {
205
if (AltsContextUtil.check(attributes)) {
206
AltsContext context = AltsContextUtil.createFrom(attributes);
207
if (context != null) {
208
System.out.println("Transport secured with ALTS");
209
System.out.println("Security level: " + context.getSecurityLevel());
210
}
211
}
212
}
213
```
214
215
### Authorization Utilities
216
217
Utility methods for performing authorization checks based on ALTS context.
218
219
```java { .api }
220
/**
221
* Utility methods for ALTS-based authorization
222
*/
223
public final class AuthorizationUtil {
224
225
/**
226
* Performs client authorization check against expected service accounts
227
* @param call the server call to check
228
* @param expectedServiceAccounts collection of expected service accounts
229
* @return Status.OK if authorized, error status otherwise
230
*/
231
public static Status clientAuthorizationCheck(
232
ServerCall<?, ?> call,
233
Collection<String> expectedServiceAccounts
234
);
235
}
236
```
237
238
**Usage Examples:**
239
240
```java
241
import io.grpc.alts.AuthorizationUtil;
242
import io.grpc.ServerCall;
243
import io.grpc.Status;
244
import java.util.Arrays;
245
import java.util.Collection;
246
247
// Server-side authorization
248
public class AuthorizingServiceImpl extends MyServiceGrpc.MyServiceImplBase {
249
250
private static final Collection<String> ALLOWED_CLIENTS = Arrays.asList(
251
"frontend@my-project.iam.gserviceaccount.com",
252
"batch-processor@my-project.iam.gserviceaccount.com"
253
);
254
255
@Override
256
public void myMethod(MyRequest request, StreamObserver<MyResponse> responseObserver) {
257
// Get the current server call
258
ServerCall<?, ?> call = getCurrentCall(); // Implementation-specific
259
260
// Perform authorization check
261
Status authStatus = AuthorizationUtil.clientAuthorizationCheck(call, ALLOWED_CLIENTS);
262
263
if (!authStatus.isOk()) {
264
responseObserver.onError(authStatus.asRuntimeException());
265
return;
266
}
267
268
// Process authorized request
269
MyResponse response = processRequest(request);
270
responseObserver.onNext(response);
271
responseObserver.onCompleted();
272
}
273
}
274
275
// Authorization in a server interceptor
276
public class AuthorizationInterceptor implements ServerInterceptor {
277
278
private final Collection<String> allowedServiceAccounts;
279
280
public AuthorizationInterceptor(Collection<String> allowedServiceAccounts) {
281
this.allowedServiceAccounts = allowedServiceAccounts;
282
}
283
284
@Override
285
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
286
ServerCall<ReqT, RespT> call,
287
Metadata headers,
288
ServerCallHandler<ReqT, RespT> next) {
289
290
Status authStatus = AuthorizationUtil.clientAuthorizationCheck(call, allowedServiceAccounts);
291
292
if (!authStatus.isOk()) {
293
call.close(authStatus, new Metadata());
294
return new ServerCall.Listener<ReqT>() {};
295
}
296
297
return next.startCall(call, headers);
298
}
299
}
300
```
301
302
## Security Context Pattern
303
304
Common pattern for accessing security context in service implementations:
305
306
```java
307
import io.grpc.alts.AltsContextUtil;
308
import io.grpc.alts.AltsContext;
309
import io.grpc.stub.StreamObserver;
310
311
public class SecureServiceImpl extends MyServiceGrpc.MyServiceImplBase {
312
313
@Override
314
public void secureMethod(MyRequest request, StreamObserver<MyResponse> responseObserver) {
315
// Access current call context
316
ServerCall<?, ?> call = getCurrentServerCall();
317
318
if (AltsContextUtil.check(call)) {
319
AltsContext altsContext = AltsContextUtil.createFrom(call);
320
321
// Use context for logging, authorization, or business logic
322
String clientServiceAccount = altsContext.getPeerServiceAccount();
323
AltsContext.SecurityLevel securityLevel = altsContext.getSecurityLevel();
324
325
// Log security information
326
System.out.printf("Request from %s with security level %s%n",
327
clientServiceAccount, securityLevel);
328
329
// Implement business logic with identity awareness
330
MyResponse response = handleSecureRequest(request, clientServiceAccount);
331
responseObserver.onNext(response);
332
responseObserver.onCompleted();
333
} else {
334
responseObserver.onError(
335
Status.UNAUTHENTICATED
336
.withDescription("ALTS authentication required")
337
.asRuntimeException()
338
);
339
}
340
}
341
342
private ServerCall<?, ?> getCurrentServerCall() {
343
// Implementation depends on how you access the current call
344
// This might involve ThreadLocal, Context propagation, or dependency injection
345
return null; // Placeholder
346
}
347
}
348
```
349
350
## Security Considerations
351
352
- **Context Availability**: ALTS context is only available for ALTS-secured connections
353
- **Service Account Validation**: Always validate peer service accounts against expected values
354
- **Security Level Checks**: Verify appropriate security levels for sensitive operations
355
- **Authorization Patterns**: Use `AuthorizationUtil` for consistent authorization checks
356
- **Testing**: Use `AltsContext.createTestInstance()` only in test environments