1# Authentication Extension Example in gRPC Python 2 3## Check Our Guide First 4 5For most common usage of authentication in gRPC Python, please see our 6[Authentication](https://grpc.io/docs/guides/auth/) guide's Python section. The 7Guide includes following scenarios: 8 91. Server SSL credential setup 102. Client SSL credential setup 113. Authenticate with Google using a JWT 124. Authenticate with Google using an Oauth2 token 13 14Also, the guide talks about gRPC specific credential types. 15 16### Channel credentials 17 18Channel credentials are attached to a `Channel` object, the most common use case 19are SSL credentials. 20 21### Call credentials 22 23Call credentials are attached to a `Call` object (corresponding to an RPC). 24Under the hood, the call credentials is a function that takes in information of 25the RPC and modify metadata through callback. 26 27## About This Example 28 29This example focuses on extending gRPC authentication mechanism: 301) Customize authentication plugin; 312) Composite client side credentials; 323) Validation through interceptor on server side. 33 34## AuthMetadataPlugin: Manipulate metadata for each call 35 36Unlike TLS/SSL based authentication, the authentication extension in gRPC Python 37lives at a much higher level of networking. It relies on the transmission of 38metadata (HTTP Header) between client and server, instead of alternating the 39transport protocol. 40 41gRPC Python provides a way to intercept an RPC and append authentication related 42metadata through 43[`AuthMetadataPlugin`](https://grpc.github.io/grpc/python/grpc.html#grpc.AuthMetadataPlugin). 44Those in need of a custom authentication method may simply provide a concrete 45implementation of the following interface: 46 47```Python 48class AuthMetadataPlugin: 49 """A specification for custom authentication.""" 50 51 def __call__(self, context, callback): 52 """Implements authentication by passing metadata to a callback. 53 54 Implementations of this method must not block. 55 56 Args: 57 context: An AuthMetadataContext providing information on the RPC that 58 the plugin is being called to authenticate. 59 callback: An AuthMetadataPluginCallback to be invoked either 60 synchronously or asynchronously. 61 """ 62``` 63 64Then pass the instance of the concrete implementation to 65`grpc.metadata_call_credentials` function to be converted into a 66`CallCredentials` object. Please NOTE that it is possible to pass a Python 67function object directly, but we recommend to inherit from the base class to 68ensure implementation correctness. 69 70 71```Python 72def metadata_call_credentials(metadata_plugin, name=None): 73 """Construct CallCredentials from an AuthMetadataPlugin. 74 75 Args: 76 metadata_plugin: An AuthMetadataPlugin to use for authentication. 77 name: An optional name for the plugin. 78 79 Returns: 80 A CallCredentials. 81 """ 82``` 83 84The `CallCredentials` object can be passed directly into an RPC like: 85 86```Python 87call_credentials = grpc.metadata_call_credentials(my_foo_plugin) 88stub.FooRpc(request, credentials=call_credentials) 89``` 90 91Or you can use `ChannelCredentials` and `CallCredentials` at the same time by 92combining them: 93 94```Python 95channel_credentials = ... 96call_credentials = ... 97composite_credentials = grpc.composite_channel_credentials( 98 channel_credential, 99 call_credentials) 100channel = grpc.secure_channel(server_address, composite_credentials) 101``` 102 103It is also possible to apply multiple `CallCredentials` to a single RPC: 104 105```Python 106call_credentials_foo = ... 107call_credentials_bar = ... 108call_credentials = grpc.composite_call_credentials( 109 call_credentials_foo, 110 call_credentials_bar) 111stub.FooRpc(request, credentials=call_credentials) 112``` 113 114## Token-based authentication 115 116Instead of `AuthMetadataPlugin`, you can also use token-based authentication 117mechanisms using OAuth2 tokens or other customized tokens. 118 119OAuth2 tokens can be obtained using libraries like [google-auth](https://google-auth.readthedocs.io/en/master/user-guide.html): 120 121```Python 122import google.auth 123 124google_credentials, unused_project_id = google.auth.default() 125call_credentials = grpc.access_token_call_credentials(google_credentials.token) 126``` 127 128After 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). 129