mirror of https://github.com/grpc/grpc.git
The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
4.4 KiB
128 lines
4.4 KiB
# Authentication Extension Example in gRPC Python |
|
|
|
## Check Our Guide First |
|
|
|
For most common usage of authentication in gRPC Python, please see our |
|
[Authentication](https://grpc.io/docs/guides/auth/) guide's Python section. The |
|
Guide includes following scenarios: |
|
|
|
1. Server SSL credential setup |
|
2. Client SSL credential setup |
|
3. Authenticate with Google using a JWT |
|
4. Authenticate with Google using an Oauth2 token |
|
|
|
Also, the guide talks about gRPC specific credential types. |
|
|
|
### Channel credentials |
|
|
|
Channel credentials are attached to a `Channel` object, the most common use case |
|
are SSL credentials. |
|
|
|
### Call credentials |
|
|
|
Call credentials are attached to a `Call` object (corresponding to an RPC). |
|
Under the hood, the call credentials is a function that takes in information of |
|
the RPC and modify metadata through callback. |
|
|
|
## About This Example |
|
|
|
This example focuses on extending gRPC authentication mechanism: |
|
1) Customize authentication plugin; |
|
2) Composite client side credentials; |
|
3) Validation through interceptor on server side. |
|
|
|
## AuthMetadataPlugin: Manipulate metadata for each call |
|
|
|
Unlike TLS/SSL based authentication, the authentication extension in gRPC Python |
|
lives at a much higher level of networking. It relies on the transmission of |
|
metadata (HTTP Header) between client and server, instead of alternating the |
|
transport protocol. |
|
|
|
gRPC Python provides a way to intercept an RPC and append authentication related |
|
metadata through |
|
[`AuthMetadataPlugin`](https://grpc.github.io/grpc/python/grpc.html#grpc.AuthMetadataPlugin). |
|
Those in need of a custom authentication method may simply provide a concrete |
|
implementation of the following interface: |
|
|
|
```Python |
|
class AuthMetadataPlugin: |
|
"""A specification for custom authentication.""" |
|
|
|
def __call__(self, context, callback): |
|
"""Implements authentication by passing metadata to a callback. |
|
|
|
Implementations of this method must not block. |
|
|
|
Args: |
|
context: An AuthMetadataContext providing information on the RPC that |
|
the plugin is being called to authenticate. |
|
callback: An AuthMetadataPluginCallback to be invoked either |
|
synchronously or asynchronously. |
|
""" |
|
``` |
|
|
|
Then pass the instance of the concrete implementation to |
|
`grpc.metadata_call_credentials` function to be converted into a |
|
`CallCredentials` object. Please NOTE that it is possible to pass a Python |
|
function object directly, but we recommend to inherit from the base class to |
|
ensure implementation correctness. |
|
|
|
|
|
```Python |
|
def metadata_call_credentials(metadata_plugin, name=None): |
|
"""Construct CallCredentials from an AuthMetadataPlugin. |
|
|
|
Args: |
|
metadata_plugin: An AuthMetadataPlugin to use for authentication. |
|
name: An optional name for the plugin. |
|
|
|
Returns: |
|
A CallCredentials. |
|
""" |
|
``` |
|
|
|
The `CallCredentials` object can be passed directly into an RPC like: |
|
|
|
```Python |
|
call_credentials = grpc.metadata_call_credentials(my_foo_plugin) |
|
stub.FooRpc(request, credentials=call_credentials) |
|
``` |
|
|
|
Or you can use `ChannelCredentials` and `CallCredentials` at the same time by |
|
combining them: |
|
|
|
```Python |
|
channel_credentials = ... |
|
call_credentials = ... |
|
composite_credentials = grpc.composite_channel_credentials( |
|
channel_credential, |
|
call_credentials) |
|
channel = grpc.secure_channel(server_address, composite_credentials) |
|
``` |
|
|
|
It is also possible to apply multiple `CallCredentials` to a single RPC: |
|
|
|
```Python |
|
call_credentials_foo = ... |
|
call_credentials_bar = ... |
|
call_credentials = grpc.composite_call_credentials( |
|
call_credentials_foo, |
|
call_credentials_bar) |
|
stub.FooRpc(request, credentials=call_credentials) |
|
``` |
|
|
|
## Token-based authentication |
|
|
|
Instead of `AuthMetadataPlugin`, you can also use token-based authentication |
|
mechanisms using OAuth2 tokens or other customized tokens. |
|
|
|
OAuth2 tokens can be obtained using libraries like [google-auth](https://google-auth.readthedocs.io/en/master/user-guide.html): |
|
|
|
```Python |
|
import google.auth |
|
|
|
google_credentials, unused_project_id = google.auth.default() |
|
call_credentials = grpc.access_token_call_credentials(google_credentials.token) |
|
``` |
|
|
|
After obtaining the token, the rest of the flow is documented in [token_based_auth_client.py](https://github.com/grpc/grpc/tree/master/examples/python/auth/token_based_auth_client.py) and [token_based_auth_server.py](https://github.com/grpc/grpc/tree/master/examples/python/auth/token_based_auth_server.py).
|
|
|