Beispiel #1
0
    def get_authenticated_user(self, callback, http_client=None):
        """Gets the OAuth authorized user and access token on callback.

        This method should be called from the handler for your registered
        OAuth Callback URL to complete the registration process. We call
        callback with the authenticated user, which in addition to standard
        attributes like 'name' includes the 'access_key' attribute, which
        contains the OAuth access you can use to make authorized requests
        to this service on behalf of the user.

        """
        request_key = escape.utf8(self.get_argument("oauth_token"))
        oauth_verifier = self.get_argument("oauth_verifier", None)
        request_cookie = self.get_cookie("_oauth_request_token")
        if not request_cookie:
            logging.warning("Missing OAuth request token cookie")
            callback(None)
            return
        self.clear_cookie("_oauth_request_token")
        cookie_key, cookie_secret = [
            base64.b64decode(escape.utf8(i)) for i in request_cookie.split("|")
        ]
        if cookie_key != request_key:
            logging.info((cookie_key, request_key, request_cookie))
            logging.warning("Request token does not match cookie")
            callback(None)
            return
        token = dict(key=cookie_key, secret=cookie_secret)
        if oauth_verifier:
            token["verifier"] = oauth_verifier
        if http_client is None:
            http_client = httpclient.AsyncHTTPClient()
        http_client.fetch(self._oauth_access_token_url(token),
                          self.async_callback(self._on_access_token, callback))
Beispiel #2
0
    def authorize_redirect(self,
                           callback_uri=None,
                           extra_params=None,
                           http_client=None):
        """Redirects the user to obtain OAuth authorization for this service.

        Twitter and FriendFeed both require that you register a Callback
        URL with your application. You should call this method to log the
        user in, and then call get_authenticated_user() in the handler
        you registered as your Callback URL to complete the authorization
        process.

        This method sets a cookie called _oauth_request_token which is
        subsequently used (and cleared) in get_authenticated_user for
        security purposes.
        """
        if callback_uri and getattr(self, "_OAUTH_NO_CALLBACKS", False):
            raise Exception("This service does not support oauth_callback")
        if http_client is None:
            http_client = httpclient.AsyncHTTPClient()
        if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a":
            http_client.fetch(
                self._oauth_request_token_url(callback_uri=callback_uri,
                                              extra_params=extra_params),
                self.async_callback(self._on_request_token,
                                    self._OAUTH_AUTHORIZE_URL, callback_uri))
        else:
            http_client.fetch(
                self._oauth_request_token_url(),
                self.async_callback(self._on_request_token,
                                    self._OAUTH_AUTHORIZE_URL, callback_uri))
Beispiel #3
0
    def facebook_request(self,
                         path,
                         callback,
                         access_token=None,
                         post_args=None,
                         **args):
        """Fetches the given relative API path, e.g., "/btaylor/picture"

        If the request is a POST, post_args should be provided. Query
        string arguments should be given as keyword arguments.

        An introduction to the Facebook Graph API can be found at
        http://developers.facebook.com/docs/api

        Many methods require an OAuth access token which you can obtain
        through authorize_redirect() and get_authenticated_user(). The
        user returned through that process includes an 'access_token'
        attribute that can be used to make authenticated requests via
        this method. Example usage::

            class MainHandler(anzu.web.RequestHandler,
                              anzu.auth.FacebookGraphMixin):
                @anzu.web.authenticated
                @anzu.web.asynchronous
                def get(self):
                    self.facebook_request(
                        "/me/feed",
                        post_args={"message": "I am posting from my Anzu application!"},
                        access_token=self.current_user["access_token"],
                        callback=self.async_callback(self._on_post))

                def _on_post(self, new_entry):
                    if not new_entry:
                        # Call failed; perhaps missing permission?
                        self.authorize_redirect()
                        return
                    self.finish("Posted a message!")

        """
        url = "https://graph.facebook.com" + path
        all_args = {}
        if access_token:
            all_args["access_token"] = access_token
            all_args.update(args)
            all_args.update(post_args or {})
        if all_args: url += "?" + urllib.urlencode(all_args)
        callback = self.async_callback(self._on_facebook_request, callback)
        http = httpclient.AsyncHTTPClient()
        if post_args is not None:
            http.fetch(url,
                       method="POST",
                       body=urllib.urlencode(post_args),
                       callback=callback)
        else:
            http.fetch(url, callback=callback)
Beispiel #4
0
    def authenticate_redirect(self):
        """Just like authorize_redirect(), but auto-redirects if authorized.

        This is generally the right interface to use if you are using
        Twitter for single-sign on.
        """
        http = httpclient.AsyncHTTPClient()
        http.fetch(
            self._oauth_request_token_url(),
            self.async_callback(self._on_request_token,
                                self._OAUTH_AUTHENTICATE_URL, None))
Beispiel #5
0
    def get_authenticated_user(self,
                               redirect_uri,
                               client_id,
                               client_secret,
                               code,
                               callback,
                               extra_fields=None):
        """Handles the login for the Facebook user, returning a user object.

      Example usage::

          class FacebookGraphLoginHandler(LoginHandler, anzu.auth.FacebookGraphMixin):
            @anzu.web.asynchronous
            def get(self):
                if self.get_argument("code", False):
                    self.get_authenticated_user(
                      redirect_uri='/auth/facebookgraph/',
                      client_id=self.settings["facebook_api_key"],
                      client_secret=self.settings["facebook_secret"],
                      code=self.get_argument("code"),
                      callback=self.async_callback(
                        self._on_login))
                    return
                self.authorize_redirect(redirect_uri='/auth/facebookgraph/',
                                        client_id=self.settings["facebook_api_key"],
                                        extra_params={"scope": "read_stream,offline_access"})

            def _on_login(self, user):
              logging.error(user)
              self.finish()

      """
        http = httpclient.AsyncHTTPClient()
        args = {
            "redirect_uri": redirect_uri,
            "code": code,
            "client_id": client_id,
            "client_secret": client_secret,
        }

        fields = set([
            'id', 'name', 'first_name', 'last_name', 'locale', 'picture',
            'link'
        ])
        if extra_fields: fields.update(extra_fields)

        http.fetch(
            self._oauth_request_token_url(**args),
            self.async_callback(self._on_access_token, redirect_uri, client_id,
                                client_secret, callback, fields))
Beispiel #6
0
    def facebook_request(self, method, callback, **args):
        """Makes a Facebook API REST request.

        We automatically include the Facebook API key and signature, but
        it is the callers responsibility to include 'session_key' and any
        other required arguments to the method.

        The available Facebook methods are documented here:
        http://wiki.developers.facebook.com/index.php/API

        Here is an example for the stream.get() method::

            class MainHandler(anzu.web.RequestHandler,
                              anzu.auth.FacebookMixin):
                @anzu.web.authenticated
                @anzu.web.asynchronous
                def get(self):
                    self.facebook_request(
                        method="stream.get",
                        callback=self.async_callback(self._on_stream),
                        session_key=self.current_user["session_key"])

                def _on_stream(self, stream):
                    if stream is None:
                       # Not authorized to read the stream yet?
                       self.redirect(self.authorize_redirect("read_stream"))
                       return
                    self.render("stream.html", stream=stream)

        """
        self.require_setting("facebook_api_key", "Facebook Connect")
        self.require_setting("facebook_secret", "Facebook Connect")
        if not method.startswith("facebook."):
            method = "facebook." + method
        args["api_key"] = self.settings["facebook_api_key"]
        args["v"] = "1.0"
        args["method"] = method
        args["call_id"] = str(long(time.time() * 1e6))
        args["format"] = "json"
        args["sig"] = self._signature(args)
        url = "http://api.facebook.com/restserver.php?" + \
            urllib.urlencode(args)
        http = httpclient.AsyncHTTPClient()
        http.fetch(url,
                   callback=self.async_callback(self._parse_response,
                                                callback))
Beispiel #7
0
    def get_authenticated_user(self, callback, http_client=None):
        """Fetches the authenticated user data upon redirect.

        This method should be called by the handler that receives the
        redirect from the authenticate_redirect() or authorize_redirect()
        methods.
        """
        # Verify the OpenID response via direct request to the OP
        args = dict((k, v[-1]) for k, v in self.request.arguments.iteritems())
        args["openid.mode"] = u"check_authentication"
        url = self._OPENID_ENDPOINT
        if http_client is None: http_client = httpclient.AsyncHTTPClient()
        http_client.fetch(url,
                          self.async_callback(self._on_authentication_verified,
                                              callback),
                          method="POST",
                          body=urllib.urlencode(args))
Beispiel #8
0
 def get_authenticated_user(self, callback):
     """Fetches the authenticated user data upon redirect."""
     # Look to see if we are doing combined OpenID/OAuth
     oauth_ns = ""
     for name, values in self.request.arguments.iteritems():
         if name.startswith("openid.ns.") and \
            values[-1] == u"http://specs.openid.net/extensions/oauth/1.0":
             oauth_ns = name[10:]
             break
     token = self.get_argument("openid." + oauth_ns + ".request_token", "")
     if token:
         http = httpclient.AsyncHTTPClient()
         token = dict(key=token, secret="")
         http.fetch(self._oauth_access_token_url(token),
                    self.async_callback(self._on_access_token, callback))
     else:
         OpenIdMixin.get_authenticated_user(self, callback)
Beispiel #9
0
    def friendfeed_request(self,
                           path,
                           callback,
                           access_token=None,
                           post_args=None,
                           **args):
        """Fetches the given relative API path, e.g., "/bret/friends"

        If the request is a POST, post_args should be provided. Query
        string arguments should be given as keyword arguments.

        All the FriendFeed methods are documented at
        http://friendfeed.com/api/documentation.

        Many methods require an OAuth access token which you can obtain
        through authorize_redirect() and get_authenticated_user(). The
        user returned through that process includes an 'access_token'
        attribute that can be used to make authenticated requests via
        this method. Example usage::

            class MainHandler(anzu.web.RequestHandler,
                              anzu.auth.FriendFeedMixin):
                @anzu.web.authenticated
                @anzu.web.asynchronous
                def get(self):
                    self.friendfeed_request(
                        "/entry",
                        post_args={"body": "Testing Anzu Web Server"},
                        access_token=self.current_user["access_token"],
                        callback=self.async_callback(self._on_post))

                def _on_post(self, new_entry):
                    if not new_entry:
                        # Call failed; perhaps missing permission?
                        self.authorize_redirect()
                        return
                    self.finish("Posted a message!")

        """
        # Add the OAuth resource request signature if we have credentials
        url = "http://friendfeed-api.com/v2" + path
        if access_token:
            all_args = {}
            all_args.update(args)
            all_args.update(post_args or {})
            method = "POST" if post_args is not None else "GET"
            oauth = self._oauth_request_parameters(url,
                                                   access_token,
                                                   all_args,
                                                   method=method)
            args.update(oauth)
        if args: url += "?" + urllib.urlencode(args)
        callback = self.async_callback(self._on_friendfeed_request, callback)
        http = httpclient.AsyncHTTPClient()
        if post_args is not None:
            http.fetch(url,
                       method="POST",
                       body=urllib.urlencode(post_args),
                       callback=callback)
        else:
            http.fetch(url, callback=callback)
Beispiel #10
0
    def twitter_request(self,
                        path,
                        callback,
                        access_token=None,
                        post_args=None,
                        **args):
        """Fetches the given API path, e.g., "/statuses/user_timeline/btaylor"

        The path should not include the format (we automatically append
        ".json" and parse the JSON output).

        If the request is a POST, post_args should be provided. Query
        string arguments should be given as keyword arguments.

        All the Twitter methods are documented at
        http://apiwiki.twitter.com/Twitter-API-Documentation.

        Many methods require an OAuth access token which you can obtain
        through authorize_redirect() and get_authenticated_user(). The
        user returned through that process includes an 'access_token'
        attribute that can be used to make authenticated requests via
        this method. Example usage::

            class MainHandler(anzu.web.RequestHandler,
                              anzu.auth.TwitterMixin):
                @anzu.web.authenticated
                @anzu.web.asynchronous
                def get(self):
                    self.twitter_request(
                        "/statuses/update",
                        post_args={"status": "Testing Anzu Web Server"},
                        access_token=user["access_token"],
                        callback=self.async_callback(self._on_post))

                def _on_post(self, new_entry):
                    if not new_entry:
                        # Call failed; perhaps missing permission?
                        self.authorize_redirect()
                        return
                    self.finish("Posted a message!")

        """
        # Add the OAuth resource request signature if we have credentials
        url = "http://api.twitter.com/1" + path + ".json"
        if access_token:
            all_args = {}
            all_args.update(args)
            all_args.update(post_args or {})
            method = "POST" if post_args is not None else "GET"
            oauth = self._oauth_request_parameters(url,
                                                   access_token,
                                                   all_args,
                                                   method=method)
            args.update(oauth)
        if args: url += "?" + urllib.urlencode(args)
        callback = self.async_callback(self._on_twitter_request, callback)
        http = httpclient.AsyncHTTPClient()
        if post_args is not None:
            http.fetch(url,
                       method="POST",
                       body=urllib.urlencode(post_args),
                       callback=callback)
        else:
            http.fetch(url, callback=callback)