PK!W CHANGELOG.md1.0.0 (2019-04-02) ================== Features -------- - Changed dependency library from rauth to requests-oauthlib. 0.1.0 (2016-06-13) ================== Features -------- - first release PK!pyramid_hybridauth/__init__.pyfrom pyramid.security import NO_PERMISSION_REQUIRED from .provider import ( authenticate, view_callback, load_providers, add_auth_provider, ) from .exceptions import ProviderAccessError, ProviderConfigError # noqa def includeme(config): config.add_route("auth_authenticate", "/{provider}/{scene}/authenticate") config.add_view( authenticate, route_name="auth_authenticate", permission=NO_PERMISSION_REQUIRED, ) config.add_route("auth_callback", "/{provider}/{scene}/callback") config.add_view( view_callback, route_name="auth_callback", permission=NO_PERMISSION_REQUIRED, ) config.add_directive("add_auth_provider", add_auth_provider) load_providers(config) PK!rbp&AApyramid_hybridauth/config.pyfrom pyramid.path import DottedNameResolver from pyramid.settings import asbool from .exceptions import ProviderConfigError CONFIG_PREFIX = "hybridauth" def is_enabled(name, settings): return asbool(settings.get(f"{CONFIG_PREFIX}.{name}.enabled", False)) def get_callbacks(name, scenes, settings): resolver = DottedNameResolver() callbacks = {} for scene in scenes: try: callback = settings.get( f"{CONFIG_PREFIX}.{name}.callback.{scene}", None ) callbacks[scene] = resolver.resolve(callback) except Exception: pass return callbacks class OAuth1Config: def __init__(self, name, settings): self.name = name prefix = f"{CONFIG_PREFIX}.{self.name}" try: self.consumer_key = settings[f"{prefix}.consumer_key"] self.secret = settings[f"{prefix}.secret"] self.request_token_url = settings[f"{prefix}.request_token_url"] self.authorize_url = settings[f"{prefix}.authorize_url"] self.access_token_url = settings[f"{prefix}.access_token_url"] except KeyError as e: raise ProviderConfigError("OAuth1 env is not setting.", e) class OAuth2Config: def __init__(self, name, settings): self.name = name prefix = f"{CONFIG_PREFIX}.{self.name}" try: self.client_id = settings[f"{prefix}.client_id"] self.secret = settings[f"{prefix}.secret"] self.authorize_url = settings[f"{prefix}.authorize_url"] self.access_token_url = settings[f"{prefix}.access_token_url"] self.request_url = settings[f"{prefix}.request_url"] self.scope = settings[f"{prefix}.scope"] except KeyError as e: raise ProviderConfigError("OAuth2 env is not setting.", e) PK!KWp`` pyramid_hybridauth/exceptions.pyclass ProviderConfigError(Exception): pass class ProviderAccessError(Exception): pass PK!  pyramid_hybridauth/provider.pyfrom pyramid.httpexceptions import HTTPNotFound, HTTPFound from pyramid.settings import aslist from .exceptions import ProviderAccessError from .config import is_enabled, get_callbacks, OAuth1Config, OAuth2Config from .services.twitter import TwitterService from .services.facebook import FaceBookService from .services.google import GoogleService from .services.yahoo import YahooService from .services.ninja import NinjaService SERVICES = { "twitter": (OAuth1Config, TwitterService), "facebook": (OAuth2Config, FaceBookService), "google": (OAuth2Config, GoogleService), "yahoo": (OAuth2Config, YahooService), "ninja": (OAuth2Config, NinjaService), } def authenticate(request): provider = get_provider(request) if not provider: raise HTTPNotFound() if not provider.has_scene(request): raise HTTPNotFound() try: return provider.authenticate(request) except Exception as e: raise ProviderAccessError(e) def view_callback(request): provider = get_provider(request) if not provider: raise HTTPNotFound() if not provider.has_scene(request): raise HTTPNotFound() try: return provider.access(request) except Exception as e: raise ProviderAccessError(e) def add_auth_provider(config, provider): config.registry.auth_providers[provider.name] = provider def get_provider(request): provider_name = request.matchdict.get("provider", None) if provider_name: return request.registry.auth_providers.get(provider_name, None) return None class Provider: def __init__(self, config, service, callbacks): self.config = config self.service = service self.callbacks = callbacks def authenticate(self, request): scene = self._get_scene_name(request) callback_url = request.route_url( "auth_callback", provider=self.name, scene=scene ) authorization_url = self.service.get_authorization_url( request, self.config, callback_url ) return HTTPFound(location=authorization_url) def access(self, request): scene = self._get_scene_name(request) callback = self.callbacks[scene] callback_url = request.route_url( "auth_callback", provider=self.name, scene=scene ) user = self.service.get_user(request, self.config, callback_url) return callback(request, self.name, user) @property def name(self): return self.config.name def has_scene(self, request): scene = self._get_scene_name(request) return not self.callbacks.get(scene) is None def _get_scene_name(self, request): return request.matchdict["scene"] def load_providers(config): config.registry.auth_providers = {} settings = config.registry.settings scenes = aslist(settings.get("hybridauth.scenes", "")) if len(scenes) < 1: raise Exception("Not config scenes.") for name, class_ in SERVICES.items(): if not is_enabled(name, settings): continue oauth_config = class_[0](name, settings) callbacks = get_callbacks(name, scenes, settings) service = class_[1]() provider = Provider(oauth_config, service, callbacks) config.add_auth_provider(provider) PK!{D'pyramid_hybridauth/services/__init__.pyfrom abc import ABCMeta, abstractmethod class Service(metaclass=ABCMeta): @abstractmethod def get_authorization_url(self, request, config, callback_url): pass @abstractmethod def get_user(self, request, config, callback_url): pass class User: def __init__(self, uid, display_name, data): self._uid = uid self._display_name = display_name self._data = data def __str__(self): return ( f"uid:{self._uid}, " f"display_name:{self._display_name}, " f"data:{self._data}" ) @property def uid(self): return self._uid @property def display_name(self): return self._display_name @property def data(self): return self._data PK!Ԗ:DD'pyramid_hybridauth/services/facebook.pyfrom . import Service, User from requests_oauthlib import OAuth2Session from requests_oauthlib.compliance_fixes import facebook_compliance_fix class FaceBookService(Service): def get_authorization_url(self, request, config, callback_url): oauth = OAuth2Session( config.client_id, scope=config.scope, redirect_uri=callback_url ) oauth = facebook_compliance_fix(oauth) authorization_url, _ = oauth.authorization_url(config.authorize_url) return authorization_url def get_user(self, request, config, callback_url): oauth = OAuth2Session( config.client_id, scope=config.scope, redirect_uri=callback_url ) oauth = facebook_compliance_fix(oauth) oauth.fetch_token( config.access_token_url, client_secret=config.secret, authorization_response=request.url, ) response = oauth.get(config.request_url) data = response.json() uid = data["id"] display_name = data.get("name") return User(uid, display_name, data) PK!9%pyramid_hybridauth/services/google.pyfrom . import Service, User from requests_oauthlib import OAuth2Session class GoogleService(Service): def get_authorization_url(self, request, config, callback_url): oauth = OAuth2Session( config.client_id, scope=config.scope, redirect_uri=callback_url ) authorization_url, _ = oauth.authorization_url( config.authorize_url, access_type="offline", prompt="select_account", ) return authorization_url def get_user(self, request, config, callback_url): oauth = OAuth2Session( config.client_id, scope=config.scope, redirect_uri=callback_url ) oauth.fetch_token( config.access_token_url, client_secret=config.secret, authorization_response=request.url, ) response = oauth.get(config.request_url) data = response.json() uid = data["id"] display_name = data.get("name") return User(uid, display_name, data) PK![$pyramid_hybridauth/services/ninja.pyfrom . import Service, User from oauthlib.common import to_unicode from requests_oauthlib import OAuth2Session from json import dumps class NinjaService(Service): def get_authorization_url(self, request, config, callback_url): oauth = OAuth2Session( config.client_id, scope=config.scope, redirect_uri=callback_url ) authorization_url, _ = oauth.authorization_url(config.authorize_url) return authorization_url def get_user(self, request, config, callback_url): oauth = OAuth2Session( config.client_id, scope=config.scope, redirect_uri=callback_url ) oauth = ninja_compliance_fix(oauth) oauth.fetch_token( config.access_token_url, client_secret=config.secret, authorization_response=request.url, include_client_id=True, ) response = oauth.get(config.request_url) data = response.json() uid = data["id"] display_name = data.get("nickname") return User(uid, display_name, data) def ninja_compliance_fix(session): def _compliance_fix(r): if r.status_code != 200: return r token = r.json() expires_in = token.get("expires_in") if expires_in and int(expires_in) < 1: token.pop("expires_in") r._content = to_unicode(dumps(token)).encode("UTF-8") return r session.register_compliance_hook("access_token_response", _compliance_fix) return session PK!*w_BB&pyramid_hybridauth/services/twitter.pyfrom . import Service, User from ..exceptions import ProviderAccessError from requests_oauthlib import OAuth1Session from urllib.parse import parse_qsl class TwitterService(Service): def get_authorization_url(self, request, config, callback_url): oauth = OAuth1Session( config.consumer_key, client_secret=config.secret, callback_uri=callback_url, ) oauth.fetch_request_token(config.request_token_url) return oauth.authorization_url(config.authorize_url) def get_user(self, request, config, callback_url): oauth_token = request.GET.get("oauth_token", None) oauth_verifier = request.GET.get("oauth_verifier", None) if oauth_token is None or oauth_verifier is None: raise ProviderAccessError("Not found parameter.") oauth = OAuth1Session( config.consumer_key, client_secret=config.secret, resource_owner_key=oauth_token, resource_owner_secret=oauth_verifier, ) response = oauth.post( config.access_token_url, params={"oauth_verifier": oauth_verifier} ) data = dict(parse_qsl(response.content.decode("utf-8"))) uid = data["user_id"] display_name = data.get("screen_name") return User(uid, display_name, data) PK!ޤ2$pyramid_hybridauth/services/yahoo.pyfrom . import Service, User from requests_oauthlib import OAuth2Session class YahooService(Service): def get_authorization_url(self, request, config, callback_url): oauth = OAuth2Session( config.client_id, scope=config.scope, redirect_uri=callback_url ) authorization_url, _ = oauth.authorization_url(config.authorize_url) return authorization_url def get_user(self, request, config, callback_url): oauth = OAuth2Session( config.client_id, scope=config.scope, redirect_uri=callback_url ) oauth.fetch_token( config.access_token_url, client_secret=config.secret, authorization_response=request.url, ) response = oauth.get(config.request_url) data = response.json() uid = data["user_id"] display_name = data.get("name") return User(uid, display_name, data) PK!HڽTU(pyramid_hybridauth-1.0.0.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!H V+pyramid_hybridauth-1.0.0.dist-info/METADATARMo1Wx7IQVMEHhH*gwuk{v=cZ!>y4yDR"%ښH|Vz:]ɦz]HxFa6u   RS@(>jjQ-d2ĠM WS&gP:Uȅ"kmV.Ƶ1{\ ZίE64"|qkm}ʿۉfI{\'' w~Ѫ7,P}kM8ݤfSFU߯emͪ]B: vINf}Lzxu>el _ bpk.Z{4ÒzQ mxڥS' 7֗RLDi*R !iH-ÜPK!H2ڨ)pyramid_hybridauth-1.0.0.dist-info/RECORDɲ@}nAlY0: l(fAs77e*ԭ9K[A(cq!a&sKi$wL`s71tAFPG;~>=?}G;j4%:kM^;teNuvĚԨSW[NjԛHW5|vvW%4yFIQSop4&,g N\nZƅ|<+Ḧ́Cj4dǗJjYy %vH EɰaJ⚳-x&+JDvfsV çAMS틳C$,ڕŰo~yo }8zqn=.Ն)֠MRsb4`i*˟<~4:뵏LT5+p@Py?;Yp[[JHA8}np(/5@KtC BOYL?~PK!W CHANGELOG.mdPK!pyramid_hybridauth/__init__.pyPK!rbp&AA"pyramid_hybridauth/config.pyPK!KWp`` pyramid_hybridauth/exceptions.pyPK!  ; pyramid_hybridauth/provider.pyPK!{D'pyramid_hybridauth/services/__init__.pyPK!Ԗ:DD'pyramid_hybridauth/services/facebook.pyPK!9%k!pyramid_hybridauth/services/google.pyPK![$%pyramid_hybridauth/services/ninja.pyPK!*w_BB&+pyramid_hybridauth/services/twitter.pyPK!ޤ2$c1pyramid_hybridauth/services/yahoo.pyPK!HڽTU(F5pyramid_hybridauth-1.0.0.dist-info/WHEELPK!H V+5pyramid_hybridauth-1.0.0.dist-info/METADATAPK!H2ڨ)7pyramid_hybridauth-1.0.0.dist-info/RECORDPKe: