def verify_data(self, response): bot_token = self.setting('BOT_TOKEN') if bot_token is None: raise AuthMissingParameter('telegram', 'SOCIAL_AUTH_TELEGRAM_BOT_TOKEN') received_hash_string = response.get('hash') auth_date = response.get('auth_date') if received_hash_string is None or auth_date is None: raise AuthMissingParameter('telegram', 'hash or auth_date') data_check_string = [ '{}={}'.format(k, v) for k, v in response.items() if k != 'hash' ] data_check_string = '\n'.join(sorted(data_check_string)) secret_key = hashlib.sha256(bot_token.encode()).digest() built_hash = hmac.new(secret_key, msg=data_check_string.encode(), digestmod=hashlib.sha256).hexdigest() current_timestamp = int(time.time()) auth_timestamp = int(auth_date) if current_timestamp - auth_timestamp > 86400: raise AuthFailed('telegram', 'Auth date is outdated') if built_hash != received_hash_string: raise AuthFailed('telegram', 'Invalid hash supplied')
def auth_complete(self, *args, **kwargs): if 'access_token' in self.data: # Client-side workflow token = self.data.get('access_token') response = self.get_json( 'https://www.googleapis.com/oauth2/v3/tokeninfo', params={'access_token': token}) self.process_error(response) return self.do_auth(token, response=response, *args, **kwargs) elif 'code' in self.data: # Server-side workflow response = self.request_access_token( self.ACCESS_TOKEN_URL, data=self.auth_complete_params(), headers=self.auth_headers(), method=self.ACCESS_TOKEN_METHOD) self.process_error(response) return self.do_auth(response['access_token'], response=response, *args, **kwargs) elif 'id_token' in self.data: # Client-side workflow token = self.data.get('id_token') response = self.get_json( 'https://www.googleapis.com/oauth2/v3/tokeninfo', params={'id_token': token}) self.process_error(response) return self.do_auth(token, response=response, *args, **kwargs) else: raise AuthMissingParameter(self, 'access_token, id_token, or code')
def openid_url(self): """Return service provider URL. This base class is generic accepting a POST parameter that specifies provider URL.""" if self.URL: return self.URL elif OPENID_ID_FIELD in self.data: return self.data[OPENID_ID_FIELD] else: raise AuthMissingParameter(self, OPENID_ID_FIELD)
def auth_complete(self, *args, **kwargs): """Completes loging process, must return user instance""" if 'assertion' not in self.data: raise AuthMissingParameter(self, 'assertion') response = self.get_json('https://browserid.org/verify', data={ 'assertion': self.data['assertion'], 'audience': self.strategy.request_host() }, method='POST') if response.get('status') == 'failure': raise AuthFailed(self) kwargs.update({'response': response, 'backend': self}) return self.strategy.authenticate(*args, **kwargs)
def auth_url(self): """Get the URL to which we must redirect in order to authenticate the user""" try: idp_name = self.strategy.request_data()['idp'] except KeyError: raise AuthMissingParameter(self, 'idp') auth = self._create_saml_auth(idp=self.get_idp(idp_name)) # Below, return_to sets the RelayState, which can contain # arbitrary data. We use it to store the specific SAML IdP # name, since we multiple IdPs share the same auth_complete # URL. return auth.login(return_to=idp_name)
def validate_state(self): """Validate state value. Raises exception on error, returns state value if valid.""" if not self.STATE_PARAMETER and not self.REDIRECT_STATE: return None state = self.get_session_state() request_state = self.get_request_state() if not request_state: raise AuthMissingParameter(self, 'state') elif not state: raise AuthStateMissing(self, 'state') elif not constant_time_compare(request_state, state): raise AuthStateForbidden(self) else: return state
def auth_complete(self, *args, **kwargs): """Completes loging process, must return user instance""" self.process_error(self.data) if not self.data.get('code'): raise AuthMissingParameter(self, 'code') state = self.validate_state() key, secret = self.get_key_and_secret() response = self.request(self.access_token_url(), params={ 'client_id': key, 'redirect_uri': self.get_redirect_uri(state), 'client_secret': secret, 'code': self.data['code'] }) # API v2.3 returns a JSON, according to the documents linked at issue # #592, but it seems that this needs to be enabled(?), otherwise the # usual querystring type response is returned. try: response = response.json() except ValueError: response = parse_qs(response.text) access_token = response['access_token'] return self.do_auth(access_token, response, *args, **kwargs)
def openid_url(self): """Returns LiveJournal authentication URL""" if not self.data.get('openid_lj_user'): raise AuthMissingParameter(self, 'openid_lj_user') return 'http://{0}.livejournal.com'.format(self.data['openid_lj_user'])
def auth_complete(self, *args, **kwargs): """Completes loging process, must return user instance""" if self.ID_KEY not in self.data: raise AuthMissingParameter(self, self.ID_KEY) kwargs.update({'response': self.data, 'backend': self}) return self.strategy.authenticate(*args, **kwargs)