Skip to content

Commit

Permalink
Added support for multiple tokens (Fixes #16)
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko committed Oct 6, 2012
1 parent c1098a5 commit 333ab43
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
10 changes: 8 additions & 2 deletions docs/index.rst
Expand Up @@ -94,11 +94,17 @@ probably sufficient::
from flask import session from flask import session


@twitter.tokengetter @twitter.tokengetter
def get_twitter_token(): def get_twitter_token(token=None):
return session.get('twitter_token') return session.get('twitter_token')


If the token does not exist, the function must return `None`, and If the token does not exist, the function must return `None`, and
otherwise return a tuple in the form ``(token, secret)``. otherwise return a tuple in the form ``(token, secret)``. The function
might also be passed a `token` parameter. This is user defined and can be
used to indicate another token. Imagine for instance you want to support
user and application tokens or different tokens for the same user.

The name of the token can be passed to to the
:meth:`~OAuthRemoteApp.request` function.


Signing in / Authorizing Signing in / Authorizing
------------------------ ------------------------
Expand Down
34 changes: 28 additions & 6 deletions flask_oauth.py
Expand Up @@ -231,18 +231,21 @@ def delete(self, *args, **kwargs):
kwargs['method'] = 'DELETE' kwargs['method'] = 'DELETE'
return self.request(*args, **kwargs) return self.request(*args, **kwargs)


def make_client(self): def make_client(self, token=None):
"""Creates a new `oauth2` Client object with the token attached. """Creates a new `oauth2` Client object with the token attached.
Usually you don't have to do that but use the :meth:`request` Usually you don't have to do that but use the :meth:`request`
method instead. method instead.
""" """
return oauth2.Client(self._consumer, self.get_request_token()) return oauth2.Client(self._consumer, self.get_request_token(token))


def request(self, url, data="", headers=None, format='urlencoded', def request(self, url, data="", headers=None, format='urlencoded',
method='GET', content_type=None): method='GET', content_type=None, token=None):
"""Sends a request to the remote server with OAuth tokens attached. """Sends a request to the remote server with OAuth tokens attached.
The `url` is joined with :attr:`base_url` if the URL is relative. The `url` is joined with :attr:`base_url` if the URL is relative.
.. versionadded:: 0.12
added the `token` parameter.
:param url: where to send the request to :param url: where to send the request to
:param data: the data to be sent to the server. If the request method :param data: the data to be sent to the server. If the request method
is ``GET`` the data is appended to the URL as query is ``GET`` the data is appended to the URL as query
Expand All @@ -257,10 +260,16 @@ def request(self, url, data="", headers=None, format='urlencoded',
:param content_type: an optional content type. If a content type is :param content_type: an optional content type. If a content type is
provided, the data is passed as it and the provided, the data is passed as it and the
`format` parameter is ignored. `format` parameter is ignored.
:param token: an optional token to pass to tokengetter. Use this if you
want to support sending requests using multiple tokens.
If you set this to anything not None, `tokengetter_func`
will receive the given token as an argument, in which case
the tokengetter should return the `(token, secret)` tuple
for the given token.
:return: an :class:`OAuthResponse` object. :return: an :class:`OAuthResponse` object.
""" """
headers = dict(headers or {}) headers = dict(headers or {})
client = self.make_client() client = self.make_client(token)
url = self.expand_url(url) url = self.expand_url(url)
if method == 'GET': if method == 'GET':
assert format == 'urlencoded' assert format == 'urlencoded'
Expand Down Expand Up @@ -296,9 +305,11 @@ def generate_request_token(self, callback=None):
session[self.name + '_oauthtok'] = tup session[self.name + '_oauthtok'] = tup
return tup return tup


def get_request_token(self): def get_request_token(self, token=None):
assert self.tokengetter_func is not None, 'missing tokengetter function' assert self.tokengetter_func is not None, 'missing tokengetter function'
rv = self.tokengetter_func() # Don't pass the token if the token is None to support old
# tokengetter functions.
rv = self.tokengetter_func(*(token and (token,) or ()))
if rv is None: if rv is None:
rv = session.get(self.name + '_oauthtok') rv = session.get(self.name + '_oauthtok')
if rv is None: if rv is None:
Expand Down Expand Up @@ -337,6 +348,17 @@ def tokengetter(self, f):
"""Registers a function as tokengetter. The tokengetter has to return """Registers a function as tokengetter. The tokengetter has to return
a tuple of ``(token, secret)`` with the user's token and token secret. a tuple of ``(token, secret)`` with the user's token and token secret.
If the data is unavailable, the function must return `None`. If the data is unavailable, the function must return `None`.
If the `token` parameter is passed to the request function it's
forwarded to the tokengetter function::
@oauth.tokengetter
def get_token(token='user'):
if token == 'user':
return find_the_user_token()
elif token == 'app':
return find_the_app_token()
raise RuntimeError('invalid token')
""" """
self.tokengetter_func = f self.tokengetter_func = f
return f return f
Expand Down

0 comments on commit 333ab43

Please sign in to comment.