Я пытаюсь реализовать веб-сервис с фильтрованным доступом к ресурсам (аутентификация OAuth) с помощью Django, и у меня возникла пара вопросов.
Я создал два веб-сервера:
Я пытаюсь использовать версию1.0a OAuth для аутентификации потребителя против провайдера.Рабочий процесс этого протокола описан здесь .
В двух словах, здесь описаны различные этапы (имя обмененного ресурса):
- потребитель запрашивает токен у поставщика (ключ, секрет)
- Если потребитель действителен, поставщик возвращает еготокен (oauth_token, oauth_token_secret)
- Потребитель перенаправляет пользователя к поставщику для входа / предоставления доступа (oauth_token)
- The пользователь предоставляет доступ к ресурсу для потребителя.
- Поставщик предоставляет потребителю верификатор токена (token_verifier)
- потребитель запрашивает access_token (ключ, секрет, oauth_token, oauth_token_secret, oauth_verifier)
- Поставщик предоставляет потребителю access_token (oauth_token)
- Потребитель использует свой oauth_token для доступа к ресурсу
Вот код мнений моего потребителя:
from django.shortcuts import render_to_response
from django.http import HttpResponse, HttpResponseRedirect
import oauth2 as oauth
import urlparse
REQUEST_TOKEN_URL = 'http://127.0.0.1:8080/api/authentication/request_token/'
AUTHORIZATION_URL = 'http://127.0.0.1:8080/api/authentication/authorize/'
ACCESS_TOKEN_URL = 'http://127.0.0.1:8080/api/authentication/access_token/'
CONSUMER_CALLBACK_URL = 'http://127.0.0.1:8000/request_access_token/'
CONSUMER_KEY = 'key'
CONSUMER_SECRET = 'secret'
consumer = oauth.Consumer(CONSUMER_KEY, CONSUMER_SECRET)
client = oauth.Client(consumer)
def request_token(request):
"""
Contacts the service provider to get a token.
"""
resp, content = client.request(REQUEST_TOKEN_URL, 'GET')
oauth_token = dict(urlparse.parse_qsl(content)).get('oauth_token', None)
oauth_token_secret = dict(urlparse.parse_qsl(content)).get('oauth_token_secret',
None)
if oauth_token is None:
return render_to_response('home.html', {'data': 'NO TOKEN FOUND'})
else:
request.session['oauth_token'] = oauth_token
request.session['oauth_token_secret'] = oauth_token_secret
return HttpResponseRedirect('request_user_permission/')
def request_user_permission(request):
"""
Redirects the user to the service provider to get permission if
token provided.
"""
oauth_token = request.session['oauth_token']
if oauth_token is None:
return render_to_response('home.html', {'data': 'NO TOKEN FOUND'})
else:
return HttpResponseRedirect("%s?oauth_token=%s&oauth_callback=%s"
% (AUTHORIZATION_URL, oauth_token, CONSUMER_CALLBACK_URL))
def request_access_token(request):
"""
Requests an access token from the service provider
if the user granted permission.
"""
error = request.GET.get('error', None)
if error is None:
oauth_verifier = request.GET.get('oauth_verifier', None)
if oauth_verifier is None:
return render_to_response('home.html',
{'data': 'UNKNOWN ERROR HAPPENED'})
else:
# User permission granted, requesting access token
oauth_token = request.session['oauth_token']
oauth_token_secret = request.session['oauth_token_secret']
token = oauth.Token(oauth_token, oauth_token_secret)
token.set_verifier(oauth_verifier)
client.token = token
resp, content = client.request(ACCESS_TOKEN_URL, 'POST')
access_token = dict(urlparse.parse_qsl(content))
return render_to_response('home.html', {'data': access_token})
else:
return render_to_response('home.html', {'data': error})
Общие вопросы OAuth
- Сколько токенов должен иметь потребитель?Один?Один на пользователя?Один на ресурс?
- Как потребитель должен хранить свой токен (ы)?
- Как указать, к каким ресурсам потребитель может получить доступ с помощью своего токена?Разве потребитель не может предоставить идентификатор ресурса, к которому он хочет получить доступ, при перенаправлении пользователя на поставщика услуг (шаг 3)?
- Если потребитель хочет получить доступ к ресурсу, для которогопользователь уже предоставил доступ в прошлом, должен ли он в любом случае перенаправить пользователя к поставщику услуг (и позволить поставщику услуг немедленно вернуть oauth_verifier вместо того, чтобы запрашивать разрешение у пользователя)?
Технические проблемы
Сейчас я использую кэшированные сеансы локальной памяти для хранения токена, но он не работает:
- Когда сеансы активированы вна потребительском сервере Пользователь должен каждый раз входить в систему на сервере поставщика услуг (даже если он уже вошел в систему).
- В первом представлении (запрашивая токен) я сохраняю
oauth_token
и oauth_token_secret
в сеансе запроса.Когда я пытаюсь получить доступ к нему во втором представлении (перед перенаправлением пользователя), это работает.Но когда я пытаюсь получить доступ к нему в последнем представлении (после перенаправления), его нет (KeyError
, oauth_token
не найдено в словаре request.session
)
Спасибо!