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 перенаправления
Если 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
Альтернативы в других языках программирования
В других экосистемах существуют схожие библиотеки для построения 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, которому не требуется предварительная регистрация специфичных для провайдера настроек, что обеспечивает гибкость, но может требовать больше ручной работы.