How to generate an AccessToken programmatically in Django?
Asked Answered
R

6

12

I'm setting up an API. Everything is working. I'm creating a token via OAuth2 python lib. I'm using TastyPie for my API.

The problem I'm facing.. is that there is no "create" token method in the AccessToken or Client models.

I can create an accessToken via the Django admin, and I can create one by doing a curl to:

myhost.com/oauth2/access_token (with all the info, secret key, client id, user & pass)

my goal is to upon successful registration of a user with my API, the oAuth client is automatically created (working) but I also want to generate the AccessToken. I cannot cURL my own server as its giving me a redirect/connection refused error so I want to do it programmatically in Python. Anyway to do this? Here's a snippet:

try:
        user = User.objects.create_user(username, password)
        user.save()

        if user:
            oauth_client = Client(user=user, name="api account", client_type=1, url="http://example.com")
            oauth_client.save()

            oauth_client_id = oauth_client.pk
            oauth_client_secret = oauth_client.client_secret

        if oauth_client:
            print user
            print oauth_client_id
            print AccessToken.objects.all()
            print '........'
            token = AccessToken(user=user, client=oauth_client_id, scope=6)
            token.save()

the last two lines above, while giving NO errors.. will NOT save a new AccessToken.

Ruberta answered 25/7, 2013 at 20:23 Comment(5)
What exact library do you use? hiidef.github.io/oauth2app or code.google.com/p/django-oauth2 or some other?Terreverte
github.com/caffeinehit/django-oauth2-provider <-- This one. I installed it via PIP (django-oauth2-provider==0.2.6). Is that the problem, am I using the wrong library?Ruberta
Not the wrong one. They all the same but a little different;).Terreverte
Ah OK. I might have to try this one instead: github.com/brosner/python-oauth2 I just spent all day on this library so it will suck to start over :(. Any other ideas @Terreverte ? Hi to Russia btw! I'm originally from Rostov :PRuberta
What happens if you change client=client=oauth_client_id with client=client=oauth_client in AccessToken(...)?Terreverte
R
9

I'm using https://github.com/caffeinehit/django-oauth2-provider. I managed to create access token and refresh token by using models. I might be bypassing grant flow. I haven't used this code in production but in development server i can perform API calls using the access token generated this way. I think it should be well tested before going to production.

#settings.py
OAUTH2_PROVIDER = {
# this is the list of available scopes
'SCOPES': {'read': 'Read scope'},
'ACCESS_TOKEN_EXPIRE_SECONDS': 36000,
} 

#views.py
expire_seconds = oauth2_settings.user_settings['ACCESS_TOKEN_EXPIRE_SECONDS']
scopes = oauth2_settings.user_settings['SCOPES']

application = Application.objects.get(name="ApplicationName")
expires = datetime.now() + timedelta(seconds=expire_seconds)
access_token = AccessToken.objects.create(
                user=user,
                application=application,
                token=random_token_generator(request),
                expires=expires,
                scope=scopes)

refresh_token = RefreshToken.objects.create(
                user=user,
                token=random_token_generator(request),
                access_token=access_token,
                application=application)

token = {
                'access_token': access_token.token,
                'token_type': 'Bearer',
                'expires_in': expire_seconds,
                'refresh_token': refresh_token.token,
                'scope': scopes}

return Response(token, status=200)
Returnable answered 2/8, 2014 at 13:9 Comment(8)
Hi, Is there any way to send unexpired access token when user request for token frequently? As of now it creates multiple tokens instead of returning same!!!!! Need solutionIngamar
There's a parameter for single access token (django-oauth2-provider.readthedocs.org/en/latest/…) but I think it doesn't work with this manual method. You can check whether user has a valid access token or not and return the corresponding token.Returnable
thanks @uger..While using the above code i am getting 'Name Error'..global name 'AccessToken' is not defined..Ingamar
Did you import necessary packages? from oauth2_provider.models import AccessToken, Application, RefreshTokenReturnable
It worked @Ugur.. One more help, I want to create single access token to for each user..Whenever i hit create token using framework URL /o/token/?grant_type=password&username=xxx&password=xxx&client_id=xxx&client_secret=xxx , It creates new accesstoken though having unexpired token in table.. I want to restrict it with authentication,authorization..Could you help me,,\Ingamar
github.com/caffeinehit/django-oauth2-provider/blob/master/… review this function. Try to fetch an existing token first, if no token found then try to generate a new token with the method in my answer.Returnable
I have seen that @Returnable , i am using Oauth Toolkit Which is using generic view structure,,Ingamar
@Tommy I'm haven't tested against OAuth Toolkit at all, but the logic is the same. You have to check if there are any valid access tokens in the database and take necessary action according the result of the query, that's all.Returnable
M
2

This is how I was able to make it work:

from oauth2_provider.views import TokenView
import json

class SuperUserLogin(views.APIView):
permission_classes = (permissions.AllowAny, )

def post(self, request, **kwargs):
    url, headers, body, status_code = TokenView().create_token_response(request)
    return Response(json.loads(body), status=status_code)

This is how my request object looks like.

{
"username" : email,
"password" : password,
"client_id" : client_id,
"client_secret" : client_secret,
"grant_type" : password

}

This generates the desired access_token. I've verified the token creation on my database.

Myrmecophagous answered 11/10, 2018 at 16:57 Comment(0)
T
1

Based on what I see here https://github.com/caffeinehit/django-oauth2-provider/blob/master/provider/oauth2/views.py#L93 token creation is done this way

access_token = AccessToken.objects.create(
    user=user,
    client=client,
    scope=scope
)
RefreshToken.objects.create(
    user=user,
    access_token=access_token,
    client=client
)

I assume second token isn't so interesting for you so it's almost your code but with managers create() method. The only difference it makes is that manager calls save() with force_insert=True.

So try

token.save(force_insert = True)
Terreverte answered 25/7, 2013 at 22:22 Comment(5)
Hey twil. Thank you for the response! So I tried this before (using the AccessToken.objects.create() but not with .save(force_insert = True). I thought it would do the trick but it still doesn't insert the token. Everything else works fine. I don't get any errors using your code but no DB insert either. The thing that is making me pull my hair is out is I can create a token via the Admin panel in Django!!! :(Ruberta
I think the problem might be that I need a 'grant' first to get an access_token but I'm not sure. I will do some more reading :|Ruberta
That's very strange because there's no extra checks before save. grant object here github.com/caffeinehit/django-oauth2-provider/blob/master/… is used only to get user and scope. May it be that you use database router?Terreverte
Well right now I am testing this on my localhost (a VM running ubuntu). To connect to my test MySQL database, I have to open a pipe. But the database is saving everything else fine.Ruberta
Is there a way I can debug the admin view that creates the access token? To see exactly what it calls? Or is there a way to debug AccessToken.objects.create()? Because it doesn't throw ANY errors at all, it just DOESNT save in the database.Ruberta
A
0

I was able to get this to work in Django 1.6 using the following:

token = AccessToken.objects.create(user=user,
                                   client=Client.objects.get(name=clientName),
                                   scope=3)
Appurtenant answered 22/4, 2014 at 12:29 Comment(0)
U
0

Try below,

In [1]: import base64

In [2]: from django.conf import settings

In [3]: from django.http import HttpRequest

In [4]: from oauth2_provider.views import TokenView


In [5]: request = HttpRequest()

In [6]: key = base64.b64encode('{}:{}'.format(<CLIENT_ID>, <SECRET_KEY>))

In [7]: request.META = {'HTTP_AUTHORIZATION': 'Basic {}'.format(key)}

In [8]: request.POST = {'grant_type': 'password', 'username': '<USERNAME>', 'password': '<PASSWORD>'}

In [9]: tv = TokenView()

In [10]: url, headers, body, status = tv.create_token_response(request)

In [11]: body
Out [11]: '{"access_token": "IsttAWdao3JF6o3Fk9ktf2gRrUhuOZ", "token_type": "Bearer", "expires_in": 36000, "refresh_token": "y2KQyyliOuRIXf3q9PWzEUeBnx43nm", "scope": "read write"}'
Unwish answered 4/4, 2016 at 12:5 Comment(0)
T
0

Try this one, I just tested it moments earlier

>>> from oauth2_provider.models import Application
>>> app = Application.objects.create(name="Sample ORM", client_type="public", authorization_grant_type="password", user_id=1)
<Application: Sample ORM>
>>> import requests
>>> from requests.auth import HTTPBasicAuth
>>> 
>>> 
>>> data = "grant_type=password&username=admin&password=d3@narmada13"
>>> headers = {"content-type": "application/x-www-form-urlencoded"}
>>> r = requests.post(token_url, data=data, auth=(app.client_id, app.client_secret), headers=headers)
>>> print r.content
{"access_token": "5kEaw4O7SX6jO9nT0NdzLBpnq0CweE", "token_type": "Bearer", "expires_in": 7776000, "refresh_token": "ZQjxcuTSTmTaLSyfGNGqNvF3M6KzwZ", "scope": "read write"}
>>> import json
>>> json.loads(r.content)['access_token']
u'5kEaw4O7SX6jO9nT0NdzLBpnq0CweE'
>>> 
Triad answered 22/9, 2016 at 4:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.