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