def persona_login(request): assertion = request.POST.get('assertion', '') settings = app_settings.PROVIDERS.get(PersonaProvider.id, {}) audience = settings.get('AUDIENCE', None) if audience is None: raise ImproperlyConfigured( "No Persona audience configured. Please " "add an AUDIENCE item to the " "SOCIALACCOUNT_PROVIDERS['persona'] setting.") resp = requests.post('https://verifier.login.persona.org/verify', { 'assertion': assertion, 'audience': audience }) try: resp.raise_for_status() extra_data = resp.json() if extra_data['status'] != 'okay': return render_authentication_error( request, provider_id=PersonaProvider.id, extra_context={'response': extra_data}) except (ValueError, requests.RequestException) as e: return render_authentication_error(request, provider_id=PersonaProvider.id, exception=e) login = providers.registry \ .by_id(PersonaProvider.id, request) \ .sociallogin_from_response(request, extra_data) login.state = SocialLogin.state_from_request(request) return complete_social_login(request, login)
def callback(request): if 'dr_auth_status' not in request.GET: return render_authentication_error(request, DraugiemProvider.id, error=AuthError.UNKNOWN) if request.GET['dr_auth_status'] != 'ok': return render_authentication_error(request, DraugiemProvider.id, error=AuthError.DENIED) if 'dr_auth_code' not in request.GET: return render_authentication_error(request, DraugiemProvider.id, error=AuthError.UNKNOWN) ret = None auth_exception = None try: app = providers.registry.by_id(DraugiemProvider.id, request).get_app(request) login = draugiem_complete_login(request, app, request.GET['dr_auth_code']) login.state = SocialLogin.unstash_state(request) ret = complete_social_login(request, login) except (requests.RequestException, DraugiemApiError) as e: auth_exception = e if not ret: ret = render_authentication_error(request, DraugiemProvider.id, exception=auth_exception) return ret
def login_by_token(request): ret = None auth_exception = None if request.method == 'POST': form = FacebookConnectForm(request.POST) if form.is_valid(): try: provider = providers.registry.by_id( FacebookProvider.id, request) login_options = provider.get_fb_login_options(request) app = provider.get_app(request) access_token = form.cleaned_data['access_token'] expires_at = None if login_options.get('auth_type') == 'reauthenticate': info = requests.get( GRAPH_API_URL + '/oauth/access_token_info', params={'client_id': app.client_id, 'access_token': access_token}).json() nonce = provider.get_nonce(request, pop=True) ok = nonce and nonce == info.get('auth_nonce') else: ok = True if ok and provider.get_settings().get('EXCHANGE_TOKEN'): resp = requests.get( GRAPH_API_URL + '/oauth/access_token', params={'grant_type': 'fb_exchange_token', 'client_id': app.client_id, 'client_secret': app.secret, 'fb_exchange_token': access_token}).json() access_token = resp['access_token'] expires_in = resp.get('expires_in') if expires_in: expires_at = timezone.now() + timedelta( seconds=int(expires_in)) if ok: token = SocialToken(app=app, token=access_token, expires_at=expires_at) login = fb_complete_login(request, app, token) login.token = token login.state = SocialLogin.state_from_request(request) ret = complete_social_login(request, login) except requests.RequestException as e: logger.exception('Error accessing FB user profile') auth_exception = e if not ret: ret = render_authentication_error(request, FacebookProvider.id, exception=auth_exception) return ret
def telegram_login(request): provider = providers.registry.by_id(TelegramProvider.id, request) data = dict(request.GET.items()) hash = data.pop('hash') payload = '\n'.join(sorted(['{}={}'.format(k, v) for k, v in data.items()])) token = provider.get_settings()['TOKEN'] token_sha256 = hashlib.sha256(token.encode()).digest() expected_hash = hmac.new(token_sha256, payload.encode(), hashlib.sha256).hexdigest() auth_date = int(data.pop('auth_date')) if hash != expected_hash or time.time() - auth_date > 30: return render_authentication_error(request, provider_id=provider.id, extra_context={'response': data}) login = provider.sociallogin_from_response(request, data) return complete_social_login(request, login)
def dispatch(self, request, *args, **kwargs): if 'error' in request.GET or 'code' not in request.GET: # Distinguish cancel from error auth_error = request.GET.get('error', None) if auth_error == self.adapter.login_cancelled_error: error = AuthError.CANCELLED else: error = AuthError.UNKNOWN return render_authentication_error( request, self.adapter.provider_id, error=error) app = self.adapter.get_provider().get_app(self.request) client = self.get_client(request, app) try: access_token = client.get_access_token(request.GET['code']) token = self.adapter.parse_token(access_token) token.app = app login = self.adapter.complete_login(request, app, token, response=access_token) login.token = token if self.adapter.supports_state: login.state = SocialLogin \ .verify_and_unstash_state( request, get_request_param(request, 'state')) else: login.state = SocialLogin.unstash_state(request) return complete_social_login(request, login) except (PermissionDenied, OAuth2Error, RequestException, ProviderException) as e: return render_authentication_error( request, self.adapter.provider_id, exception=e)
def dispatch(self, request): """ View to handle final steps of OAuth based authentication where the user gets redirected back to from the service provider """ login_done_url = reverse(self.adapter.provider_id + "_callback") client = self._get_client(request, login_done_url) if not client.is_valid(): if 'denied' in request.GET: error = AuthError.CANCELLED else: error = AuthError.UNKNOWN extra_context = dict(oauth_client=client) return render_authentication_error(request, self.adapter.provider_id, error=error, extra_context=extra_context) app = self.adapter.get_provider().get_app(request) try: access_token = client.get_access_token() token = SocialToken( app=app, token=access_token['oauth_token'], # .get() -- e.g. Evernote does not feature a secret token_secret=access_token.get('oauth_token_secret', '')) login = self.adapter.complete_login(request, app, token, response=access_token) login.token = token login.state = SocialLogin.unstash_state(request) return complete_social_login(request, login) except OAuthError as e: return render_authentication_error(request, self.adapter.provider_id, exception=e)
def complete_login(self, login): return complete_social_login(self.request, login)