Prepare request uri: примеры (PYTHON)
prepare_request_uri(uri: str, redirect_uri: str=None, scope: list=None, state: str=None, **kwargs: Any): strОписание функции prepare_request_uri
Метод prepare_request_uri принадлежит классу oauthlib.oauth2.WebApplicationClient в библиотеке OAuthLib для Python. Он применяется для создания URI конечной точки авторизации OAuth 2.0, на который необходимо перенаправить пользовательский агент (например, браузер). Этот URI включает в себя обязательные параметры, такие как client_id, response_type, redirect_uri, а также опциональные scope, state и другие.
Метод чаще всего используется в веб-приложениях, которые следуют модели Authorization Code Grant (поток кода авторизации), но также поддерживает и другие типы ответов.
Аргументы функции
- authorization_endpoint (str, обязательный): URL конечной точки авторизации OAuth 2.0 провайдера.
- redirect_uri (str, необязательный): URI, на который провайдер OAuth 2.0 перенаправит пользователя после авторизации. Если не указан, используется значение, заданное при создании клиента.
- scope (list или str, необязательный): Области доступа, которые запрашивает приложение. Могут быть переданы как список строк или как одна строка, разделенная пробелами.
- state (str, необязательный): Случайная строка для защиты от CSRF-атак. Рекомендуется всегда использовать.
- **kwargs: Дополнительные параметры, которые будут добавлены в строку запроса URI. Это могут быть
code_challengeдля PKCE,nonceдля OpenID Connect и другие.
Возвращаемое значение
Функция возвращает строку (str), представляющую собой полный URI для перенаправления пользователя. Этот URI включает базовый адрес конечной точки авторизации и параметры, сформированные в виде строки запроса.
Примеры использования prepare_request_uri
Ниже представлены различные варианты вызова функции с демонстрацией результатов.
Базовый пример
Создание URI с обязательными параметрами.
from oauthlib.oauth2 import WebApplicationClient
client_id = 'ваш_идентификатор_клиента'
client = WebApplicationClient(client_id)
authorization_url = 'https://provider.com/oauth/authorize'
uri = client.prepare_request_uri(
authorization_url,
redirect_uri='https://yourapp.com/callback',
scope=['read', 'write'],
state='random_state_string'
)
print(uri)https://provider.com/oauth/authorize?response_type=code&client_id=ваш_идентификатор_клиента&redirect_uri=https%3A%2F%2Fyourapp.com%2Fcallback&scope=read+write&state=random_state_string
Пример с параметрами PKCE
Использование расширения PKCE для публичных клиентов.
from oauthlib.oauth2 import WebApplicationClient
import hashlib
import base64
import os
client = WebApplicationClient('client_id_123')
code_verifier = base64.urlsafe_b64encode(os.urandom(40)).decode('utf-8').rstrip('=')
code_challenge = hashlib.sha256(code_verifier.encode()).digest()
code_challenge = base64.urlsafe_b64encode(code_challenge).decode('utf-8').rstrip('=')
uri = client.prepare_request_uri(
'https://auth.server/authorize',
redirect_uri='https://app.local/cb',
scope='openid profile',
state='secure_state_123',
code_challenge=code_challenge,
code_challenge_method='S256'
)
print(uri[:120] + '...')https://auth.server/authorize?response_type=code&client_id=client_id_123&redirect_uri=https%3A%2F%2Fapp.local%2Fcb&scope=openid+profile&state=secure_state_123&code_challenge=...&code_challenge_method=S256
Похожие функции в Python
Библиотека OAuthLib предоставляет другие клиенты и методы для работы с OAuth 2.0.
- WebApplicationClient.prepare_authorization_request: Аналогичный метод, который возвращает кортеж из URI, заголовков и тела запроса. Может быть полезен для нестандартных HTTP-запросов.
- MobileApplicationClient.prepare_request_uri: Клиент для мобильных приложений (Implicit Grant). Использует
response_type='token'по умолчанию. - LegacyApplicationClient: Клиент для доверенных приложений (Resource Owner Password Credentials Grant). Не использует
prepare_request_uri, так как авторизация происходит без перенаправления пользователя. - BackendApplicationClient: Клиент для сервер-серверного взаимодействия (Client Credentials Grant).
Метод prepare_request_uri WebApplicationClient является основным для классического веб-потока с кодом авторизации.
Альтернативы в других языках программирования
В других экосистемах существуют схожие библиотеки для построения URI авторизации OAuth 2.0.
JavaScript (Node.js)
Библиотека openid-client или simple-oauth2. Обычно используется метод, конфигурирующий клиент, который затем генерирует URL.
const { Issuer } = require('openid-client');
(async () => {
const googleIssuer = await Issuer.discover('https://accounts.google.com');
const client = new googleIssuer.Client({
client_id: 'CLIENT_ID',
redirect_uris: ['https://yourapp.com/callback']
});
const authorizationUrl = client.authorizationUrl({
scope: 'openid email',
state: 'some_state'
});
console.log(authorizationUrl);
})();PHP
Библиотека league/oauth2-client предоставляет класс AbstractProvider с методом getAuthorizationUrl().
$provider = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => 'CLIENT_ID',
'redirectUri' => 'https://yourapp.com/callback',
'urlAuthorize' => 'https://provider.com/oauth/authorize'
]);
$authorizationUrl = $provider->getAuthorizationUrl(['scope' => 'read']);
$_SESSION['oauth2state'] = $provider->getState();
echo $authorizationUrl;Java
Фреймворк Spring Security OAuth 2.0 Client использует класс AuthorizationCodeGrantRequest для конструирования URI через OAuth2AuthorizationRequestResolver.
// Конфигурация через свойства приложения. Генерация URI происходит автоматически фреймворком.
// Прямого аналога в одну строку нет, процесс инкапсулирован.Ключевое отличие Python-реализации в использовании универсального клиента WebApplicationClient, которому не требуется предварительная регистрация специфичных для провайдера настроек, что обеспечивает гибкость, но может требовать больше ручной работы.
Типичные ошибки при использовании
Неверный или отсутствующий URI перенаправления
Если redirect_uri не передан в метод и не был установлен при создании клиента, возникнет ошибка.
client = WebApplicationClient('client_id')
try:
uri = client.prepare_request_uri('https://provider.com/auth')
except ValueError as e:
print(f'Ошибка: {e}')Ошибка: Missing redirect_uri.
Некорректная кодировка параметров
Функция автоматически кодирует параметры. Попытка передать уже закодированную строку может привести к двойному кодированию.
# Неправильно: ручное кодирование
uri = client.prepare_request_uri(
'https://provider.com/auth',
redirect_uri='https%3A%2F%2Fapp.com%2Fcb', # Уже закодировано
state='test'
)
print(uri) # redirect_uri будет закодирован повторноhttps://provider.com/auth?response_type=code&client_id=client_id&redirect_uri=https%253A%252F%252Fapp.com%252Fcb&state=test
В результате провайдер может не распознать URI.
Использование небезопасного состояния (state)
Отсутствие параметра state или использование предсказуемого значения делает приложение уязвимым к CSRF-атакам.
История изменений функции
Метод prepare_request_uri долгое время оставался стабильным. Основные изменения в библиотеке OAuthLib касались улучшения безопасности и поддержки новых расширений спецификации OAuth 2.0.
- Версия 3.x: Улучшена поддержка PKCE (RFC 7636). Параметры
code_challengeиcode_challenge_methodстали корректно обрабатываться как часть**kwargs. - Более ранние версии: В версиях до 2.0.0 могли отличаться названия некоторых параметров или детали обработки scope. Рекомендуется использовать версии 3.x и выше.
При обновлении библиотеки стоит обратить внимание на объявление нерекомендуемых (deprecated) способов вызова, хотя сигнатура данного метода не претерпела кардинальных изменений.
Расширенные примеры использования
Интеграция с конкретным провайдером (GitHub)
Пример формирования URI для GitHub OAuth App с использованием пользовательских параметров.
from oauthlib.oauth2 import WebApplicationClient
client = WebApplicationClient(client_id='github_client_id')
github_auth_url = 'https://github.com/login/oauth/authorize'
uri = client.prepare_request_uri(
github_auth_url,
redirect_uri='http://localhost:8000/auth/callback',
scope=['user', 'repo'],
state='unique_session_state_xyz',
allow_signup='false' # Специфичный параметр GitHub
)
print(uri)https://github.com/login/oauth/authorize?response_type=code&client_id=github_client_id&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fcallback&scope=user+repo&state=unique_session_state_xyz&allow_signup=false
Использование нестандартного response_type
Некоторые провайдеры поддерживают гибридные потоки OpenID Connect.
from oauthlib.oauth2 import WebApplicationClient
client = WebApplicationClient(client_id='oidc_client', default_response_type='code id_token')
uri = client.prepare_request_uri(
'https://oidc.provider.com/authorize',
redirect_uri='https://app.com/callback',
scope='openid email',
state='state_123',
nonce='nonce_456', # Обязательный параметр для OpenID Connect
response_mode='fragment' # Указание режима ответа
)
print(uri[:150] + '...')https://oidc.provider.com/authorize?response_type=code+id_token&client_id=oidc_client&redirect_uri=https%3A%2F%2Fapp.com%2Fcallback&scope=openid+email&state=state_123&nonce=nonce_456&response_mode=fragment...
Динамическое изменение scope на основе действий пользователя
Создание разных URI для запроса разных наборов разрешений в рамках одного приложения.
def generate_auth_url(base_scopes, extra_scopes=None):
client = WebApplicationClient('dynamic_client')
all_scopes = base_scopes
if extra_scopes:
all_scopes.extend(extra_scopes)
uri = client.prepare_request_uri(
'https://api.service.com/oauth2/auth',
redirect_uri='https://app.com/cb',
scope=all_scopes,
state='dynamic_scope_state'
)
return uri
# Запрос базовых прав
url1 = generate_auth_url(['profile'])
print('URL1:', url1.split('scope=')[1].split('&')[0])
# Запрос базовых прав + дополнительных
url2 = generate_auth_url(['profile'], ['email', 'messages:read'])
print('URL2:', url2.split('scope=')[1].split('&')[0])URL1: profile URL2: profile+email+messages%3Aread