-
Notifications
You must be signed in to change notification settings - Fork 461
/
Copy pathauth.md
439 lines (347 loc) · 17.8 KB
/
auth.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
---
title: Authentication
description: >-
An overview of gRPC authentication, including built-in auth mechanisms, and
how to plug in your own authentication systems.
---
### Overview
gRPC is designed to work with a variety of authentication mechanisms, making it
easy to safely use gRPC to talk to other systems. You can use our supported
mechanisms - SSL/TLS with or without Google token-based authentication - or you
can plug in your own authentication system by extending our provided code.
gRPC also provides a simple authentication API that lets you provide all the
necessary authentication information as `Credentials` when creating a channel or
making a call.
### Supported auth mechanisms
The following authentication mechanisms are built-in to gRPC:
- **SSL/TLS**: gRPC has SSL/TLS integration and promotes the use of SSL/TLS
to authenticate the server, and to encrypt all the data exchanged between
the client and the server. Optional mechanisms are available for clients to
provide certificates for mutual authentication.
- **ALTS**: gRPC supports
[ALTS](https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security)
as a transport security mechanism, if the application is running on
[Compute Engine](https://cloud.google.com/compute) or
[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine).
For details, see one of the following
language-specific pages:
[ALTS in C++]({{< relref "docs/languages/cpp/alts" >}}),
[ALTS in Go]({{< relref "docs/languages/go/alts" >}}),
[ALTS in Java]({{< relref "docs/languages/java/alts" >}}),
[ALTS in Python]({{< relref "docs/languages/python/alts" >}}).
- **Token-based authentication with Google**: gRPC provides a generic
mechanism (described below) to attach metadata based credentials to requests
and responses. Additional support for acquiring access tokens
(typically OAuth2 tokens) while accessing Google APIs through gRPC is
provided for certain auth flows: you can see how this works in our code
examples below. In general this mechanism must be used *as well as* SSL/TLS
on the channel - Google will not allow connections without SSL/TLS, and
most gRPC language implementations will not let you send credentials on an
unencrypted channel.
{{% alert title="Warning" color="warning" %}}
Google credentials should only be used to connect to Google services. Sending
a Google issued OAuth2 token to a non-Google service could result in this
token being stolen and used to impersonate the client to Google services.
{{% /alert %}}
### Authentication API
gRPC provides a simple authentication API based around the unified concept of
Credentials objects, which can be used when creating an entire gRPC channel or
an individual call.
#### Credential types
Credentials can be of two types:
- **Channel credentials**, which are attached to a `Channel`, such as SSL
credentials.
- **Call credentials**, which are attached to a call (or `ClientContext` in
C++).
You can also combine these in a `CompositeChannelCredentials`, allowing you to
specify, for example, SSL details for the channel along with call credentials
for each call made on the channel. A `CompositeChannelCredentials` associates a
`ChannelCredentials` and a `CallCredentials` to create a new
`ChannelCredentials`. The result will send the authentication data associated
with the composed `CallCredentials` with every call made on the channel.
For example, you could create a `ChannelCredentials` from an `SslCredentials`
and an `AccessTokenCredentials`. The result when applied to a `Channel` would
send the appropriate access token for each call on this channel.
Individual `CallCredentials` can also be composed using
`CompositeCallCredentials`. The resulting `CallCredentials` when used in a call
will trigger the sending of the authentication data associated with the two
`CallCredentials`.
#### Using client-side SSL/TLS
Now let's look at how `Credentials` work with one of our supported auth
mechanisms. This is the simplest authentication scenario, where a client just
wants to authenticate the server and encrypt all data. The example is in C++,
but the API is similar for all languages: you can see how to enable SSL/TLS in
more languages in our Examples section below.
```cpp
// Create a default SSL ChannelCredentials object.
auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
// Create a channel using the credentials created in the previous step.
auto channel = grpc::CreateChannel(server_name, channel_creds);
// Create a stub on the channel.
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
// Make actual RPC calls on the stub.
grpc::Status s = stub->sayHello(&context, *request, response);
```
For advanced use cases such as modifying the root CA or using client certs,
the corresponding options can be set in the `SslCredentialsOptions` parameter
passed to the factory method.
{{% alert title="Note" color="info" %}}
Non-POSIX-compliant systems (such as Windows) need to specify the root
certificates in `SslCredentialsOptions`, since the defaults are only
configured for POSIX filesystems.
{{% /alert %}}
#### Using OAuth token-based authentication
OAuth 2.0 Protocol is the industry-standard protocol for authorization. It enables
websites or applications to obtain limited access to user accounts using OAuth tokens.
gRPC offers a set of simple APIs to integrate OAuth 2.0 into applications, streamlining authentication.
At a high level, using OAuth token-based authentication includes 3 steps:
1. Get or generate an OAuth token on client side.
* You can generate Google-specific tokens following instructions below.
2. Create credentials with the OAuth token.
* OAuth token is always part of per-call credentials, you can also attach the per-call credentials
to some channel credentials.
* The token will be sent to server, normally as part of HTTP Authorization header.
3. Server side verifies the token.
* In most implementations, the validation is done using a server side interceptor.
For details of how to use OAuth token in different languages, please refer to our examples below.
#### Using Google token-based authentication
gRPC applications can use a simple API to create a credential that works for
authentication with Google in various deployment scenarios. Again, our example
is in C++ but you can find examples in other languages in our Examples section.
```cpp
auto creds = grpc::GoogleDefaultCredentials();
// Create a channel, stub and make RPC calls (same as in the previous example)
auto channel = grpc::CreateChannel(server_name, creds);
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
grpc::Status s = stub->sayHello(&context, *request, response);
```
This channel credentials object works for applications using Service Accounts as
well as for applications running in [Google Compute Engine
(GCE)](https://cloud.google.com/compute/). In the former case, the service
account’s private keys are loaded from the file named in the environment
variable `GOOGLE_APPLICATION_CREDENTIALS`. The keys are used to generate bearer
tokens that are attached to each outgoing RPC on the corresponding channel.
For applications running in GCE, a default service account and corresponding
OAuth2 scopes can be configured during VM setup. At run-time, this credential
handles communication with the authentication systems to obtain OAuth2 access
tokens and attaches them to each outgoing RPC on the corresponding channel.
#### Extending gRPC to support other authentication mechanisms
The Credentials plugin API allows developers to plug in their own type of
credentials. This consists of:
- The `MetadataCredentialsPlugin` abstract class, which contains the pure virtual
`GetMetadata` method that needs to be implemented by a sub-class created by
the developer.
- The `MetadataCredentialsFromPlugin` function, which creates a `CallCredentials`
from the `MetadataCredentialsPlugin`.
Here is example of a simple credentials plugin which sets an authentication
ticket in a custom header.
```cpp
class MyCustomAuthenticator : public grpc::MetadataCredentialsPlugin {
public:
MyCustomAuthenticator(const grpc::string& ticket) : ticket_(ticket) {}
grpc::Status GetMetadata(
grpc::string_ref service_url, grpc::string_ref method_name,
const grpc::AuthContext& channel_auth_context,
std::multimap<grpc::string, grpc::string>* metadata) override {
metadata->insert(std::make_pair("x-custom-auth-ticket", ticket_));
return grpc::Status::OK;
}
private:
grpc::string ticket_;
};
auto call_creds = grpc::MetadataCredentialsFromPlugin(
std::unique_ptr<grpc::MetadataCredentialsPlugin>(
new MyCustomAuthenticator("super-secret-ticket")));
```
A deeper integration can be achieved by plugging in a gRPC credentials
implementation at the core level. gRPC internals also allow switching out
SSL/TLS with other encryption mechanisms.
### Language guides and examples
These authentication mechanisms will be available in all gRPC's supported
languages. The following table links to examples demonstrating authentication
and authorization in various languages.
| Language | Example | Documentation |
|----------|-------------------------------------------|------------------------|
| C++ | N/A | N/A |
| Go | [Go Example] | [Go Documentation] |
| Java | [Java Example TLS] ([Java Example ATLS]) | [Java Documentation] |
| Python | [Python Example] | [Python Documentation] |
[Go Example]: https://github.com/grpc/grpc-go/tree/master/examples/features/encryption
[Go Documentation]: https://github.com/grpc/grpc-go/tree/master/examples/features/encryption#encryption
[Java Example TLS]: https://github.com/grpc/grpc-java/tree/master/examples/example-tls
[Java Example ATLS]: https://github.com/grpc/grpc-java/tree/master/examples/example-alts
[Java Documentation]: https://github.com/grpc/grpc-java/tree/master/examples/example-tls#hello-world-example-with-tls
[Python Example]: https://github.com/grpc/grpc/tree/master/examples/python/auth
[Python Documentation]: https://github.com/grpc/grpc/tree/master/examples/python/auth#authentication-extension-example-in-grpc-python
### Language guides and examples for OAuth token-based authentication
The following table links to examples demonstrating OAuth token-based
authentication and authorization in various languages.
| Language | Example | Documentation |
|----------|-------------------------------------------|-------------------------------|
| C++ | N/A | N/A |
| Go | [Go OAuth Example] | [Go OAuth Documentation] |
| Java | [Java OAuth Example] | [Java OAuth Documentation] |
| Python | [Python OAuth Example] | [Python OAuth Documentation] |
[Go OAuth Example]: https://github.com/grpc/grpc-go/tree/master/examples/features/authentication#authentication
[Go OAuth Documentation]: https://github.com/grpc/grpc-go/tree/master/examples/features/authentication#oauth2
[Java OAuth Example]: https://github.com/grpc/grpc-java/tree/master/examples/example-oauth#authentication-example
[Java OAuth Documentation]: https://github.com/grpc/grpc-java/tree/master/examples/example-oauth
[Python OAuth Example]: https://github.com/grpc/grpc/blob/master/examples/python/auth/token_based_auth_client.py
[Python OAuth Documentation]: https://github.com/grpc/grpc/tree/master/examples/python/auth#token-based-authentication
### Additional Examples
The following sections demonstrate how authentication and authorization features
described above appear in other languages not listed above.
#### Ruby
##### Base case - no encryption or authentication
```ruby
stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure)
...
```
##### With server authentication SSL/TLS
```ruby
creds = GRPC::Core::ChannelCredentials.new(load_certs) # load_certs typically loads a CA roots file
stub = Helloworld::Greeter::Stub.new('myservice.example.com', creds)
```
##### Authenticate with Google
```ruby
require 'googleauth' # from http://www.rubydoc.info/gems/googleauth/0.1.0
...
ssl_creds = GRPC::Core::ChannelCredentials.new(load_certs) # load_certs typically loads a CA roots file
authentication = Google::Auth.get_application_default()
call_creds = GRPC::Core::CallCredentials.new(authentication.updater_proc)
combined_creds = ssl_creds.compose(call_creds)
stub = Helloworld::Greeter::Stub.new('greeter.googleapis.com', combined_creds)
```
#### Node.js
##### Base case - No encryption/authentication
```js
var stub = new helloworld.Greeter('localhost:50051', grpc.credentials.createInsecure());
```
##### With server authentication SSL/TLS
```js
const root_cert = fs.readFileSync('path/to/root-cert');
const ssl_creds = grpc.credentials.createSsl(root_cert);
const stub = new helloworld.Greeter('myservice.example.com', ssl_creds);
```
##### Authenticate with Google
```js
// Authenticating with Google
var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library
...
var ssl_creds = grpc.credentials.createSsl(root_certs);
(new GoogleAuth()).getApplicationDefault(function(err, auth) {
var call_creds = grpc.credentials.createFromGoogleCredential(auth);
var combined_creds = grpc.credentials.combineChannelCredentials(ssl_creds, call_creds);
var stub = new helloworld.Greeter('greeter.googleapis.com', combined_credentials);
});
```
##### Authenticate with Google using OAuth2 token (legacy approach)
```js
var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library
...
var ssl_creds = grpc.Credentials.createSsl(root_certs); // load_certs typically loads a CA roots file
var scope = 'https://www.googleapis.com/auth/grpc-testing';
(new GoogleAuth()).getApplicationDefault(function(err, auth) {
if (auth.createScopeRequired()) {
auth = auth.createScoped(scope);
}
var call_creds = grpc.credentials.createFromGoogleCredential(auth);
var combined_creds = grpc.credentials.combineChannelCredentials(ssl_creds, call_creds);
var stub = new helloworld.Greeter('greeter.googleapis.com', combined_credentials);
});
```
##### With server authentication SSL/TLS and a custom header with token
```js
const rootCert = fs.readFileSync('path/to/root-cert');
const channelCreds = grpc.credentials.createSsl(rootCert);
const metaCallback = (_params, callback) => {
const meta = new grpc.Metadata();
meta.add('custom-auth-header', 'token');
callback(null, meta);
}
const callCreds = grpc.credentials.createFromMetadataGenerator(metaCallback);
const combCreds = grpc.credentials.combineChannelCredentials(channelCreds, callCreds);
const stub = new helloworld.Greeter('myservice.example.com', combCreds);
```
#### PHP
##### Base case - No encryption/authorization
```php
$client = new helloworld\GreeterClient('localhost:50051', [
'credentials' => Grpc\ChannelCredentials::createInsecure(),
]);
```
##### With server authentication SSL/TLS
```php
$client = new helloworld\GreeterClient('myservice.example.com', [
'credentials' => Grpc\ChannelCredentials::createSsl(file_get_contents('roots.pem')),
]);
```
##### Authenticate with Google
```php
function updateAuthMetadataCallback($context)
{
$auth_credentials = ApplicationDefaultCredentials::getCredentials();
return $auth_credentials->updateMetadata($metadata = [], $context->service_url);
}
$channel_credentials = Grpc\ChannelCredentials::createComposite(
Grpc\ChannelCredentials::createSsl(file_get_contents('roots.pem')),
Grpc\CallCredentials::createFromPlugin('updateAuthMetadataCallback')
);
$opts = [
'credentials' => $channel_credentials
];
$client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);
```
##### Authenticate with Google using OAuth2 token (legacy approach)
```php
// the environment variable "GOOGLE_APPLICATION_CREDENTIALS" needs to be set
$scope = "https://www.googleapis.com/auth/grpc-testing";
$auth = Google\Auth\ApplicationDefaultCredentials::getCredentials($scope);
$opts = [
'credentials' => Grpc\Credentials::createSsl(file_get_contents('roots.pem'));
'update_metadata' => $auth->getUpdateMetadataFunc(),
];
$client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);
```
#### Dart
##### Base case - no encryption or authentication
```dart
final channel = new ClientChannel('localhost',
port: 50051,
options: const ChannelOptions(
credentials: const ChannelCredentials.insecure()));
final stub = new GreeterClient(channel);
```
##### With server authentication SSL/TLS
```dart
// Load a custom roots file.
final trustedRoot = new File('roots.pem').readAsBytesSync();
final channelCredentials =
new ChannelCredentials.secure(certificates: trustedRoot);
final channelOptions = new ChannelOptions(credentials: channelCredentials);
final channel = new ClientChannel('myservice.example.com',
options: channelOptions);
final client = new GreeterClient(channel);
```
##### Authenticate with Google
```dart
// Uses publicly trusted roots by default.
final channel = new ClientChannel('greeter.googleapis.com');
final serviceAccountJson =
new File('service-account.json').readAsStringSync();
final credentials = new JwtServiceAccountAuthenticator(serviceAccountJson);
final client =
new GreeterClient(channel, options: credentials.toCallOptions);
```
##### Authenticate a single RPC call
```dart
// Uses publicly trusted roots by default.
final channel = new ClientChannel('greeter.googleapis.com');
final client = new GreeterClient(channel);
...
final serviceAccountJson =
new File('service-account.json').readAsStringSync();
final credentials = new JwtServiceAccountAuthenticator(serviceAccountJson);
final response =
await client.sayHello(request, options: credentials.toCallOptions);
```