コード例 #1
0
    def get_user_details(self, response):
        """
        Gets the user details from Special:OAuth/identify
        """
        key, secret = self.get_key_and_secret()
        access_token = response['access_token']

        auth = OAuth1(key,
                      client_secret=secret,
                      resource_owner_key=access_token['oauth_token'],
                      resource_owner_secret=access_token['oauth_token_secret'])

        req_resp = requests.post(url=self.setting('MEDIAWIKI_URL'),
                                 params={'title': 'Special:OAuth/identify'},
                                 auth=auth)

        try:
            identity = jwt.decode(req_resp.content,
                                  secret,
                                  audience=key,
                                  algorithms=['HS256'],
                                  leeway=self.LEEWAY)
        except jwt.InvalidTokenError as exception:
            raise AuthException(
                self, 'An error occurred while trying to read json ' +
                'content: {0}'.format(exception))

        issuer = urlparse(identity['iss']).netloc
        expected_domain = urlparse(self.setting('MEDIAWIKI_URL')).netloc

        if not issuer == expected_domain:
            raise AuthException(
                self, 'Unexpected issuer {0}, expected {1}'.format(
                    issuer, expected_domain))

        now = time.time()
        issued_at = float(identity['iat'])
        if not now >= (issued_at - self.LEEWAY):
            raise AuthException(
                self,
                'Identity issued {0} seconds in the future'.format(issued_at -
                                                                   now))

        authorization_header = force_unicode(
            req_resp.request.headers['Authorization'])
        request_nonce = re.search(r'oauth_nonce="(.*?)"',
                                  authorization_header).group(1)

        if identity['nonce'] != request_nonce:
            raise AuthException(
                self, 'Replay attack detected: {0} != {1}'.format(
                    identity['nonce'], request_nonce))

        return {'username': identity['username'], 'userID': identity['sub']}
コード例 #2
0
def associate_by_email(backend, details, user=None, *args, **kwargs):
    """
    Associate current auth with a user with the same email address in the DB.

    This pipeline entry is not 100% secure unless you know that the providers
    enabled enforce email verification on their side, otherwise a user can
    attempt to take over another user account by using the same (not validated)
    email address on some provider.  This pipeline entry is disabled by
    default.
    """
    if user:
        return None

    email = details.get('email')
    if email:
        # Try to associate accounts registered with the same email address,
        # only if it's a single object. AuthException is raised if multiple
        # objects are returned.
        users = list(backend.strategy.storage.user.get_users_by_email(email))
        if len(users) == 0:
            return None
        elif len(users) > 1:
            raise AuthException(
                backend,
                'The given email address is associated with another account')
        else:
            return {'user': users[0], 'is_new': False}
コード例 #3
0
    def unauthorized_token(self):
        """
        Return request for unauthorized token (first stage)

        Mediawiki request token is requested from e.g.:
         * https://en.wikipedia.org/w/index.php?title=Special:OAuth/initiate
        """
        params = self.request_token_extra_arguments()
        params.update(self.get_scope_argument())
        params['title'] = 'Special:OAuth/initiate'
        key, secret = self.get_key_and_secret()
        decoding = None if six.PY3 else 'utf-8'
        response = self.request(self.setting('MEDIAWIKI_URL'),
                                params=params,
                                auth=OAuth1(
                                    key,
                                    secret,
                                    callback_uri=self.setting('CALLBACK'),
                                    decoding=decoding),
                                method=self.REQUEST_TOKEN_METHOD)

        if response.content.decode().startswith('Error'):
            raise AuthException(self, response.content.decode())

        return response.content.decode()
コード例 #4
0
 def openid_request(self, params=None):
     """Return openid request"""
     try:
         return self.consumer().begin(
             url_add_parameters(self.openid_url(), params))
     except DiscoveryFailure as err:
         raise AuthException(self,
                             'OpenID discovery error: {0}'.format(err))
コード例 #5
0
 def process_error(self, data):
     if not data:
         raise AuthException(self, 'OpenID relying party endpoint')
     elif data.status == FAILURE:
         raise AuthFailed(self, data.message)
     elif data.status == CANCEL:
         raise AuthCanceled(self)
     elif data.status != SUCCESS:
         raise AuthUnknownError(self, data.status)
コード例 #6
0
    def auth_complete(self, *args, **kwargs):
        access_token = self.data.get('access_token')
        response = {}

        if 'signed_request' in self.data:
            key, secret = self.get_key_and_secret()
            response = self.load_signed_request(self.data['signed_request'])
            if 'user_id' not in response and 'oauth_token' not in response:
                raise AuthException(self)

            if response is not None:
                access_token = response.get('access_token') or \
                               response.get('oauth_token') or \
                               self.data.get('access_token')

        if access_token is None:
            if self.data.get('error') == 'access_denied':
                raise AuthCanceled(self)
            else:
                raise AuthException(self)
        return self.do_auth(access_token, response, *args, **kwargs)
コード例 #7
0
    def user_data(self, access_token, *args, **kwargs):
        """Loads user data from service"""
        request_data = ['first_name', 'last_name', 'screen_name', 'nickname',
                        'photo'] + self.setting('EXTRA_DATA', [])

        fields = ','.join(set(request_data))
        data = vk_api(self, 'users.get', {
            'access_token': access_token,
            'fields': fields,
        })

        if data and data.get('error'):
            error = data['error']
            msg = error.get('error_msg', 'Unknown error')
            if error.get('error_code') == 5:
                raise AuthTokenRevoked(self, msg)
            else:
                raise AuthException(self, msg)

        if data:
            data = data.get('response')[0]
            data['user_photo'] = data.get('photo')  # Backward compatibility
        return data or {}
コード例 #8
0
 def policy(self):
     policy = self.setting('POLICY')
     if not policy or not policy.lower().startswith('b2c_'):
         raise AuthException('SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_POLICY is '
                             'required and should start with `b2c_`')
     return policy
コード例 #9
0
 def auth_complete(self, *args, **kwargs):
     """Completes login process, must return user instance."""
     if not users.get_current_user():
         raise AuthException('Authentication error')
     kwargs.update({'response': '', 'backend': self})
     return self.strategy.authenticate(*args, **kwargs)