Esempio n. 1
0
  def get(self):
    code = util.get_required_param(self, 'code')
    state = util.decode_oauth_state(util.get_required_param(self, 'state'))

    endpoint = state.get('endpoint')
    me = state.get('me')
    if not endpoint or not me:
        raise exc.HTTPBadRequest("invalid state parameter")

    state = state.get('state') or ''
    validate_resp = util.requests_post(endpoint, data={
      'me': me,
      'client_id': appengine_config.INDIEAUTH_CLIENT_ID,
      'code': code,
      'redirect_uri': self.request.path_url,
      'state': state,
    })

    if validate_resp.status_code // 100 == 2:
      data = util.sniff_json_or_form_encoded(validate_resp.content)
      if data.get('me'):
        verified = data.get('me')
        user_json = build_user_json(verified)
        indie_auth = IndieAuth(id=verified, user_json=json.dumps(user_json))
        indie_auth.put()
        self.finish(indie_auth, state=state)
      else:
        raise exc.HTTPBadRequest(
          'Verification response missing required "me" field')
    else:
      raise exc.HTTPBadRequest('IndieAuth verification failed: %s %s' %
                               (validate_resp.status_code, validate_resp.text))
Esempio n. 2
0
  def redirect_url(self, state=None, me=None):
    assert appengine_config.INDIEAUTH_CLIENT_ID, (
      "Please fill in the indieauth_client_id in your app's root directory.")

    if not me:
      me = util.get_required_param(self, 'me')
    parsed = urlparse.urlparse(me)
    if not parsed.scheme:
      me = 'http://' + me

    redirect_uri = self.to_url()
    endpoint = discover_authorization_endpoint(me)

    url = endpoint + '?' + urllib.urlencode({
      'me': me,
      'client_id': appengine_config.INDIEAUTH_CLIENT_ID,
      'redirect_uri': redirect_uri,
      'state': util.encode_oauth_state({
        'endpoint': endpoint,
        'me': me,
        'state': state,
      }),
    })

    logging.info('Redirecting to IndieAuth: %s', url)
    return str(url)
Esempio n. 3
0
    def get(self):
        # handle errors
        error = self.request.get('error')
        if error:
            if error == 'access_denied':
                logging.info('User declined')
                self.finish(None, state=self.request.get('state'))
                return
            else:
                raise exc.HTTPBadRequest('Error: %s' % error)

        # extract auth code and request access token
        auth_code = util.get_required_param(self, 'code')
        data = {
            'code': auth_code,
            'client_id': appengine_config.MEDIUM_CLIENT_ID,
            'client_secret': appengine_config.MEDIUM_CLIENT_SECRET,
            # redirect_uri here must be the same in the oauth code request!
            # (the value here doesn't actually matter since it's requested server side.)
            'redirect_uri': self.request.path_url,
            'grant_type': 'authorization_code',
        }
        resp = util.requests_post(GET_ACCESS_TOKEN_URL,
                                  data=urllib.urlencode(data),
                                  headers={
                                      'User-Agent': USER_AGENT
                                  }).text
        logging.debug('Access token response: %s', resp)

        try:
            resp = json.loads(resp)
        except:
            logging.exception('Could not decode JSON')
            raise

        errors = resp.get('errors') or resp.get('error')
        if errors:
            logging.info('Errors: %s', errors)
            raise exc.HTTPBadRequest(errors[0].get('message'))

        # TODO: handle refresh token
        access_token = resp['access_token']
        user_json = MediumAuth(
            access_token_str=access_token).get(API_USER_URL).text
        id = json.loads(user_json)['data']['id']
        auth = MediumAuth(id=id,
                          access_token_str=access_token,
                          user_json=user_json)
        auth.put()

        self.finish(auth, state=self.request.get('state'))
Esempio n. 4
0
  def get(self):
    state = util.get_required_param(self, 'state')

    # handle errors
    error = self.request.get('error')
    error_reason = urllib.unquote_plus(self.request.get('error_reason', ''))

    if error or error_reason:
      if error == 'access_denied':
        logging.info('User declined: %s', error_reason)
        self.finish(None, state=state)
        return
      else:
        raise exc.HTTPBadRequest(' '.join((error, error_reason)))

    # lookup the CSRF token
    try:
      csrf_id = int(urllib.unquote_plus(state).split('|')[-1])
    except (ValueError, TypeError):
      raise exc.HTTPBadRequest('Invalid state value %r' % state)

    csrf = DropboxCsrf.get_by_id(csrf_id)
    if not csrf:
      raise exc.HTTPBadRequest('No CSRF token for id %s' % csrf_id)

    # request an access token
    data = {
      'client_id': appengine_config.DROPBOX_APP_KEY,
      'client_secret': appengine_config.DROPBOX_APP_SECRET,
      'code': util.get_required_param(self, 'code'),
      'redirect_uri': self.request.path_url,
    }
    try:
      resp = util.urlopen(GET_ACCESS_TOKEN_URL % data, data='').read()
    except BaseException, e:
      util.interpret_http_exception(e)
      raise
Esempio n. 5
0
  def get(self):
    if CallbackHandler.handle_error(self):
      return

    auth_code = util.get_required_param(self, 'code')
    url = GET_ACCESS_TOKEN_URL % {
      'auth_code': auth_code,
      'client_id': appengine_config.FACEBOOK_APP_ID,
      'client_secret': appengine_config.FACEBOOK_APP_SECRET,
      'redirect_uri': urllib.quote_plus(self.request.path_url),
      }
    try:
      resp = json.loads(util.urlopen(url).read())
    except urllib2.HTTPError, e:
      logging.error(e.read())
      raise
Esempio n. 6
0
    def get(self):
        # handle errors
        error = self.request.get('error')
        if error:
            if error == 'access_denied':
                logging.info('User declined')
                self.finish(None, state=self.request.get('state'))
                return
            else:
                msg = 'Error: %s: %s' % (error,
                                         self.request.get('error_description'))
                logging.info(msg)
                raise exc.HTTPBadRequest(msg)

        # extract auth code and request access token
        auth_code = util.get_required_param(self, 'code')
        data = {
            'code': auth_code,
            'client_id': appengine_config.GITHUB_CLIENT_ID,
            'client_secret': appengine_config.GITHUB_CLIENT_SECRET,
            # redirect_uri here must be the same in the oauth code request!
            # (the value here doesn't actually matter since it's requested server side.)
            'redirect_uri': self.request.path_url,
        }
        resp = util.requests_post(GET_ACCESS_TOKEN_URL,
                                  data=urllib.urlencode(data)).text
        logging.debug('Access token response: %s', resp)

        resp = urlparse.parse_qs(resp)

        error = resp.get('error')
        if error:
            msg = 'Error: %s: %s' % (error[0], resp.get('error_description'))
            logging.info(msg)
            raise exc.HTTPBadRequest(msg)

        access_token = resp['access_token'][0]
        resp = GitHubAuth(access_token_str=access_token).post(
            API_GRAPHQL, json=GRAPHQL_USER).json()
        logging.debug('GraphQL data.viewer response: %s', resp)
        user_json = resp['data']['viewer']
        auth = GitHubAuth(id=user_json['login'],
                          access_token_str=access_token,
                          user_json=json.dumps(user_json))
        auth.put()

        self.finish(auth, state=self.request.get('state'))
Esempio n. 7
0
    def get(self):
        # handle errors
        error = self.request.get('error')
        if error:
            error_description = urllib.unquote_plus(
                self.request.get('error_description', ''))
            if error == 'access_denied':
                logging.info('User declined: %s', error_description)
                self.finish(None, state=self.request.get('state'))
                return
            else:
                raise exc.HTTPBadRequest('Error: %s %s ' %
                                         (error, error_description))

        # extract auth code and request access token
        auth_code = util.get_required_param(self, 'code')
        data = {
            'code': auth_code,
            'client_id': appengine_config.WORDPRESS_CLIENT_ID,
            'client_secret': appengine_config.WORDPRESS_CLIENT_SECRET,
            # redirect_uri here must be the same in the oauth code request!
            # (the value here doesn't actually matter since it's requested server side.)
            'redirect_uri': self.request.path_url,
            'grant_type': 'authorization_code',
        }
        resp = util.urlopen(GET_ACCESS_TOKEN_URL,
                            data=urllib.urlencode(data)).read()
        logging.debug('Access token response: %s', resp)

        try:
            resp = json.loads(resp)
            blog_id = resp['blog_id']
            blog_url = resp['blog_url']
            blog_domain = util.domain_from_link(resp['blog_url'])
            access_token = resp['access_token']
        except:
            logging.exception('Could not decode JSON')
            raise

        auth = WordPressAuth(id=blog_domain,
                             blog_id=blog_id,
                             blog_url=blog_url,
                             access_token_str=access_token)
        auth.user_json = auth.urlopen(API_USER_URL).read()
        auth.put()

        self.finish(auth, state=self.request.get('state'))
Esempio n. 8
0
  def get(self):
    # handle errors
    error = self.request.get('error')
    if error:
      if error == 'access_denied':
        logging.info('User declined')
        self.finish(None, state=self.request.get('state'))
        return
      else:
        raise exc.HTTPBadRequest('Error: %s' % error)

    # extract auth code and request access token
    auth_code = util.get_required_param(self, 'code')
    data = {
      'code': auth_code,
      'client_id': appengine_config.MEDIUM_CLIENT_ID,
      'client_secret': appengine_config.MEDIUM_CLIENT_SECRET,
      # redirect_uri here must be the same in the oauth code request!
      # (the value here doesn't actually matter since it's requested server side.)
      'redirect_uri': self.request.path_url,
      'grant_type': 'authorization_code',
      }
    resp = util.requests_post(
      GET_ACCESS_TOKEN_URL, data=urllib.urlencode(data),
      headers={'User-Agent': USER_AGENT}).text
    logging.debug('Access token response: %s', resp)

    try:
      resp = json.loads(resp)
    except:
      logging.exception('Could not decode JSON')
      raise

    errors = resp.get('errors') or resp.get('error')
    if errors:
      logging.info('Errors: %s', errors)
      raise exc.HTTPBadRequest(errors[0].get('message'))

    # TODO: handle refresh token
    access_token = resp['access_token']
    user_json = MediumAuth(access_token_str=access_token).get(API_USER_URL).text
    id = json.loads(user_json)['data']['id']
    auth = MediumAuth(id=id, access_token_str=access_token, user_json=user_json)
    auth.put()

    self.finish(auth, state=self.request.get('state'))
Esempio n. 9
0
  def get(self):
    # handle errors
    error = self.request.get('error')
    if error:
      if error == 'access_denied':
        logging.info('User declined')
        self.finish(None, state=self.request.get('state'))
        return
      else:
        msg = 'Error: %s: %s' % (error, self.request.get('error_description'))
        logging.info(msg)
        raise exc.HTTPBadRequest(msg)

    # extract auth code and request access token
    auth_code = util.get_required_param(self, 'code')
    data = {
      'code': auth_code,
      'client_id': appengine_config.GITHUB_CLIENT_ID,
      'client_secret': appengine_config.GITHUB_CLIENT_SECRET,
      # redirect_uri here must be the same in the oauth code request!
      # (the value here doesn't actually matter since it's requested server side.)
      'redirect_uri': self.request.path_url,
      }
    resp = util.requests_post(GET_ACCESS_TOKEN_URL,
                              data=urllib.urlencode(data)).text
    logging.debug('Access token response: %s', resp)

    resp = urlparse.parse_qs(resp)

    error = resp.get('error')
    if error:
      msg = 'Error: %s: %s' % (error[0], resp.get('error_description'))
      logging.info(msg)
      raise exc.HTTPBadRequest(msg)

    access_token = resp['access_token'][0]
    resp = GitHubAuth(access_token_str=access_token).post(
        API_GRAPHQL, json=GRAPHQL_USER).json()
    logging.debug('GraphQL data.viewer response: %s', resp)
    user_json = resp['data']['viewer']
    auth = GitHubAuth(id=user_json['login'], access_token_str=access_token,
                      user_json=json.dumps(user_json))
    auth.put()

    self.finish(auth, state=self.request.get('state'))
Esempio n. 10
0
    def get(self):
        if self.handle_error():
            return

        # https://disqus.com/api/docs/auth/
        auth_code = util.get_required_param(self, 'code')
        data = {
            'grant_type': 'authorization_code',
            'client_id': appengine_config.DISQUS_CLIENT_ID,
            'client_secret': appengine_config.DISQUS_CLIENT_SECRET,
            'redirect_uri': self.request_url_with_state(),
            'code': auth_code,
        }

        resp = util.urlopen(GET_ACCESS_TOKEN_URL,
                            data=urllib.urlencode(data)).read()
        try:
            data = json.loads(resp)
        except (ValueError, TypeError):
            logging.exception('Bad response:\n%s', resp)
            raise exc.HttpBadRequest(
                'Bad Disqus response to access token request')

        access_token = data['access_token']
        user_id = data['user_id']
        # TODO is a username key preferred?
        # username = data['username']

        auth = DisqusAuth(id=str(user_id),
                          auth_code=auth_code,
                          access_token_str=access_token)

        resp = auth.urlopen(USER_DETAILS_URL % user_id).read()
        try:
            user_data = json.loads(resp)['response']
        except (ValueError, TypeError):
            logging.exception('Bad response:\n%s', resp)
            raise exc.HttpBadRequest(
                'Bad Disqus response to user details request')

        auth.user_json = json.dumps(user_data)
        logging.info('created disqus auth %s', auth)
        auth.put()
        self.finish(auth, state=self.request.get('state'))
Esempio n. 11
0
  def get(self):
    if facebook.CallbackHandler.handle_error(self):
      return

    # http://instagram.com/developer/authentication/
    auth_code = util.get_required_param(self, 'code')
    data = {
      'client_id': appengine_config.INSTAGRAM_CLIENT_ID,
      'client_secret': appengine_config.INSTAGRAM_CLIENT_SECRET,
      'code': auth_code,
      'redirect_uri': self.request_url_with_state(),
      'grant_type': 'authorization_code',
    }

    try:
      resp = util.urlopen(GET_ACCESS_TOKEN_URL, data=urllib.urlencode(data)).read()
    except BaseException, e:
      util.interpret_http_exception(e)
      raise
Esempio n. 12
0
    def get(self):
        if facebook.CallbackHandler.handle_error(self):
            return

        # http://instagram.com/developer/authentication/
        auth_code = util.get_required_param(self, 'code')
        data = {
            'client_id': appengine_config.INSTAGRAM_CLIENT_ID,
            'client_secret': appengine_config.INSTAGRAM_CLIENT_SECRET,
            'code': auth_code,
            'redirect_uri': self.request_url_with_state(),
            'grant_type': 'authorization_code',
        }

        try:
            resp = util.urlopen(GET_ACCESS_TOKEN_URL,
                                data=urllib.urlencode(data)).read()
        except BaseException, e:
            util.interpret_http_exception(e)
            raise
Esempio n. 13
0
  def get(self):
    if self.handle_error():
      return

    # https://disqus.com/api/docs/auth/
    auth_code = util.get_required_param(self, 'code')
    data = {
        'grant_type': 'authorization_code',
        'client_id': appengine_config.DISQUS_CLIENT_ID,
        'client_secret': appengine_config.DISQUS_CLIENT_SECRET,
        'redirect_uri': self.request_url_with_state(),
        'code': auth_code,
    }

    resp = util.urlopen(GET_ACCESS_TOKEN_URL, data=urllib.urlencode(data)).read()
    try:
      data = json.loads(resp)
    except (ValueError, TypeError):
      logging.exception('Bad response:\n%s', resp)
      raise exc.HttpBadRequest('Bad Disqus response to access token request')

    access_token = data['access_token']
    user_id = data['user_id']
    # TODO is a username key preferred?
    # username = data['username']

    auth = DisqusAuth(id=str(user_id),
                      auth_code=auth_code,
                      access_token_str=access_token)

    resp = auth.urlopen(USER_DETAILS_URL % user_id).read()
    try:
      user_data = json.loads(resp)['response']
    except (ValueError, TypeError):
      logging.exception('Bad response:\n%s', resp)
      raise exc.HttpBadRequest('Bad Disqus response to user details request')

    auth.user_json = json.dumps(user_data)
    logging.info('created disqus auth %s', auth)
    auth.put()
    self.finish(auth, state=self.request.get('state'))
Esempio n. 14
0
  def get(self):
    # handle errors
    error = self.request.get('error')
    desc = self.request.get('error_description')
    if error:
      # https://docs.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow?context=linkedin/consumer/context#application-is-rejected
      if error in ('user_cancelled_login', 'user_cancelled_authorize'):
        logging.info('User declined: %s', self.request.get('error_description'))
        self.finish(None, state=self.request.get('state'))
        return
      else:
        msg = 'Error: %s: %s' % (error, desc)
        logging.info(msg)
        raise exc.HTTPBadRequest(msg)

    # extract auth code and request access token
    auth_code = util.get_required_param(self, 'code')
    data = {
      'grant_type': 'authorization_code',
      'code': auth_code,
      'client_id': appengine_config.LINKEDIN_CLIENT_ID,
      'client_secret': appengine_config.LINKEDIN_CLIENT_SECRET,
      # redirect_uri here must be the same in the oauth code request!
      # (the value here doesn't actually matter since it's requested server side.)
      'redirect_uri': self.request.path_url,
      }
    resp = util.requests_post(ACCESS_TOKEN_URL, data=urllib.urlencode(data)).json()
    logging.debug('Access token response: %s', resp)
    if resp.get('serviceErrorCode'):
      msg = 'Error: %s' % resp
      logging.info(msg)
      raise exc.HTTPBadRequest(msg)

    access_token = resp['access_token']
    resp = LinkedInAuth(access_token_str=access_token).get(API_PROFILE_URL).json()
    logging.debug('Profile response: %s', resp)
    auth = LinkedInAuth(id=resp['id'], access_token_str=access_token,
                        user_json=json.dumps(resp))
    auth.put()

    self.finish(auth, state=self.request.get('state'))