perxis.auth
Модуль для аутентификации в gRPC с использованием OAuth2 и API-ключей.
Этот модуль предоставляет два класса для аутентификации:
OAuth2Plugin
: Аутентификация с помощью OAuth2.APIKeyPlugin
: Аутентификация с использованием API-ключа.
Данный код можно использовать для настройки gRPC-клиента с нужным типом аутентификации.
Пример использования:
gRPC Python предоставляет способ перехвата RPC и добавления метаданных, связанных с аутентификацией, через AuthMetadataPlugin. Те, кому нужен специальный метод аутентификации, могут просто предоставить конкретную реализацию следующего интерфейса:
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.
"""
Затем передайте экземпляр конкретной реализации в функцию grpc.metadata_call_credentials, которая будет преобразована в объект CallCredentials.
ОБРАТИТЕ ВНИМАНИЕ, что можно передать объект функции 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.
"""
Объект CallCredentials
можно передать непосредственно в RPC, например:
>>> call_credentials = grpc.metadata_call_credentials(my_foo_plugin)
>>> stub.FooRpc(request, credentials=call_credentials)
Пример авторизации и аутентификации OAuth2
import grpc
from oauthlib.oauth2 import Client
from oauthlib.oauth2.rfc6749.parameters import prepare_token_request
from perxis.auth import OAuth2Plugin
from perxis.users.users_pb2 import GetRequest
from perxis.users.users_pb2_grpc import UsersStub
class ExtendedClient(Client):
def __init__(self, client_id, grant_type, username, password, **kwargs):
self.grant_type = grant_type
self.username = username
self.password = password
super(ExtendedClient, self).__init__(client_id, **kwargs)
def prepare_request_body(self, body='', scope=None, include_client_id=False, **kwargs):
kwargs['client_id'] = self.client_id
kwargs['include_client_id'] = include_client_id
return prepare_token_request(
self.grant_type,
body=body,
username=self.username,
password=self.password,
scope=scope,
**kwargs
)
oauth2_plugin = OAuth2Plugin(
client=ExtendedClient(
client_id='client_id',
grant_type='password',
username='user',
password='pass'
),
client_secret='client_secret',
token_url='https://example.com/oauth/token',
audience='audience'
)
call_credentials = grpc.metadata_call_credentials(oauth2_plugin)
with grpc.insecure_channel('localhost:50051') as channel:
request = GetRequest(user_id=1)
stub = UsersStub(channel)
stub.Get(request, credentials=call_credentials)
1""" 2Модуль для аутентификации в gRPC с использованием OAuth2 и API-ключей. 3 4Этот модуль предоставляет два класса для аутентификации: 5 6- [`OAuth2Plugin`](#OAuth2Plugin): Аутентификация с помощью OAuth2. 7- [`APIKeyPlugin`](#APIKeyPlugin): Аутентификация с использованием API-ключа. 8 9Данный код можно использовать для настройки gRPC-клиента с нужным типом аутентификации. 10 11## Пример использования: 12.. include:: ../README.md 13 :start-line: 22 14 :end-line: 120 15--- 16""" 17 18import time 19import grpc 20from oauthlib.oauth2 import Client, OAuth2Token 21from requests_oauthlib import OAuth2Session 22 23 24class OAuth2Plugin(grpc.AuthMetadataPlugin): 25 """Спецификация аутентификации для gRPC с использованием OAuth2. 26 27 Этот класс управляет получением и обновлением токена OAuth2 для аутентификации 28 gRPC-запросов. 29 30 Attributes: 31 _token (str | None): Токен. По умолчанию None. 32 oauth2 (OAuth2Session): Сессия OAuth2 для управления токенами. 33 Args: 34 client (Client): OAuth2 клиент. 35 client_secret (str): Секрет клиента. 36 token_url (str): URL для получения токена. 37 audience (str): Получатель (аудитория) токена, указывающая, для какого 38 сервиса он предназначен. 39 signature_header_key (str, optional): Заголовок для подписи запроса. 40 По умолчанию "authorization". 41 token_type (str, optional): Тип токена. По умолчанию "Bearer". 42 """ 43 44 _token = None 45 46 def __init__( 47 self, 48 client: Client, 49 client_secret: str, 50 token_url: str, 51 audience: str, 52 signature_header_key: str = "authorization", 53 token_type: str = "Bearer", 54 ) -> None: 55 """Инициализирует объект аутентификации OAuth2 для gRPC. 56 57 Этот метод устанавливает основные параметры OAuth2-клиента, необходимые 58 для получения и обновления токена. 59 60 Args: 61 client (Client): OAuth2 клиент для аутентификации. 62 client_secret (str): Секретный ключ клиента. 63 token_url (str): URL-адрес сервера авторизации для получения токена. 64 audience (str): Аудитория токена, указывающая целевой сервис. 65 signature_header_key (str, optional): Заголовок, в который будет добавляться токен. 66 По умолчанию "authorization". 67 token_type (str, optional): Тип токена. По умолчанию "Bearer". 68 """ 69 self._client_secret = client_secret 70 self._token_url = token_url 71 self._audience = audience 72 self._signature_header_key = signature_header_key 73 self._token_type = token_type 74 self.oauth2 = OAuth2Session(client=client) 75 76 def __call__( 77 self, 78 context: grpc.AuthMetadataContext, 79 callback: grpc.AuthMetadataPluginCallback, 80 ) -> None: 81 """Добавляет токен в метаданные gRPC-запроса. 82 83 Args: 84 context (grpc.AuthMetadataContext): Контекст аутентификации gRPC. 85 callback (grpc.AuthMetadataPluginCallback): Callback для передачи метаданных. 86 """ 87 callback( 88 metadata=( 89 ( 90 self._signature_header_key, 91 f'{self._token_type} {self.token["access_token"]}', 92 ), 93 ), 94 error=None, 95 ) 96 97 @property 98 def token(self) -> OAuth2Token: 99 """Получает текущий OAuth2-токен, обновляя его при необходимости. 100 101 Returns: 102 OAuth2Token: Актуальный токен. 103 """ 104 105 def fetch_token() -> OAuth2Token: 106 return self.oauth2.fetch_token( 107 token_url=self._token_url, 108 client_secret=self._client_secret, 109 audience=self._audience, 110 ) 111 112 def refresh_token() -> OAuth2Token: 113 return self.oauth2.refresh_token( 114 token_url=self._token_url, 115 client_secret=self._client_secret, 116 audience=self._audience, 117 ) 118 119 if self._token is None: 120 self._token = fetch_token() 121 122 if self._token["expires_at"] and self._token["expires_at"] < time.time(): 123 if "refresh_token" in self._token: 124 self._token = refresh_token() 125 else: 126 self._token = fetch_token() 127 return self._token 128 129 130class APIKeyPlugin(grpc.AuthMetadataPlugin): 131 """Спецификация аутентификации для gRPC с использованием API-ключа. 132 133 Этот класс добавляет API-ключ в заголовок запроса для аутентификации 134 gRPC-запросов. 135 136 Attributes: 137 _token (str): API-ключ. 138 _signature_header_key (str): Заголовок, в который вставляется ключ. 139 _token_type (str): Тип токена (например, "API-Key"). 140 Args: 141 token (str): API-ключ. 142 signature_header_key (str, optional): Заголовок для подписи запроса. 143 По умолчанию "authorization". 144 token_type (str, optional): Тип токена. По умолчанию "API-Key". 145 """ 146 147 _token = None 148 149 def __init__( 150 self, 151 token: str, 152 signature_header_key: str = "authorization", 153 token_type: str = "API-Key", 154 ) -> None: 155 """Инициализирует объект аутентификации API-ключа для gRPC. 156 157 Args: 158 token (str): API-ключ, используемый для аутентификации. 159 signature_header_key (str, optional): Заголовок, в который будет добавляться API-ключ. 160 По умолчанию "authorization". 161 token_type (str, optional): Тип токена. По умолчанию "API-Key". 162 """ 163 self._token = token 164 self._signature_header_key = signature_header_key 165 self._token_type = token_type 166 167 def __call__( 168 self, 169 context: grpc.AuthMetadataContext, 170 callback: grpc.AuthMetadataPluginCallback, 171 ) -> None: 172 """Добавляет API-ключ в метаданные gRPC-запроса. 173 174 Args: 175 context (grpc.AuthMetadataContext): Контекст аутентификации gRPC. 176 callback (grpc.AuthMetadataPluginCallback): Callback для передачи метаданных. 177 """ 178 callback( 179 metadata=( 180 (self._signature_header_key, f"{self._token_type} {self._token}"), 181 ), 182 error=None, 183 )
25class OAuth2Plugin(grpc.AuthMetadataPlugin): 26 """Спецификация аутентификации для gRPC с использованием OAuth2. 27 28 Этот класс управляет получением и обновлением токена OAuth2 для аутентификации 29 gRPC-запросов. 30 31 Attributes: 32 _token (str | None): Токен. По умолчанию None. 33 oauth2 (OAuth2Session): Сессия OAuth2 для управления токенами. 34 Args: 35 client (Client): OAuth2 клиент. 36 client_secret (str): Секрет клиента. 37 token_url (str): URL для получения токена. 38 audience (str): Получатель (аудитория) токена, указывающая, для какого 39 сервиса он предназначен. 40 signature_header_key (str, optional): Заголовок для подписи запроса. 41 По умолчанию "authorization". 42 token_type (str, optional): Тип токена. По умолчанию "Bearer". 43 """ 44 45 _token = None 46 47 def __init__( 48 self, 49 client: Client, 50 client_secret: str, 51 token_url: str, 52 audience: str, 53 signature_header_key: str = "authorization", 54 token_type: str = "Bearer", 55 ) -> None: 56 """Инициализирует объект аутентификации OAuth2 для gRPC. 57 58 Этот метод устанавливает основные параметры OAuth2-клиента, необходимые 59 для получения и обновления токена. 60 61 Args: 62 client (Client): OAuth2 клиент для аутентификации. 63 client_secret (str): Секретный ключ клиента. 64 token_url (str): URL-адрес сервера авторизации для получения токена. 65 audience (str): Аудитория токена, указывающая целевой сервис. 66 signature_header_key (str, optional): Заголовок, в который будет добавляться токен. 67 По умолчанию "authorization". 68 token_type (str, optional): Тип токена. По умолчанию "Bearer". 69 """ 70 self._client_secret = client_secret 71 self._token_url = token_url 72 self._audience = audience 73 self._signature_header_key = signature_header_key 74 self._token_type = token_type 75 self.oauth2 = OAuth2Session(client=client) 76 77 def __call__( 78 self, 79 context: grpc.AuthMetadataContext, 80 callback: grpc.AuthMetadataPluginCallback, 81 ) -> None: 82 """Добавляет токен в метаданные gRPC-запроса. 83 84 Args: 85 context (grpc.AuthMetadataContext): Контекст аутентификации gRPC. 86 callback (grpc.AuthMetadataPluginCallback): Callback для передачи метаданных. 87 """ 88 callback( 89 metadata=( 90 ( 91 self._signature_header_key, 92 f'{self._token_type} {self.token["access_token"]}', 93 ), 94 ), 95 error=None, 96 ) 97 98 @property 99 def token(self) -> OAuth2Token: 100 """Получает текущий OAuth2-токен, обновляя его при необходимости. 101 102 Returns: 103 OAuth2Token: Актуальный токен. 104 """ 105 106 def fetch_token() -> OAuth2Token: 107 return self.oauth2.fetch_token( 108 token_url=self._token_url, 109 client_secret=self._client_secret, 110 audience=self._audience, 111 ) 112 113 def refresh_token() -> OAuth2Token: 114 return self.oauth2.refresh_token( 115 token_url=self._token_url, 116 client_secret=self._client_secret, 117 audience=self._audience, 118 ) 119 120 if self._token is None: 121 self._token = fetch_token() 122 123 if self._token["expires_at"] and self._token["expires_at"] < time.time(): 124 if "refresh_token" in self._token: 125 self._token = refresh_token() 126 else: 127 self._token = fetch_token() 128 return self._token
Спецификация аутентификации для gRPC с использованием OAuth2.
Этот класс управляет получением и обновлением токена OAuth2 для аутентификации gRPC-запросов.
Attributes:
- _token (str | None): Токен. По умолчанию None.
- oauth2 (OAuth2Session): Сессия OAuth2 для управления токенами.
Arguments:
- client (Client): OAuth2 клиент.
- client_secret (str): Секрет клиента.
- token_url (str): URL для получения токена.
- audience (str): Получатель (аудитория) токена, указывающая, для какого сервиса он предназначен.
- signature_header_key (str, optional): Заголовок для подписи запроса. По умолчанию "authorization".
- token_type (str, optional): Тип токена. По умолчанию "Bearer".
47 def __init__( 48 self, 49 client: Client, 50 client_secret: str, 51 token_url: str, 52 audience: str, 53 signature_header_key: str = "authorization", 54 token_type: str = "Bearer", 55 ) -> None: 56 """Инициализирует объект аутентификации OAuth2 для gRPC. 57 58 Этот метод устанавливает основные параметры OAuth2-клиента, необходимые 59 для получения и обновления токена. 60 61 Args: 62 client (Client): OAuth2 клиент для аутентификации. 63 client_secret (str): Секретный ключ клиента. 64 token_url (str): URL-адрес сервера авторизации для получения токена. 65 audience (str): Аудитория токена, указывающая целевой сервис. 66 signature_header_key (str, optional): Заголовок, в который будет добавляться токен. 67 По умолчанию "authorization". 68 token_type (str, optional): Тип токена. По умолчанию "Bearer". 69 """ 70 self._client_secret = client_secret 71 self._token_url = token_url 72 self._audience = audience 73 self._signature_header_key = signature_header_key 74 self._token_type = token_type 75 self.oauth2 = OAuth2Session(client=client)
Инициализирует объект аутентификации OAuth2 для gRPC.
Этот метод устанавливает основные параметры OAuth2-клиента, необходимые для получения и обновления токена.
Arguments:
- client (Client): OAuth2 клиент для аутентификации.
- client_secret (str): Секретный ключ клиента.
- token_url (str): URL-адрес сервера авторизации для получения токена.
- audience (str): Аудитория токена, указывающая целевой сервис.
- signature_header_key (str, optional): Заголовок, в который будет добавляться токен. По умолчанию "authorization".
- token_type (str, optional): Тип токена. По умолчанию "Bearer".
98 @property 99 def token(self) -> OAuth2Token: 100 """Получает текущий OAuth2-токен, обновляя его при необходимости. 101 102 Returns: 103 OAuth2Token: Актуальный токен. 104 """ 105 106 def fetch_token() -> OAuth2Token: 107 return self.oauth2.fetch_token( 108 token_url=self._token_url, 109 client_secret=self._client_secret, 110 audience=self._audience, 111 ) 112 113 def refresh_token() -> OAuth2Token: 114 return self.oauth2.refresh_token( 115 token_url=self._token_url, 116 client_secret=self._client_secret, 117 audience=self._audience, 118 ) 119 120 if self._token is None: 121 self._token = fetch_token() 122 123 if self._token["expires_at"] and self._token["expires_at"] < time.time(): 124 if "refresh_token" in self._token: 125 self._token = refresh_token() 126 else: 127 self._token = fetch_token() 128 return self._token
Получает текущий OAuth2-токен, обновляя его при необходимости.
Returns:
OAuth2Token: Актуальный токен.
131class APIKeyPlugin(grpc.AuthMetadataPlugin): 132 """Спецификация аутентификации для gRPC с использованием API-ключа. 133 134 Этот класс добавляет API-ключ в заголовок запроса для аутентификации 135 gRPC-запросов. 136 137 Attributes: 138 _token (str): API-ключ. 139 _signature_header_key (str): Заголовок, в который вставляется ключ. 140 _token_type (str): Тип токена (например, "API-Key"). 141 Args: 142 token (str): API-ключ. 143 signature_header_key (str, optional): Заголовок для подписи запроса. 144 По умолчанию "authorization". 145 token_type (str, optional): Тип токена. По умолчанию "API-Key". 146 """ 147 148 _token = None 149 150 def __init__( 151 self, 152 token: str, 153 signature_header_key: str = "authorization", 154 token_type: str = "API-Key", 155 ) -> None: 156 """Инициализирует объект аутентификации API-ключа для gRPC. 157 158 Args: 159 token (str): API-ключ, используемый для аутентификации. 160 signature_header_key (str, optional): Заголовок, в который будет добавляться API-ключ. 161 По умолчанию "authorization". 162 token_type (str, optional): Тип токена. По умолчанию "API-Key". 163 """ 164 self._token = token 165 self._signature_header_key = signature_header_key 166 self._token_type = token_type 167 168 def __call__( 169 self, 170 context: grpc.AuthMetadataContext, 171 callback: grpc.AuthMetadataPluginCallback, 172 ) -> None: 173 """Добавляет API-ключ в метаданные gRPC-запроса. 174 175 Args: 176 context (grpc.AuthMetadataContext): Контекст аутентификации gRPC. 177 callback (grpc.AuthMetadataPluginCallback): Callback для передачи метаданных. 178 """ 179 callback( 180 metadata=( 181 (self._signature_header_key, f"{self._token_type} {self._token}"), 182 ), 183 error=None, 184 )
Спецификация аутентификации для gRPC с использованием API-ключа.
Этот класс добавляет API-ключ в заголовок запроса для аутентификации gRPC-запросов.
Attributes:
- _token (str): API-ключ.
- _signature_header_key (str): Заголовок, в который вставляется ключ.
- _token_type (str): Тип токена (например, "API-Key").
Arguments:
- token (str): API-ключ.
- signature_header_key (str, optional): Заголовок для подписи запроса. По умолчанию "authorization".
- token_type (str, optional): Тип токена. По умолчанию "API-Key".
150 def __init__( 151 self, 152 token: str, 153 signature_header_key: str = "authorization", 154 token_type: str = "API-Key", 155 ) -> None: 156 """Инициализирует объект аутентификации API-ключа для gRPC. 157 158 Args: 159 token (str): API-ключ, используемый для аутентификации. 160 signature_header_key (str, optional): Заголовок, в который будет добавляться API-ключ. 161 По умолчанию "authorization". 162 token_type (str, optional): Тип токена. По умолчанию "API-Key". 163 """ 164 self._token = token 165 self._signature_header_key = signature_header_key 166 self._token_type = token_type
Инициализирует объект аутентификации API-ключа для gRPC.
Arguments:
- token (str): API-ключ, используемый для аутентификации.
- signature_header_key (str, optional): Заголовок, в который будет добавляться API-ключ. По умолчанию "authorization".
- token_type (str, optional): Тип токена. По умолчанию "API-Key".