Samuele B.
Samuele B.

Reputation: 658

Storing access_token and refresh_token in Django from a gapi response

I have an LMS application made with Django REST and Vue.js. To authenticate users, I use Google OAuth2 the following way:

The way it works is the following: the user clicks on the login button and is redirected to the account selection page in Google which, when completed, returns an access token. The frontend makes a request to an endpoint on the backend which uses the convert-token function provided by drf-social-oauth2 to exchange the Google access token with an in-house token that the frontend can use from then on to authenticate requests.

I recently added a Google Classroom integration to my application which makes some requests on the students' behalf to Classroom, which requires using their access tokens.

The problem is that with this procedure, I don't actually keep the Google issued token on my backend; I just use it to generate the in-house token.

How can I modify the procedure I outlined so that I can keep users' access tokens?

I thought I had a plan but apparently it's not quite what I need:

I created this model to store the Google tokens

class GoogleOAuth2Credentials(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    access_token = EncryptedTextField()
    refresh_token = EncryptedTextField()
    id_token = EncryptedTextField()
    scope = models.JSONField(validators=[validate_str_list])

Then I can add a method to the drf-social-oauth2 pipeline what looks like this:

def store_token(backend, strategy, details, response, user=None, *args, **kwargs):
    GoogleOAuth2Credentials.objects.create_or_update(
        user=user,
        defaults={"access_token": response["access_token"], refresh_token=response["refresh_token"]
    )

This function would be executed every time the convert-token procedure is used and would allow me to store the token. There's only one issue with this: the response doesn't contain a refresh_token, so all I would have is an access_token, which isn't very practical.

I believe the reason there is no refresh_token is that the response comes from the frontend gapi client, which has some limitations.

How can I get around this issue?

Upvotes: 2

Views: 825

Answers (1)

Jeremy
Jeremy

Reputation: 1578

I may be wrong here, but if i am right you should not be storing the access token (i think they expire in an hour), but should be storing the refresh token as an access token is only valid for the scope of the request for that service it was created for.

It is the refresh token that gives you ability to make additional requests with new tokens. So you can save that with the id / secret to get auth later.

enter image description here

So you would want to do something like https://www.googleapis.com/oauth2/v4/token?client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&refresh_token=${REFRESH_TOKEN}&grant_type=refresh_token after you have made the first request to get the refresh token to get other access tokens and make additional requests.

TLDR access tokens are disposable!

Hope this is at least a little bit helpful!

Upvotes: 1

Related Questions