Source code for

"""Flickr OAuth drop-in.

Uses oauthlib directly to authenticate and sign requests with OAuth
1.0 credentials.

Note that when users decline Flickr's OAuth prompt by clicking the Cancel
button, Flickr redirects them to its home page, *not* to us.
import logging
import oauthlib.oauth1
import urllib.parse, urllib.request

from flask import request
from import ndb

from . import flickr_auth, views, models
from .webutil import flask_util, util
from .webutil.util import json_dumps, json_loads

logger = logging.getLogger(__name__)

API_URL = ''

[docs]class FlickrAuth(models.BaseAuth): """An authenticated Flickr user. Provides methods that return information about this user and make OAuth-signed requests to the Flickr API. Stores OAuth credentials in the datastore. Key is the Flickr user ID. See models.BaseAuth for usage details. """ # access token token_key = ndb.StringProperty(required=True) token_secret = ndb.StringProperty(required=True) user_json = ndb.TextProperty(required=True)
[docs] def site_name(self): return 'Flickr'
[docs] def user_display_name(self): """Returns the user id. """ return self.key_id()
[docs] def access_token(self): """Returns the OAuth access token as a (string key, string secret) tuple. """ return (self.token_key, self.token_secret)
def _api(self): return oauthlib.oauth1.Client( flickr_auth.FLICKR_APP_KEY, client_secret=flickr_auth.FLICKR_APP_SECRET, resource_owner_key=self.token_key, resource_owner_secret=self.token_secret, signature_type=oauthlib.oauth1.SIGNATURE_TYPE_QUERY)
[docs] def urlopen(self, url, **kwargs): return flickr_auth.signed_urlopen( url, self.token_key, self.token_secret, **kwargs)
def call_api_method(self, method, params): return flickr_auth.call_api_method( method, params, self.token_key, self.token_secret)
[docs]class Start(views.Start): """Starts three-legged OAuth with Flickr. Fetches an OAuth request token, then redirects to Flickr's auth page to request an access token. """ NAME = 'flickr' LABEL = 'Flickr'
[docs] def redirect_url(self, state=None): assert flickr_auth.FLICKR_APP_KEY and flickr_auth.FLICKR_APP_SECRET, \ "Please fill in the flickr_app_key and flickr_app_secret files in your app's root directory." # double-URL-encode state because Flickr URL-decodes the redirect URL before # redirecting to it, and JSON values may have ?s and &s. e.g. the Bridgy # WordPress plugin's redirect URL when using Bridgy's registration API # ( looks like: # /wp-admin/admin.php?page=bridgy_options&service=flickr if state: state = urllib.parse.quote(state) client = oauthlib.oauth1.Client( flickr_auth.FLICKR_APP_KEY, client_secret=flickr_auth.FLICKR_APP_SECRET, callback_uri=self.to_url(state)) url, headers, data = client.sign(REQUEST_TOKEN_URL) resp = util.requests_get(url, headers=headers, data=data) parsed = urllib.parse.parse_qs(resp.text) if parsed.get('error') or parsed.get('oauth_problem'): flask_util.error(resp.text) resource_owner_key = parsed.get('oauth_token')[0] resource_owner_secret = parsed.get('oauth_token_secret')[0] models.OAuthRequestToken( id=resource_owner_key, token_secret=resource_owner_secret, state=state).put() if self.scope: auth_url = AUTHORIZE_URL + '?' + urllib.parse.urlencode({ 'perms': self.scope or 'read', 'oauth_token': resource_owner_key }) else: auth_url = AUTHENTICATE_URL + '?' + urllib.parse.urlencode({ 'oauth_token': resource_owner_key }) 'Generated request token, redirect to Flickr authorization url: %s', auth_url) return auth_url
[docs] @classmethod def button_html(cls, *args, **kwargs): return super(cls, cls).button_html( *args, input_style='background-color: #EEEEEE; padding: 10px', **kwargs)
[docs]class Callback(views.Callback): """The OAuth callback. Fetches an access token and redirects to the front page. """
[docs] def dispatch_request(self): oauth_token = request.values.get('oauth_token') oauth_verifier = request.values.get('oauth_verifier') request_token = models.OAuthRequestToken.get_by_id(oauth_token) client = oauthlib.oauth1.Client( flickr_auth.FLICKR_APP_KEY, client_secret=flickr_auth.FLICKR_APP_SECRET, resource_owner_key=oauth_token, resource_owner_secret=request_token.token_secret, verifier=oauth_verifier) uri, headers, body = client.sign(ACCESS_TOKEN_URL) try: resp = util.urlopen(urllib.request.Request(uri, body, headers)) except BaseException as e: util.interpret_http_exception(e) raise parsed = dict(urllib.parse.parse_qs( access_token = parsed.get('oauth_token')[0] access_secret = parsed.get('oauth_token_secret')[0] user_nsid = parsed.get('user_nsid')[0] if access_token is None: flask_util.error('Missing required query parameter oauth_token.') auth = FlickrAuth(id=user_nsid, token_key=access_token, token_secret=access_secret) user_json = auth.call_api_method('flickr.people.getInfo', {'user_id': user_nsid}) auth.user_json = json_dumps(user_json) auth.put() return self.finish(auth, state=request.values.get('state'))