Esempio n. 1
0
    def callback(self):
        if request.args.get('error'):
            if request.args['error'] == 'user_denied':
                raise LoginCallbackError(
                    _(u"You denied the GitHub login request"))
            elif request.args['error'] == 'redirect_uri_mismatch':
                # TODO: Log this as an exception for the server admin to look at
                raise LoginCallbackError(
                    _(u"This server's callback URL is misconfigured"))
            else:
                raise LoginCallbackError(_(u"Unknown failure"))
        code = request.args.get('code', None)
        try:
            response = requests.post(self.token_url,
                                     headers={
                                         'Accept': 'application/json'
                                     },
                                     params={
                                         'client_id': self.key,
                                         'client_secret': self.secret,
                                         'code': code
                                     }).json()
        except requests.ConnectionError as e:
            raise LoginCallbackError(
                _(u"Unable to authenticate via GitHub. Internal details: {error}"
                  ).format(error=e))
        if 'error' in response:
            raise LoginCallbackError(response['error'])
        ghinfo = requests.get(self.user_info,
                              params={
                                  'access_token': response['access_token']
                              }).json()
        ghemails = requests.get(self.user_emails,
                                params={
                                    'access_token': response['access_token']
                                },
                                headers={
                                    'Accept': 'application/vnd.github.v3+json'
                                }).json()

        email = None
        emails = []
        if ghemails and isinstance(ghemails, (list, tuple)):
            for result in ghemails:
                if result.get('verified') and not result['email'].endswith(
                        '@users.noreply.github.com'):
                    emails.append(result['email'])
        if emails:
            email = emails[0]
        return {
            'email': email,
            'emails': emails,
            'userid': ghinfo['login'],
            'username': ghinfo['login'],
            'fullname': ghinfo.get('name'),
            'avatar_url': ghinfo.get('avatar_url'),
            'oauth_token': response['access_token'],
            'oauth_token_secret': None,  # OAuth 2 doesn't need token secrets
            'oauth_token_type': response['token_type']
        }
Esempio n. 2
0
 def decorated_function(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except (OAuthException, BadStatusLine, AttributeError, socket_error,
             gaierror) as e:
         raise LoginCallbackError(e)
     except KeyError:
         # XXX: Twitter sometimes returns a 404 with no Content-Type header. This causes a
         # KeyError in the Flask-OAuth library. Catching the KeyError here is a kludge.
         # We need to get Flask-OAuth fixed or stop using it.
         raise LoginCallbackError(
             _("Twitter had an intermittent error. Please try again"))
Esempio n. 3
0
    def unwrapped_callback(self, resp):
        if resp is None:
            raise LoginCallbackError(_("You denied the request to login"))

        # Try to read more from the user's Twitter profile
        auth = TwitterOAuthHandler(self.consumer_key, self.consumer_secret)
        auth.set_access_token(resp['oauth_token'], resp['oauth_token_secret'])
        api = TwitterAPI(auth)
        try:
            twinfo = api.verify_credentials(include_entities='false',
                                            skip_status='true',
                                            include_email='true')
            fullname = twinfo.name
            avatar_url = twinfo.profile_image_url_https.replace(
                '_normal.', '_bigger.')
            email = getattr(twinfo, 'email', None)
        except TweepError:
            fullname = None
            avatar_url = None
            email = None

        return {
            'email': email,
            'userid': resp['user_id'],
            'username': resp['screen_name'],
            'fullname': fullname,
            'avatar_url': avatar_url,
            'oauth_token': resp['oauth_token'],
            'oauth_token_secret': resp['oauth_token_secret'],
            'oauth_token_type': None,  # Twitter doesn't have token types
        }
Esempio n. 4
0
    def unwrapped_callback(self, resp):
        if resp is None:
            raise LoginCallbackError(_("You denied the request to login"))

        # Try to read more from the user's Twitter profile
        auth = TwitterOAuthHandler(self.consumer_key, self.consumer_secret)
        if self.access_key is not None and self.access_secret is not None:
            auth.set_access_token(self.access_key, self.access_secret)
        else:
            auth.set_access_token(resp['oauth_token'],
                                  resp['oauth_token_secret'])
        api = TwitterAPI(auth)
        try:
            twinfo = api.lookup_users(user_ids=[resp['user_id']])[0]
            fullname = twinfo.name
            avatar_url = twinfo.profile_image_url_https.replace(
                '_normal.', '_bigger.')
        except TweepError:
            fullname = None
            avatar_url = None

        return {
            'userid': resp['user_id'],
            'username': resp['screen_name'],
            'fullname': fullname,
            'avatar_url': avatar_url,
            'oauth_token': resp['oauth_token'],
            'oauth_token_secret': resp['oauth_token_secret'],
            'oauth_token_type': None,  # Twitter doesn't have token types
        }
Esempio n. 5
0
    def unwrapped_callback(self, resp):
        if resp is None:
            raise LoginCallbackError("You denied the request to login")

        # Try to read more from the user's Twitter profile
        try:
            twinfo = requests.get('http://api.twitter.com/1/users/lookup.json',
                                  params={
                                      'user_id': resp['user_id']
                                  }).json()[0]
        except:  # Ignore all errors since this data is optional and there are many errors requests could raise
            twinfo = {}

        return {
            'userid':
            resp['user_id'],
            'username':
            resp['screen_name'],
            'fullname':
            twinfo.get('name', '@' + resp['screen_name']),
            'avatar_url':
            twinfo.get('profile_image_url',
                       '').replace("_normal.", "_bigger."),
            'oauth_token':
            resp['oauth_token'],
            'oauth_token_secret':
            resp['oauth_token_secret'],
            'oauth_token_type':
            None,  # Twitter doesn't have token types
        }
Esempio n. 6
0
 def callback(self):
     if 'google_callback' in session:
         callback_url = session.pop('google_callback')
     else:
         raise LoginCallbackError(
             _("Duplicate callback. Did you go back in your browser history?"
               ))
     if request.args.get('error'):
         if request.args['error'] == 'access_denied':
             raise LoginCallbackError(
                 _("You denied the Google login request"))
         else:
             raise LoginCallbackError(_("Unknown failure"))
     code = request.args.get('code', None)
     try:
         credentials = self.flow(callback_url).step2_exchange(code)
         response = requests.get(
             self.info_url,
             headers={
                 'Authorization': (
                     credentials.token_response[
                         'token_type']  # 'Bearer', etc
                     + ' ' + credentials.access_token)
             },
         ).json()
     except Exception as e:
         raise LoginCallbackError(
             _("Unable to authenticate via Google. Internal details: {error}"
               ).format(error=e))
     if response.get('error'):
         raise LoginCallbackError(
             _("Unable to login via Google: {error}").format(
                 error=response['error'].get('message', '')))
     return {
         'email': credentials.id_token['email'],
         'userid': credentials.id_token['email'],
         'username': credentials.id_token['email'],
         'fullname': response.get('name', ''),
         'avatar_url': response.get('picture'),
         'oauth_token': credentials.access_token,
         'oauth_token_secret': None,  # OAuth 2 doesn't need token secrets
         'oauth_token_type': credentials.token_response['token_type'],
     }
Esempio n. 7
0
    def callback(self):
        if request.args.get('error'):
            if request.args['error'] == 'user_denied':
                raise LoginCallbackError(u"You denied the GitHub login request")
            elif request.args['error'] == 'redirect_uri_mismatch':
                # TODO: Log this as an exception for the server admin to look at
                raise LoginCallbackError(u"This server's callback URL is misconfigured")
            else:
                raise LoginCallbackError(u"Unknown failure")
        code = request.args.get('code', None)
        response = requests.post(self.token_url, headers={'Accept': 'application/json'},
            params={
                'client_id': self.key,
                'client_secret': self.secret,
                'code': code
                }
            ).json()
        if 'error' in response:
            raise LoginCallbackError(response['error'])
        ghinfo = requests.get(self.user_info,
            params={'access_token': response['access_token']}).json()
        ghemails = requests.get(self.user_emails,
            params={'access_token': response['access_token']},
            headers={'Accept': 'application/vnd.github.v3+json'}).json()

        email = None
        if ghemails and isinstance(ghemails, (list, tuple)):
            for result in ghemails:
                if result.get('verified'):
                    email = result['email']
                    break  # TODO: Support multiple emails in login providers
        return {'email': email,
                'userid': ghinfo['login'],
                'username': ghinfo['login'],
                'fullname': ghinfo.get('name'),
                'avatar_url': ghinfo.get('avatar_url'),
                'oauth_token': response['access_token'],
                'oauth_token_secret': None,  # OAuth 2 doesn't need token secrets
                'oauth_token_type': response['token_type']
                }
Esempio n. 8
0
    def callback(self):
        state = session.pop('linkedin_state', None)
        callback_url = session.pop('linkedin_callback', None)
        if state is None or request.args.get('state') != state:
            raise LoginCallbackError(
                "We detected a possible attempt at cross-site request forgery")
        if 'error' in request.args:
            if request.args['error'] == 'access_denied':
                raise LoginCallbackError(
                    u"You denied the LinkedIn login request")
            elif request.args['error'] == 'redirect_uri_mismatch':
                # TODO: Log this as an exception for the server admin to look at
                raise LoginCallbackError(
                    u"This server's callback URL is misconfigured")
            else:
                raise LoginCallbackError(u"Unknown failure")
        code = request.args.get('code', None)
        try:
            response = requests.post(self.token_url,
                                     headers={
                                         'Accept': 'application/json'
                                     },
                                     params={
                                         'grant_type': 'authorization_code',
                                         'client_id': self.key,
                                         'client_secret': self.secret,
                                         'code': code,
                                         'redirect_uri': callback_url,
                                     }).json()
        except requests.ConnectionError as e:
            raise LoginCallbackError(
                u"Unable to authenticate via LinkedIn. Internal details: {error}"
                .format(error=e))
        if 'error' in response:
            raise LoginCallbackError(response['error'])
        info = requests.get(self.user_info,
                            params={
                                'oauth2_access_token': response['access_token']
                            },
                            headers={
                                'x-li-format': 'json'
                            }).json()

        return {
            'email': info.get('emailAddress'),
            'userid': info.get('id'),
            'username': info.get('publicProfileUrl'),
            'fullname': info.get('formattedName'),
            'avatar_url': info.get('pictureUrl'),
            'oauth_token': response['access_token'],
            'oauth_token_secret': None,  # OAuth 2 doesn't need token secrets
            'oauth_token_type': None
        }
Esempio n. 9
0
    def callback(self):
        state = session.pop('linkedin_state', None)
        callback_url = session.pop('linkedin_callback', None)
        if state is None or request.args.get('state') != state:
            raise LoginCallbackError(
                _("We detected a possible attempt at cross-site request forgery"
                  ))
        if 'error' in request.args:
            if request.args['error'] == 'access_denied':
                raise LoginCallbackError(
                    _("You denied the LinkedIn login request"))
            elif request.args['error'] == 'redirect_uri_mismatch':
                # TODO: Log this as an exception for the server admin to look at
                raise LoginCallbackError(
                    _("This server's callback URL is misconfigured"))
            else:
                raise LoginCallbackError(_("Unknown failure"))
        code = request.args.get('code', None)
        try:
            response = requests.post(
                self.token_url,
                headers={
                    'Accept': 'application/json'
                },
                params={
                    'grant_type': 'authorization_code',
                    'client_id': self.key,
                    'client_secret': self.secret,
                    'code': code,
                    'redirect_uri': callback_url,
                },
            ).json()
        except requests.exceptions.RequestException as e:
            raise LoginCallbackError(
                _("Unable to authenticate via LinkedIn. Internal details: {error}"
                  ).format(error=e))
        if 'error' in response:
            raise LoginCallbackError(response['error'])
        try:
            info = requests.get(
                self.user_info,
                params={
                    'oauth2_access_token': response['access_token']
                },
                headers={
                    'x-li-format': 'json'
                },
            ).json()
        except requests.exceptions.RequestException as e:
            raise LoginCallbackError(
                _("Unable to authenticate via LinkedIn. Internal details: {error}"
                  ).format(error=e))

        if not info.get('id'):
            raise LoginCallbackError(
                _("Unable to retrieve user details from LinkedIn. Please try again"
                  ))

        try:
            email_info = requests.get(
                self.user_email,
                params={
                    'oauth2_access_token': response['access_token']
                },
                headers={
                    'x-li-format': 'json'
                },
            ).json()
        except requests.exceptions.RequestException as e:
            raise LoginCallbackError(
                _("Unable to fetch email from LinkedIn. Internal details: {error}"
                  ).format(error=e))

        email_address = ''
        if 'elements' in email_info and email_info['elements']:
            email_address = email_info['elements'][0]['handle~'][
                'emailAddress']

        return {
            'email':
            email_address,
            'userid':
            info.get('id'),
            'username':
            info.get('id'),
            'fullname': (info.get('localizedFirstName') + ' ' +
                         info.get('localizedLastName')),
            'avatar_url':
            '',
            'oauth_token':
            response['access_token'],
            'oauth_token_secret':
            None,  # OAuth 2 doesn't need token secrets
            'oauth_token_type':
            None,
        }
Esempio n. 10
0
 def decorated_function(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except HTTPFetchingError as e:
         raise LoginCallbackError(e)
Esempio n. 11
0
 def decorated_function(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except (OAuthException, BadStatusLine, AttributeError, socket_error,
             gaierror) as e:
         raise LoginCallbackError(e)