Пример #1
0
    def setUp(self):
        jane = User.objects.create_user('jane', '*****@*****.**', 'toto')

        self.resource = Resource(name='photos', url='/oauth/photo/')
        self.resource.save()
        self.CONSUMER_KEY = 'dpf43f3p2l4k3l03'
        self.CONSUMER_SECRET = 'kd94hf93k423kf44'
        self.consumer = Consumer(key=self.CONSUMER_KEY,
                                 secret=self.CONSUMER_SECRET,
                                 name='printer.example.com',
                                 user=jane)
        self.consumer.save()
        def setUp(self):
            self.client = Client()
            self.username = '******'
            self.email = '*****@*****.**'
            self.password = '******'
            self.user = User.objects.create_user(self.username, self.email, self.password)

            # OAuth requirements
            self.resource = Resource(name='data', url='/')
            self.resource.save()
            self.CONSUMER_KEY = 'dpf43f3p2l4k3l03'
            self.CONSUMER_SECRET = 'kd94hf93k423kf44'
            self.consumer = Consumer(key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET,
                                name='api.example.com', user=self.user)
            self.consumer.save()
Пример #3
0
def setup_func():
    
    #from http://code.google.com/p/nose-gae/issues/detail?id=13
    os.environ['SERVER_NAME'] = 'localhost'
    os.environ['SERVER_PORT'] = '8080'
    os.environ['AUTH_DOMAIN'] = 'example.org'
    os.environ['USER_EMAIL'] = ''
    os.environ['USER_ID'] = ''
    
    
    resource = Resource(name='default', url='/oauth/photo/')
    resource.put()
    
    consumer = Consumer(key_=CONSUMER_KEY, secret=CONSUMER_SECRET, name='printer.example.com')
    consumer.put()
Пример #4
0
    def setUp(self):
        username = self.username = '******'
        password = self.password = '******'
        email = self.email = '*****@*****.**'
        jane = self.jane = User.objects.create_user(username, email, password)
        resource = self.resource = Resource(name='photos', url='/api/v1/user/jane/')
        resource.save()
        CONSUMER_KEY = self.CONSUMER_KEY = 'dpf43f3p2l4k3l03'
        CONSUMER_SECRET = self.CONSUMER_SECRET = 'kd94hf93k423kf44'
        consumer = self.consumer = Consumer(key=CONSUMER_KEY, secret=CONSUMER_SECRET,
                                            name='printer.example.com', user=jane)
        consumer.save()

        self.callback_token = self.callback = 'http://printer.example.com/request_token_ready'
        self.callback_confirmed = True
        self.request_token_parameters = {
            'oauth_consumer_key': self.CONSUMER_KEY,
            'oauth_signature_method': 'PLAINTEXT',
            'oauth_signature': '%s&' % self.CONSUMER_SECRET,
            'oauth_timestamp': str(int(time.time())),
            'oauth_nonce': 'requestnonce',
            'oauth_version': '1.0',
            'oauth_callback': self.callback,
            'scope': 'photos',  # custom argument to specify Protected Resource
            }

        self.c = Client()
Пример #5
0
def setup_func():

    #from http://code.google.com/p/nose-gae/issues/detail?id=13
    os.environ['SERVER_NAME'] = 'localhost'
    os.environ['SERVER_PORT'] = '8080'
    os.environ['AUTH_DOMAIN'] = 'example.org'
    os.environ['USER_EMAIL'] = ''
    os.environ['USER_ID'] = ''

    resource = Resource(name='default', url='/oauth/photo/')
    resource.put()

    consumer = Consumer(key_=CONSUMER_KEY,
                        secret=CONSUMER_SECRET,
                        name='printer.example.com')
    consumer.put()
Пример #6
0
    def setUp(self):
        jane = User.objects.create_user("jane", "*****@*****.**", "toto")

        self.resource = Resource(name="photos", url="/oauth/photo/")
        self.resource.save()
        self.CONSUMER_KEY = "dpf43f3p2l4k3l03"
        self.CONSUMER_SECRET = "kd94hf93k423kf44"
        self.consumer = Consumer(
            key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET, name="printer.example.com", user=jane
        )
        self.consumer.save()
        def setUp(self):
            self.client = Client()
            self.username = '******'
            self.email = '*****@*****.**'
            self.password = '******'
            self.user = User.objects.create_user(self.username, self.email, self.password)

            # OAuth requirements
            self.resource = Resource(name='data', url='/')
            self.resource.save()
            self.CONSUMER_KEY = 'dpf43f3p2l4k3l03'
            self.CONSUMER_SECRET = 'kd94hf93k423kf44'
            self.consumer = Consumer(key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET,
                                name='api.example.com', user=self.user)
            self.consumer.save()
        def setUp(self):
            self.client = Client()
            self.username = "******"
            self.email = "*****@*****.**"
            self.password = "******"
            self.user = User.objects.create_user(self.username, self.email, self.password)

            # OAuth requirements
            self.resource = Resource(name="data", url="/")
            self.resource.save()
            self.CONSUMER_KEY = "dpf43f3p2l4k3l03"
            self.CONSUMER_SECRET = "kd94hf93k423kf44"
            self.consumer = Consumer(
                key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET, name="api.example.com", user=self.user
            )
            self.consumer.save()
Пример #9
0
from oauth_provider.models import Resource,Consumer
from oauth_provider.consts import ACCEPTED



default_consumer = Consumer(name="Tomboy default consumer", 
        description="Tomboy default consumer", 
        key_ = 'anyone',
        secret = 'anyone',
        status = ACCEPTED
        )
default_consumer.put()

default_resource = Resource(name="default")
default_resource.put()
    class OAuthTests(TestCase):
        """
        OAuth authentication:
        * the user would like to access his API data from a third-party website
        * the third-party website proposes a link to get that API data
        * the user is redirected to the API and must log in if not authenticated
        * the API displays a webpage to confirm that the user trusts the third-party website
        * if confirmed, the user is redirected to the third-party website through the callback view
        * the third-party website is able to retrieve data from the API
        """
        urls = 'djangorestframework.tests.oauthentication'

        def setUp(self):
            self.client = Client()
            self.username = '******'
            self.email = '*****@*****.**'
            self.password = '******'
            self.user = User.objects.create_user(self.username, self.email, self.password)

            # OAuth requirements
            self.resource = Resource(name='data', url='/')
            self.resource.save()
            self.CONSUMER_KEY = 'dpf43f3p2l4k3l03'
            self.CONSUMER_SECRET = 'kd94hf93k423kf44'
            self.consumer = Consumer(key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET,
                                name='api.example.com', user=self.user)
            self.consumer.save()

        def test_oauth_invalid_and_anonymous_access(self):
            """
            Verify that the resource is protected and the OAuth authorization view
            require the user to be logged in.
            """
            response = self.client.get('/')
            self.assertEqual(response.content, 'Invalid request parameters.')
            self.assertEqual(response.status_code, 401)
            response = self.client.get('/oauth/authorize/', follow=True)
            self.assertRedirects(response, '/accounts/login/?next=/oauth/authorize/')

        def test_oauth_authorize_access(self):
            """
            Verify that once logged in, the user can access the authorization page
            but can't display the page because the request token is not specified.
            """
            self.client.login(username=self.username, password=self.password)
            response = self.client.get('/oauth/authorize/', follow=True)
            self.assertEqual(response.content, 'No request token specified.')

        def _create_request_token_parameters(self):
            """
            A shortcut to create request's token parameters.
            """
            return {
                'oauth_consumer_key': self.CONSUMER_KEY,
                'oauth_signature_method': 'PLAINTEXT',
                'oauth_signature': '%s&' % self.CONSUMER_SECRET,
                'oauth_timestamp': str(int(time.time())),
                'oauth_nonce': 'requestnonce',
                'oauth_version': '1.0',
                'oauth_callback': 'http://api.example.com/request_token_ready',
                'scope': 'data',
            }

        def test_oauth_request_token_retrieval(self):
            """
            Verify that the request token can be retrieved by the server.
            """
            response = self.client.get("/oauth/request_token/",
                                        self._create_request_token_parameters())
            self.assertEqual(response.status_code, 200)
            token = list(Token.objects.all())[-1]
            self.failIf(token.key not in response.content)
            self.failIf(token.secret not in response.content)

        def test_oauth_user_request_authorization(self):
            """
            Verify that the user can access the authorization page once logged in
            and the request token has been retrieved.
            """
            # Setup
            response = self.client.get("/oauth/request_token/",
                                        self._create_request_token_parameters())
            token = list(Token.objects.all())[-1]

            # Starting the test here
            self.client.login(username=self.username, password=self.password)
            parameters = {'oauth_token': token.key,}
            response = self.client.get("/oauth/authorize/", parameters)
            self.assertEqual(response.status_code, 200)
            self.failIf(not response.content.startswith('Fake authorize view for api.example.com with params: oauth_token='))
            self.assertEqual(token.is_approved, 0)
            parameters['authorize_access'] = 1 # fake authorization by the user
            response = self.client.post("/oauth/authorize/", parameters)
            self.assertEqual(response.status_code, 302)
            self.failIf(not response['Location'].startswith('http://api.example.com/request_token_ready?oauth_verifier='))
            token = Token.objects.get(key=token.key)
            self.failIf(token.key not in response['Location'])
            self.assertEqual(token.is_approved, 1)

        def _create_access_token_parameters(self, token):
            """
            A shortcut to create access' token parameters.
            """
            return {
                'oauth_consumer_key': self.CONSUMER_KEY,
                'oauth_token': token.key,
                'oauth_signature_method': 'PLAINTEXT',
                'oauth_signature': '%s&%s' % (self.CONSUMER_SECRET, token.secret),
                'oauth_timestamp': str(int(time.time())),
                'oauth_nonce': 'accessnonce',
                'oauth_version': '1.0',
                'oauth_verifier': token.verifier,
                'scope': 'data',
            }

        def test_oauth_access_token_retrieval(self):
            """
            Verify that the request token can be retrieved by the server.
            """
            # Setup
            response = self.client.get("/oauth/request_token/",
                                        self._create_request_token_parameters())
            token = list(Token.objects.all())[-1]
            self.client.login(username=self.username, password=self.password)
            parameters = {'oauth_token': token.key,}
            response = self.client.get("/oauth/authorize/", parameters)
            parameters['authorize_access'] = 1 # fake authorization by the user
            response = self.client.post("/oauth/authorize/", parameters)
            token = Token.objects.get(key=token.key)

            # Starting the test here
            response = self.client.get("/oauth/access_token/", self._create_access_token_parameters(token))
            self.assertEqual(response.status_code, 200)
            self.failIf(not response.content.startswith('oauth_token_secret='))
            access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1]
            self.failIf(access_token.key not in response.content)
            self.failIf(access_token.secret not in response.content)
            self.assertEqual(access_token.user.username, 'john')

        def _create_access_parameters(self, access_token):
            """
            A shortcut to create access' parameters.
            """
            parameters = {
                'oauth_consumer_key': self.CONSUMER_KEY,
                'oauth_token': access_token.key,
                'oauth_signature_method': 'HMAC-SHA1',
                'oauth_timestamp': str(int(time.time())),
                'oauth_nonce': 'accessresourcenonce',
                'oauth_version': '1.0',
            }
            oauth_request = oauth.Request.from_token_and_callback(access_token,
                http_url='http://testserver/', parameters=parameters)
            signature_method = oauth.SignatureMethod_HMAC_SHA1()
            signature = signature_method.sign(oauth_request, self.consumer, access_token)
            parameters['oauth_signature'] = signature
            return parameters

        def test_oauth_protected_resource_access(self):
            """
            Verify that the request token can be retrieved by the server.
            """
            # Setup
            response = self.client.get("/oauth/request_token/",
                                        self._create_request_token_parameters())
            token = list(Token.objects.all())[-1]
            self.client.login(username=self.username, password=self.password)
            parameters = {'oauth_token': token.key,}
            response = self.client.get("/oauth/authorize/", parameters)
            parameters['authorize_access'] = 1 # fake authorization by the user
            response = self.client.post("/oauth/authorize/", parameters)
            token = Token.objects.get(key=token.key)
            response = self.client.get("/oauth/access_token/", self._create_access_token_parameters(token))
            access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1]

            # Starting the test here
            response = self.client.get("/", self._create_access_token_parameters(access_token))
            self.assertEqual(response.status_code, 200)
            self.assertEqual(response.content, '{"resource": "Protected!"}')
Пример #11
0
class Test1(TestCase):
    def setUp(self):
        jane = User.objects.create_user("jane", "*****@*****.**", "toto")

        self.resource = Resource(name="photos", url="/oauth/photo/")
        self.resource.save()
        self.CONSUMER_KEY = "dpf43f3p2l4k3l03"
        self.CONSUMER_SECRET = "kd94hf93k423kf44"
        self.consumer = Consumer(
            key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET, name="printer.example.com", user=jane
        )
        self.consumer.save()

    def test_1(self):
        """Obtaining a Request Token"""

        response = self.client.get("/oauth/request_token/")
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)

        # depends on REALM_KEY_NAME Django setting
        self.assertEqual(response._headers["www-authenticate"], ("WWW-Authenticate", 'OAuth realm=""'))
        self.assertEqual(response.content, "Invalid request parameters.")

        # The Consumer sends the following HTTP POST request to the Service Provider

        parameters = {
            "oauth_consumer_key": self.CONSUMER_KEY,
            "oauth_signature_method": "PLAINTEXT",
            "oauth_signature": "%s&" % self.CONSUMER_SECRET,
            "oauth_timestamp": str(int(time.time())),
            "oauth_nonce": "requestnonce",
            "oauth_version": "1.0",
            "oauth_callback": "http://printer.example.com/request_token_ready",
            "scope": "photos",  # custom argument to specify Protected Resource
        }
        response = self.client.get("/oauth/request_token/", parameters)

        # The Service Provider checks the signature and replies with an unauthorized
        # Request Token in the body of the HTTP response::

        self.assertEqual(response.status_code, httplib.OK)

        self.assertTrue("oauth_token_secret=" in response.content)
        self.assertTrue("oauth_token=" in response.content)
        self.assertTrue("oauth_callback_confirmed=true" in response.content)

        token = list(Token.objects.all())[-1]
        self.assertTrue(token.key in response.content)
        self.assertTrue(token.secret in response.content)
        self.assertEqual(token.callback, u"http://printer.example.com/request_token_ready")
        self.assertTrue(token.callback_confirmed)

        # If you try to access a resource with a wrong scope, it will return an error::
        # This is not supported.
        #        parameters['scope'] = 'videos'
        #        parameters['oauth_nonce'] = 'requestnoncevideos'
        #        response = self.client.get("/oauth/request_token/", parameters)
        #        print "-------"
        #        print response
        #        print "-------"
        #        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        #        self.assertEqual(response.content, 'Resource videos does not exist.')

        parameters["scope"] = "photos"  # restore

        # If you try to put a wrong callback, it will return an error::

        parameters["oauth_callback"] = "wrongcallback"
        parameters["oauth_nonce"] = "requestnoncewrongcallback"
        response = self.client.get("/oauth/request_token/", parameters)
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertEqual(response.content, "Invalid callback URL.")

        # If you do not provide any callback (i.e. oob), the Service Provider SHOULD
        # display the value of the verification code::

        parameters["oauth_callback"] = "oob"
        parameters["oauth_nonce"] = "requestnonceoob"
        response = self.client.get("/oauth/request_token/", parameters)
        self.assertEqual(response.status_code, httplib.OK)
        self.assertTrue("oauth_token_secret=" in response.content)
        self.assertTrue("oauth_token=" in response.content)
        self.assertTrue("oauth_callback_confirmed=true" in response.content)

        oobtoken = list(Token.objects.all())[-1]
        self.assertTrue(oobtoken.key in response.content)
        self.assertTrue(oobtoken.secret in response.content)
        self.assertEqual(oobtoken.callback, None)
        self.assertFalse(oobtoken.callback_confirmed)

        # ======== Requesting User Authorization ============

        # The Consumer redirects Jane's browser to the Service Provider User
        # Authorization URL to obtain Jane's approval for accessing her private photos.

        # The Service Provider asks Jane to sign-in using her username and password::
        parameters = {"oauth_token": token.key}
        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.FOUND)

        self.assertTrue(True)
        print response["Location"]
        self.assertRedirects(response, "/accounts/login/?next=/oauth/authorize/")
        self.assertTrue(token.key in response["Location"])

        # If successful, asks her if she approves granting printer.example.com access to
        # her private photos. If Jane approves the request, the Service Provider
        # redirects her back to the Consumer's callback URL::

        self.assertTrue(self.client.login(username="******", password="******"))
        self.assertEqual(token.is_approved, 0)

        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.OK)
        self.assertEqual(response.content, "Fake authorize view for printer.example.com with params: oauth_token=...")

        # fake authorization by the user
        parameters["authorize_access"] = 1
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.FOUND)
        self.assertRedirects(response, "/request_token_ready")

        token = Token.objects.get(key=self.token.key)
        self.assertTrue(token.key in response["Location"])
        self.assertEqual(token.is_approved, 1)

        # without session parameter (previous POST removed it)
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertEqual(response.content, "Action not allowed.")

        # fake access not granted by the user (set session parameter again)
        response = self.client.get("/oauth/authorize/", parameters)
        parameters["authorize_access"] = 0
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.FOUND)
        self.assertRedirects(response, "/request_token_ready")
        self.client.logout()

        # With OAuth 1.0a, the callback argument can be set to "oob" (out-of-band),
        # you can specify your own default callback view with the
        # ``OAUTH_PROVIDER_CALLBACK_VIEW`` setting::

        #        from oauth_provider.consts import OUT_OF_BAND
        token.callback = OUT_OF_BAND
        token.save()
        parameters = {"oauth_token": token.key}
        self.assertTrue(self.client.login(username="******", password="******"))

        response = self.client.get("/oauth/authorize/", parameters)
        parameters["authorize_access"] = 0
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.OK)
        self.assertEqual(response.content, "Fake callback view.")
        self.client.logout()

        # ========== Obtaining an Access Token ===========

        # Now that the Consumer knows Jane approved the Request Token, it asks the
        # Service Provider to exchange it for an Access Token::

        parameters = {
            "oauth_consumer_key": self.CONSUMER_KEY,
            "oauth_token": token.key,
            "oauth_signature_method": "PLAINTEXT",
            "oauth_signature": "%s&%s" % (self.CONSUMER_SECRET, token.secret),
            "oauth_timestamp": str(int(time.time())),
            "oauth_nonce": "accessnonce",
            "oauth_version": "1.0",
            "oauth_verifier": self.token.verifier,
            "scope": "photos",
        }
        response = self.client.get("/oauth/access_token/", parameters)

        # You can use HTTP Authorization header, if you provide both, header will be
        # checked before parameters. It depends on your needs.

        # The Service Provider checks the signature and replies with an Access Token in
        # the body of the HTTP response::
        self.assertEqual(response.status_code, httplib.OK)
        self.assertTrue("oauth_token_secret=" in response.content)
        self.assertTrue("oauth_token=" in response.content)

        access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1]
        self.assertTrue(access_token.key in response.content)
        self.assertTrue(access_token.secret in response.content)
        self.assertEqual(access_token.user.name, u"jane")

        # The Consumer will not be able to request another Access Token with the same
        # parameters because the Request Token has been deleted once Access Token is
        # created::

        response = self.client.get("/oauth/access_token/", parameters)
        self.assertEqual(response.status_code, httplib.BAD_REQUEST)
        self.assertEqual(response.content, "Invalid request token.")

        # The Consumer will not be able to request another Access Token with a missing
        # or invalid verifier::

        new_request_token = Token.objects.create_token(
            token_type=Token.REQUEST,
            timestamp=str(int(time.time())),
            consumer=Consumer.objects.get(key=self.CONSUMER_KEY),
            user=User.objects.get(username="******"),
            resource=Resource.objects.get(name="photos"),
        )
        new_request_token.is_approved = True
        new_request_token.save()
        parameters["oauth_token"] = new_request_token.key
        parameters["oauth_signature"] = "%s&%s" % (self.CONSUMER_SECRET, new_request_token.secret)
        parameters["oauth_verifier"] = "invalidverifier"
        response = self.client.get("/oauth/access_token/", parameters)
        self.assertEqual(response.status_code, httplib.BAD_REQUEST)
        self.assertEqual(response.content, "Invalid OAuth verifier.")

        parameters["oauth_verifier"] = new_request_token.verifier  # restore

        # The Consumer will not be able to request an Access Token if the token is not
        # approved::

        new_request_token.is_approved = False
        new_request_token.save()
        parameters["oauth_nonce"] = "anotheraccessnonce"
        response = self.client.get("/oauth/access_token/", parameters)
        self.assertEqual(response.status_code, httplib.BAD_REQUEST)
        self.assertEqual(response.content, "Request Token not approved by the user.")

        # Accessing Protected Resources

        # The Consumer is now ready to request the private photo. Since the photo URL is
        # not secure (HTTP), it must use HMAC-SHA1.

        # Generating Signature Base String

        # To generate the signature, it first needs to generate the Signature Base
        # String. The request contains the following parameters (oauth_signature
        # excluded) which are ordered and concatenated into a normalized string::

        parameters = {
            "oauth_consumer_key": self.CONSUMER_KEY,
            "oauth_token": access_token.key,
            "oauth_signature_method": "HMAC-SHA1",
            "oauth_timestamp": str(int(time.time())),
            "oauth_nonce": "accessresourcenonce",
            "oauth_version": "1.0",
        }

        # Calculating Signature Value

        # HMAC-SHA1 produces the following digest value as a base64-encoded string
        # (using the Signature Base String as text and kd94hf93k423kf44&pfkkdhi9sl3r4s00
        # as key)::

        import oauth2 as oauth

        oauth_request = oauth.Request.from_token_and_callback(
            access_token, http_url="http://testserver/oauth/photo/", parameters=parameters
        )
        signature_method = oauth.SignatureMethod_HMAC_SHA1()
        signature = signature_method.sign(oauth_request, self.consumer, access_token)

        # Requesting Protected Resource

        # All together, the Consumer request for the photo is::

        parameters["oauth_signature"] = signature
        response = self.client.get("/oauth/photo/", parameters)
        self.assertEqual(response.status_code, httplib.OK)
        self.assertEqual(response.content, "Protected Resource access!")

        # Otherwise, an explicit error will be raised::

        parameters["oauth_signature"] = "wrongsignature"
        parameters["oauth_nonce"] = "anotheraccessresourcenonce"
        response = self.client.get("/oauth/photo/", parameters)
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertTrue("Invalid signature. Expected signature base string: GET" in response.content)

        response = self.client.get("/oauth/photo/")
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertEqual(response.content, "Invalid request parameters.")

        # Revoking Access

        # If Jane deletes the Access Token of printer.example.com, the Consumer will not
        # be able to access the Protected Resource anymore::

        access_token.delete()
        # Note that an "Invalid signature" error will be raised here if the
        # token is not revoked by Jane because we reuse a previously used one.
        parameters["oauth_signature"] = signature
        parameters["oauth_nonce"] = "yetanotheraccessresourcenonce"
        response = self.client.get("/oauth/photo/", parameters)
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertTrue("Invalid access token: ...", response.content)
    class OAuthTests(TestCase):
        """
        OAuth authentication:
        * the user would like to access his API data from a third-party website
        * the third-party website proposes a link to get that API data
        * the user is redirected to the API and must log in if not authenticated
        * the API displays a webpage to confirm that the user trusts the third-party website
        * if confirmed, the user is redirected to the third-party website through the callback view
        * the third-party website is able to retrieve data from the API
        """
        urls = 'djangorestframework.tests.oauthentication'

        def setUp(self):
            self.client = Client()
            self.username = '******'
            self.email = '*****@*****.**'
            self.password = '******'
            self.user = User.objects.create_user(self.username, self.email, self.password)

            # OAuth requirements
            self.resource = Resource(name='data', url='/')
            self.resource.save()
            self.CONSUMER_KEY = 'dpf43f3p2l4k3l03'
            self.CONSUMER_SECRET = 'kd94hf93k423kf44'
            self.consumer = Consumer(key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET,
                                name='api.example.com', user=self.user)
            self.consumer.save()

        def test_oauth_invalid_and_anonymous_access(self):
            """
            Verify that the resource is protected and the OAuth authorization view
            require the user to be logged in.
            """
            response = self.client.get('/')
            self.assertEqual(response.content, 'Invalid request parameters.')
            self.assertEqual(response.status_code, 401)
            response = self.client.get('/oauth/authorize/', follow=True)
            self.assertRedirects(response, '/accounts/login/?next=/oauth/authorize/')

        def test_oauth_authorize_access(self):
            """
            Verify that once logged in, the user can access the authorization page
            but can't display the page because the request token is not specified.
            """
            self.client.login(username=self.username, password=self.password)
            response = self.client.get('/oauth/authorize/', follow=True)
            self.assertEqual(response.content, 'No request token specified.')

        def _create_request_token_parameters(self):
            """
            A shortcut to create request's token parameters.
            """
            return {
                'oauth_consumer_key': self.CONSUMER_KEY,
                'oauth_signature_method': 'PLAINTEXT',
                'oauth_signature': '%s&' % self.CONSUMER_SECRET,
                'oauth_timestamp': str(int(time.time())),
                'oauth_nonce': 'requestnonce',
                'oauth_version': '1.0',
                'oauth_callback': 'http://api.example.com/request_token_ready',
                'scope': 'data',
            }

        def test_oauth_request_token_retrieval(self):
            """
            Verify that the request token can be retrieved by the server.
            """
            response = self.client.get("/oauth/request_token/",
                                        self._create_request_token_parameters())
            self.assertEqual(response.status_code, 200)
            token = list(Token.objects.all())[-1]
            self.failIf(token.key not in response.content)
            self.failIf(token.secret not in response.content)

        def test_oauth_user_request_authorization(self):
            """
            Verify that the user can access the authorization page once logged in
            and the request token has been retrieved.
            """
            # Setup
            response = self.client.get("/oauth/request_token/",
                                        self._create_request_token_parameters())
            token = list(Token.objects.all())[-1]

            # Starting the test here
            self.client.login(username=self.username, password=self.password)
            parameters = {'oauth_token': token.key,}
            response = self.client.get("/oauth/authorize/", parameters)
            self.assertEqual(response.status_code, 200)
            self.failIf(not response.content.startswith('Fake authorize view for api.example.com with params: oauth_token='))
            self.assertEqual(token.is_approved, 0)
            parameters['authorize_access'] = 1 # fake authorization by the user
            response = self.client.post("/oauth/authorize/", parameters)
            self.assertEqual(response.status_code, 302)
            self.failIf(not response['Location'].startswith('http://api.example.com/request_token_ready?oauth_verifier='))
            token = Token.objects.get(key=token.key)
            self.failIf(token.key not in response['Location'])
            self.assertEqual(token.is_approved, 1)

        def _create_access_token_parameters(self, token):
            """
            A shortcut to create access' token parameters.
            """
            return {
                'oauth_consumer_key': self.CONSUMER_KEY,
                'oauth_token': token.key,
                'oauth_signature_method': 'PLAINTEXT',
                'oauth_signature': '%s&%s' % (self.CONSUMER_SECRET, token.secret),
                'oauth_timestamp': str(int(time.time())),
                'oauth_nonce': 'accessnonce',
                'oauth_version': '1.0',
                'oauth_verifier': token.verifier,
                'scope': 'data',
            }

        def test_oauth_access_token_retrieval(self):
            """
            Verify that the request token can be retrieved by the server.
            """
            # Setup
            response = self.client.get("/oauth/request_token/",
                                        self._create_request_token_parameters())
            token = list(Token.objects.all())[-1]
            self.client.login(username=self.username, password=self.password)
            parameters = {'oauth_token': token.key,}
            response = self.client.get("/oauth/authorize/", parameters)
            parameters['authorize_access'] = 1 # fake authorization by the user
            response = self.client.post("/oauth/authorize/", parameters)
            token = Token.objects.get(key=token.key)

            # Starting the test here
            response = self.client.get("/oauth/access_token/", self._create_access_token_parameters(token))
            self.assertEqual(response.status_code, 200)
            self.failIf(not response.content.startswith('oauth_token_secret='))
            access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1]
            self.failIf(access_token.key not in response.content)
            self.failIf(access_token.secret not in response.content)
            self.assertEqual(access_token.user.username, 'john')

        def _create_access_parameters(self, access_token):
            """
            A shortcut to create access' parameters.
            """
            parameters = {
                'oauth_consumer_key': self.CONSUMER_KEY,
                'oauth_token': access_token.key,
                'oauth_signature_method': 'HMAC-SHA1',
                'oauth_timestamp': str(int(time.time())),
                'oauth_nonce': 'accessresourcenonce',
                'oauth_version': '1.0',
            }
            oauth_request = oauth.Request.from_token_and_callback(access_token,
                http_url='http://testserver/', parameters=parameters)
            signature_method = oauth.SignatureMethod_HMAC_SHA1()
            signature = signature_method.sign(oauth_request, self.consumer, access_token)
            parameters['oauth_signature'] = signature
            return parameters

        def test_oauth_protected_resource_access(self):
            """
            Verify that the request token can be retrieved by the server.
            """
            # Setup
            response = self.client.get("/oauth/request_token/",
                                        self._create_request_token_parameters())
            token = list(Token.objects.all())[-1]
            self.client.login(username=self.username, password=self.password)
            parameters = {'oauth_token': token.key,}
            response = self.client.get("/oauth/authorize/", parameters)
            parameters['authorize_access'] = 1 # fake authorization by the user
            response = self.client.post("/oauth/authorize/", parameters)
            token = Token.objects.get(key=token.key)
            response = self.client.get("/oauth/access_token/", self._create_access_token_parameters(token))
            access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1]

            # Starting the test here
            response = self.client.get("/", self._create_access_token_parameters(access_token))
            self.assertEqual(response.status_code, 200)
            self.assertEqual(response.content, '{"resource": "Protected!"}')
Пример #13
0
class Test1(TestCase):
    def setUp(self):
        jane = User.objects.create_user('jane', '*****@*****.**', 'toto')

        self.resource = Resource(name='photos', url='/oauth/photo/')
        self.resource.save()
        self.CONSUMER_KEY = 'dpf43f3p2l4k3l03'
        self.CONSUMER_SECRET = 'kd94hf93k423kf44'
        self.consumer = Consumer(key=self.CONSUMER_KEY,
                                 secret=self.CONSUMER_SECRET,
                                 name='printer.example.com',
                                 user=jane)
        self.consumer.save()

    def test_1(self):
        """Obtaining a Request Token"""

        response = self.client.get("/oauth/request_token/")
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)

        # depends on REALM_KEY_NAME Django setting
        self.assertEqual(response._headers['www-authenticate'],
                         ('WWW-Authenticate', 'OAuth realm=""'))
        self.assertEqual(response.content, 'Invalid request parameters.')

        # The Consumer sends the following HTTP POST request to the Service Provider

        parameters = {
            'oauth_consumer_key': self.CONSUMER_KEY,
            'oauth_signature_method': 'PLAINTEXT',
            'oauth_signature': '%s&' % self.CONSUMER_SECRET,
            'oauth_timestamp': str(int(time.time())),
            'oauth_nonce': 'requestnonce',
            'oauth_version': '1.0',
            'oauth_callback': 'http://printer.example.com/request_token_ready',
            'scope': 'photos',  # custom argument to specify Protected Resource
        }
        response = self.client.get("/oauth/request_token/", parameters)

        # The Service Provider checks the signature and replies with an unauthorized
        # Request Token in the body of the HTTP response::

        self.assertEqual(response.status_code, httplib.OK)

        self.assertTrue("oauth_token_secret=" in response.content)
        self.assertTrue("oauth_token=" in response.content)
        self.assertTrue("oauth_callback_confirmed=true" in response.content)

        token = list(Token.objects.all())[-1]
        self.assertTrue(token.key in response.content)
        self.assertTrue(token.secret in response.content)
        self.assertEqual(token.callback,
                         u'http://printer.example.com/request_token_ready')
        self.assertTrue(token.callback_confirmed)

        # If you try to access a resource with a wrong scope, it will return an error::
        # This is not supported.
        #        parameters['scope'] = 'videos'
        #        parameters['oauth_nonce'] = 'requestnoncevideos'
        #        response = self.client.get("/oauth/request_token/", parameters)
        #        print "-------"
        #        print response
        #        print "-------"
        #        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        #        self.assertEqual(response.content, 'Resource videos does not exist.')

        parameters['scope'] = 'photos'  # restore

        # If you try to put a wrong callback, it will return an error::

        parameters['oauth_callback'] = 'wrongcallback'
        parameters['oauth_nonce'] = 'requestnoncewrongcallback'
        response = self.client.get("/oauth/request_token/", parameters)
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertEqual(response.content, 'Invalid callback URL.')

        # If you do not provide any callback (i.e. oob), the Service Provider SHOULD
        # display the value of the verification code::

        parameters['oauth_callback'] = 'oob'
        parameters['oauth_nonce'] = 'requestnonceoob'
        response = self.client.get("/oauth/request_token/", parameters)
        self.assertEqual(response.status_code, httplib.OK)
        self.assertTrue("oauth_token_secret=" in response.content)
        self.assertTrue("oauth_token=" in response.content)
        self.assertTrue("oauth_callback_confirmed=true" in response.content)

        oobtoken = list(Token.objects.all())[-1]
        self.assertTrue(oobtoken.key in response.content)
        self.assertTrue(oobtoken.secret in response.content)
        self.assertEqual(oobtoken.callback, None)
        self.assertFalse(oobtoken.callback_confirmed)

        # ======== Requesting User Authorization ============

        # The Consumer redirects Jane's browser to the Service Provider User
        # Authorization URL to obtain Jane's approval for accessing her private photos.

        # The Service Provider asks Jane to sign-in using her username and password::
        parameters = {
            'oauth_token': token.key,
        }
        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.FOUND)

        self.assertTrue(True)
        print response['Location']
        self.assertRedirects(response,
                             '/accounts/login/?next=/oauth/authorize/')
        self.assertTrue(token.key in response['Location'])

        # If successful, asks her if she approves granting printer.example.com access to
        # her private photos. If Jane approves the request, the Service Provider
        # redirects her back to the Consumer's callback URL::

        self.assertTrue(self.client.login(username='******', password='******'))
        self.assertEqual(token.is_approved, 0)

        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.OK)
        self.assertEqual(
            response.content,
            'Fake authorize view for printer.example.com with params: oauth_token=...'
        )

        # fake authorization by the user
        parameters['authorize_access'] = 1
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.FOUND)
        self.assertRedirects(response, "/request_token_ready")

        token = Token.objects.get(key=self.token.key)
        self.assertTrue(token.key in response['Location'])
        self.assertEqual(token.is_approved, 1)

        # without session parameter (previous POST removed it)
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertEqual(response.content, 'Action not allowed.')

        # fake access not granted by the user (set session parameter again)
        response = self.client.get("/oauth/authorize/", parameters)
        parameters['authorize_access'] = 0
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.FOUND)
        self.assertRedirects(response, "/request_token_ready")
        self.client.logout()

        # With OAuth 1.0a, the callback argument can be set to "oob" (out-of-band),
        # you can specify your own default callback view with the
        # ``OAUTH_PROVIDER_CALLBACK_VIEW`` setting::

        #        from oauth_provider.consts import OUT_OF_BAND
        token.callback = OUT_OF_BAND
        token.save()
        parameters = {
            'oauth_token': token.key,
        }
        self.assertTrue(self.client.login(username='******', password='******'))

        response = self.client.get("/oauth/authorize/", parameters)
        parameters['authorize_access'] = 0
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, httplib.OK)
        self.assertEqual(response.content, 'Fake callback view.')
        self.client.logout()

        # ========== Obtaining an Access Token ===========

        # Now that the Consumer knows Jane approved the Request Token, it asks the
        # Service Provider to exchange it for an Access Token::

        parameters = {
            'oauth_consumer_key': self.CONSUMER_KEY,
            'oauth_token': token.key,
            'oauth_signature_method': 'PLAINTEXT',
            'oauth_signature': '%s&%s' % (self.CONSUMER_SECRET, token.secret),
            'oauth_timestamp': str(int(time.time())),
            'oauth_nonce': 'accessnonce',
            'oauth_version': '1.0',
            'oauth_verifier': self.token.verifier,
            'scope': 'photos',
        }
        response = self.client.get("/oauth/access_token/", parameters)

        # You can use HTTP Authorization header, if you provide both, header will be
        # checked before parameters. It depends on your needs.

        # The Service Provider checks the signature and replies with an Access Token in
        # the body of the HTTP response::
        self.assertEqual(response.status_code, httplib.OK)
        self.assertTrue('oauth_token_secret=' in response.content)
        self.assertTrue('oauth_token=' in response.content)

        access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1]
        self.assertTrue(access_token.key in response.content)
        self.assertTrue(access_token.secret in response.content)
        self.assertEqual(access_token.user.name, u'jane')

        # The Consumer will not be able to request another Access Token with the same
        # parameters because the Request Token has been deleted once Access Token is
        # created::

        response = self.client.get("/oauth/access_token/", parameters)
        self.assertEqual(response.status_code, httplib.BAD_REQUEST)
        self.assertEqual(response.content, 'Invalid request token.')

        # The Consumer will not be able to request another Access Token with a missing
        # or invalid verifier::

        new_request_token = Token.objects.create_token(
            token_type=Token.REQUEST,
            timestamp=str(int(time.time())),
            consumer=Consumer.objects.get(key=self.CONSUMER_KEY),
            user=User.objects.get(username="******"),
            resource=Resource.objects.get(name='photos'))
        new_request_token.is_approved = True
        new_request_token.save()
        parameters['oauth_token'] = new_request_token.key
        parameters['oauth_signature'] = '%s&%s' % (self.CONSUMER_SECRET,
                                                   new_request_token.secret)
        parameters['oauth_verifier'] = 'invalidverifier'
        response = self.client.get("/oauth/access_token/", parameters)
        self.assertEqual(response.status_code, httplib.BAD_REQUEST)
        self.assertEqual(response.content, 'Invalid OAuth verifier.')

        parameters['oauth_verifier'] = new_request_token.verifier  # restore

        # The Consumer will not be able to request an Access Token if the token is not
        # approved::

        new_request_token.is_approved = False
        new_request_token.save()
        parameters['oauth_nonce'] = 'anotheraccessnonce'
        response = self.client.get("/oauth/access_token/", parameters)
        self.assertEqual(response.status_code, httplib.BAD_REQUEST)
        self.assertEqual(response.content,
                         'Request Token not approved by the user.')

        # Accessing Protected Resources

        # The Consumer is now ready to request the private photo. Since the photo URL is
        # not secure (HTTP), it must use HMAC-SHA1.

        # Generating Signature Base String

        # To generate the signature, it first needs to generate the Signature Base
        # String. The request contains the following parameters (oauth_signature
        # excluded) which are ordered and concatenated into a normalized string::

        parameters = {
            'oauth_consumer_key': self.CONSUMER_KEY,
            'oauth_token': access_token.key,
            'oauth_signature_method': 'HMAC-SHA1',
            'oauth_timestamp': str(int(time.time())),
            'oauth_nonce': 'accessresourcenonce',
            'oauth_version': '1.0',
        }

        # Calculating Signature Value

        # HMAC-SHA1 produces the following digest value as a base64-encoded string
        # (using the Signature Base String as text and kd94hf93k423kf44&pfkkdhi9sl3r4s00
        # as key)::

        import oauth2 as oauth
        oauth_request = oauth.Request.from_token_and_callback(
            access_token,
            http_url='http://testserver/oauth/photo/',
            parameters=parameters)
        signature_method = oauth.SignatureMethod_HMAC_SHA1()
        signature = signature_method.sign(oauth_request, self.consumer,
                                          access_token)

        # Requesting Protected Resource

        # All together, the Consumer request for the photo is::

        parameters['oauth_signature'] = signature
        response = self.client.get("/oauth/photo/", parameters)
        self.assertEqual(response.status_code, httplib.OK)
        self.assertEqual(response.content, 'Protected Resource access!')

        # Otherwise, an explicit error will be raised::

        parameters['oauth_signature'] = 'wrongsignature'
        parameters['oauth_nonce'] = 'anotheraccessresourcenonce'
        response = self.client.get("/oauth/photo/", parameters)
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertTrue(
            'Invalid signature. Expected signature base string: GET' in
            response.content)

        response = self.client.get("/oauth/photo/")
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertEqual(response.content, 'Invalid request parameters.')

        # Revoking Access

        # If Jane deletes the Access Token of printer.example.com, the Consumer will not
        # be able to access the Protected Resource anymore::

        access_token.delete()
        # Note that an "Invalid signature" error will be raised here if the
        # token is not revoked by Jane because we reuse a previously used one.
        parameters['oauth_signature'] = signature
        parameters['oauth_nonce'] = 'yetanotheraccessresourcenonce'
        response = self.client.get("/oauth/photo/", parameters)
        self.assertEqual(response.status_code, httplib.UNAUTHORIZED)
        self.assertTrue('Invalid access token: ...', response.content)