dimanche 24 janvier 2021

django drf testing social oauth2 with google

I'm trying to test drf-social-oauth2's integration with Google via python manage.py test with the following test class:

class DRFSocialOAuthIntegrationTest(TestCase):

    def setUp(self):

        self.test_user = UserModel.objects.create_user("test_user", "test@user.com", TEST_USER_PASSWORD)

        self.application = Application(
            name="Test Application",
            redirect_uris="",
            user=self.test_user,
            client_type=Application.CLIENT_CONFIDENTIAL,
            authorization_grant_type=Application.GRANT_PASSWORD,  # https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/models.py
        )
        self.application.save()
        
        # Every test needs a client.
        self.client = Client()

    def tearDown(self):
        self.application.delete()
        self.test_user.delete()

    def test_drf_social_oauth2_integration(self):
        '''Following testing steps found at curl -X POST -d "grant_type=convert_token&client_id=<django-oauth-generated-client_id>&client_secret=<django-oauth-generated-client_secret>&backend=google-oauth2&token=<google_token>" http://localhost:8000/auth/convert-token'''
        

    def convert_google_token(self):
        '''
        Convert Google token to our access token       
        curl -X POST -d "grant_type=convert_token&client_id=<client_id>&client_secret=<client_secret>&backend=google-oauth2&token=<google_token>" http://localhost:8000/auth/convert-token
        '''

        return self.client.post(
            '/auth/convert-token', 
            {
                'grant_type': 'convert_token',
                'client_id': self.application.client_id, 
                'client_secret': self.application.client_secret, 
                'backend': 'google-oauth2', 
                'token': <google_token>
            }
        )

That seems to work fine, but I have to keep feeding it the google_token by manually navigating to https://developers.google.com/oauthplayground/?code=<my_code>&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid&authuser=0&prompt=consent#:

enter image description here

Once there, I click on the 'Exchange authorization code for tokens' button, get the access token, and paste that access token into the tokenparameter of the request inside convert_google_token(). This doesn't feel very automated. I'm not sure if I should just click the checkbox so that the access token is refreshed automatically and therefore never have to edit it in convert_google_token(). Or maybe I'm supposed to get that access token programmatically. But I believe that would entail getting the authorization code first, which would have to also be programmatically since it is a one-time code, right?

So in order to get that authorization code, I was trying to parse the html response from developers.google.com/oauthplayground/ like so:

    def get_google_authorization_code_html():
        import requests
        return requests.post(
            'https://developers.google.com/oauthplayground/',
            json={
                'code': <my_code>,
                'scope': "email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid",
                'authuser': "0",
                'prompt': "consent"
            }
        )

    response = get_google_authorization_code_html()            #;print(f'Google authorization code html returned: {response.content=}')
    self.assertEqual(response.status_code, 200)
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(response.content)                      ;print('Google authorization code html return: '); print(soup.prettify())

However, the input element that in the browser shows the authorization code is actually blank in the html response, so I can't retrieve it from there. Would this even be the proper way to go about this? I may be missing key knowledge as I'm pretty new to OAuth2, Django, and testing. I've been trying to read up on it and particularly diagrams such as the one found in this Medium article make me think I'm more or less on the right track, but I'm not sure.

Aucun commentaire:

Enregistrer un commentaire