xref: /aosp_15_r20/external/grpc-grpc/examples/python/auth/README.md (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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