Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication error while testing my application. #7

Closed
PraveshKoirala opened this issue Jul 8, 2015 · 14 comments
Closed

Authentication error while testing my application. #7

PraveshKoirala opened this issue Jul 8, 2015 · 14 comments
Labels

Comments

@PraveshKoirala
Copy link

Hi,

I am using django-rest-framework-social-oauth2 along with django rest framework to develop an app. All was running well and good but when it came to testing the code, I found a bizzare error.

At the start of my testing code, I created a superuser and an application registered to him. Afterwards, I called the /auth/convert-token endpoint with my facebook access token. While it did return me an access_token, subsequent calling of other endpoints with this returned access_token always failed with the message,

"Authentication credentials were not provided"

I tried to investigate it by placing breakpoints in the function create_token of rest_framework_social_oauth2.views where I found that the AccessToken.objects.create call was not actually creating a new row in my test database (I found this by placing breakpoints after the call and investigating with external database viewer).

Note that this behavior is explicit to the testing code.

Can you please tell me what seems to be the problem here?

I am using django 1.8 with postgresql as backend and django-oauth-toolkit 0.8.1
and django-rest-framework-social-oauth2 0.0.8

@PhilipGarnero
Copy link
Collaborator

Hello,

Does creating a token in the shell using the same lines as in convert_token works ?
Is convert_token returning an access and refresh token ?

@PraveshKoirala
Copy link
Author

Yeah.. as I told you, this problem is explicit to unit testing. Also, convert_token is returning the access_token and the refresh_token.

The problem as I understand is caused because the AccessToken and the RefreshToken model that is created is somehow not flushed into the test database. The Application model, however, works just fine. I don't know why this is the case though but I am beginning to think that this has something to do with the django oauth toolkit and not the rest framework social oauth. In any case, I am currently unable to test my app because of this.

@PhilipGarnero
Copy link
Collaborator

Could you post here your test so I can reproduce ?

@PraveshKoirala
Copy link
Author

Here's my code. Note that the error happens in test_B_user_retrieve_details

from django.test import TestCase
from django.contrib.auth.models import User
from oauth2_provider.models import Application

access_token = ""

class UserCreateTestCase(TestCase):

    @classmethod
    def setUpClass(cls):
        # create Super user
        try:
            # do we already have a user?
            User.objects.get(username="admin")

        except User.DoesNotExist:
            User.objects.create(username="admin", first_name="admin",
                            last_name="admin", is_staff=True, email="email@email.com", password="admin")

            Application.objects.create(name="MyApp", client_type="Public",
                                       authorization_grant_type="Resource owner password-based", user_id=1)

        super(UserCreateTestCase, cls).setUpClass()

    def test_A_get_access_token(self):
        """
        Register a valid facebook user here
        """
        valid_access_token = <valid_access_token>
        header = "Bearer facebook-app " + valid_access_token

        # convert token
        res = self.client.get("/api/v1/auth/convert-token", {}, HTTP_AUTHORIZATION=header)
        print res.data

        self.assertIn('access_token', res.data, "Couldn't generate access_token")

    # save this access_token
        global access_token
        access_token = res.data['access_token']


    def test_B_user_retrieve_details(self):
            """
        This always runs after the test_A_get_access_token..
            """
        # Here /users/1 is an endpoint that returns the details about user. Nothing fancy, just a view that inherits from
        # generics.RetrieveAPIView
        res = self.client.get("/users/1", {"access_token": access_token})
        # Here, res.data, instead of containing information about the user, throws "Credential invalid" message
        print res.data

@PraveshKoirala
Copy link
Author

Here are the libraries that I am using.. (obtained from pip freeze)

Django==1.8.2
Jinja2==2.7.3
MarkupSafe==0.23
Pillow==2.9.0
PyJWT==1.3.0
PyYAML==3.11
Pygments==2.0.2
argparse==1.2.1
django-activity-stream==0.6.0
django-braces==1.8.0
django-debug-toolbar==1.3.0
django-jinja==1.4.1
django-jsonfield==0.9.13
django-oauth-toolkit==0.8.1
django-rest-framework-social-oauth2==0.0.8
django-rest-swagger==0.3.2
djangorestframework==3.1.3
djorm-ext-pgfulltext==0.10
elasticsearch==1.6.0
elasticsearch-dsl==0.0.4
httpie==0.9.2
httpsig==1.1.2
oauthlib==0.7.2
psycopg2==2.6
pycrypto==2.6.1
python-dateutil==2.4.2
python-openid==2.2.5
python-social-auth==0.2.10
pytz==2015.4
requests==2.7.0
requests-oauthlib==0.5.0
six==1.9.0
sqlparse==0.1.15
stream-django==1.2.4
stream-python==2.3.2
urllib3==1.10.4
wsgiref==0.1.2

@PhilipGarnero
Copy link
Collaborator

I couldn't reproduce your issue but your tests are probably wrong.
First, if you're going to unittest, all your tests should be independent from each other: you need to get rid of this access_token global.
Second I see two mistakes in your code:
Application.objects.create(name="MyApp", client_type="Public" should be Application.objects.create(name="Owner", client_type="Public" and
res = self.client.get("/users/1", {"access_token": access_token}) should be
res = self.client.get("/users/1", {}, HTTP_AUTHORIZATION="Bearer " + access_token)

@PraveshKoirala
Copy link
Author

I don't understand why I must use

Application.objects.create(name="Owner", client_type="Public" instead of Application.objects.create(name="MyApp", client_type="Public"

Also, using

res = self.client.get("/users/1", {}, HTTP_AUTHORIZATION="Bearer " + access_token)

only changed the error message.. now it says

{'status': 401, 'message': u'Invalid token header. No credentials provided.'}

I agree when you say that unit tests are meant to be independent but in this particular case, I had to make an exception.

@PraveshKoirala
Copy link
Author

I am curious though, what did you get when you tried reproducing this code??

@PhilipGarnero
Copy link
Collaborator

Owner corresponds to the default value of the PROPRIETARY_APPLICATION_NAME setting.
If you want to name your application otherwise you need to define this setting.
This is prone to change anyway as it is not flexible enough.
Regarding the tests, they passed. Which authentication classes did you enabled for your view ?

@PhilipGarnero
Copy link
Collaborator

Did you manage to get this to work ?

@PraveshKoirala
Copy link
Author

The authentication classes that I enabled are OAuth2Authetication and SocialAuthentication.

And as for managing to getting it work, I couldn't. Anyways, I am closing this issue because I don't think it pertains to this particular library. Many thanks for your replies.

@abdarbl0013
Copy link

@PraveshKoirala I am facing the same issue. Did you ever find the solution for it?

@PraveshKoirala
Copy link
Author

Forgot about it but maybe move the convert-token code to setUp method? It was probably due to the nature of the unit tests being self-contained (i.e. inside a transaction)... Give it a try maybe.

@SaraFarron
Copy link

If you have similar problem this is what Ive discovered: while testing DRF (and most likely django also) creates an empty test database, you can see it after all tests was completed it prints
Destroying test database for alias 'default'...
So what I did for my tests is made a base class with a method that creates a user, token and then

client.credentials(HTTP_AUTHORIZATION='Token ' + token)

and then inherited it in every test class. You can also do it in the setUp() method, but I had many test classes so I did this way so that I don't need to write it several times.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants