class OauthRequest(models.Model): """Stores authorization request so that we can look it up **Args:** * *client:* A oauth2app.models.Client object * *user:* A django.contrib.auth.models.User object **Kwargs:** * *key:* A string representing the authorization code. *Default 30 character random string* * *expire:* A positive integer timestamp representing the access token's expiration time. * *redirect_uri:* A string representing the redirect_uri provided by the requesting client when the code was issued. *Default None* * *scope:* A list of oauth2app.models.AccessRange objects. *Default None* """ client = models.ForeignKey(Client) user = models.ForeignKey(User) code = models.CharField( unique=False, max_length=CODE_KEY_LENGTH, default="", db_index=True) response_type = models.CharField(max_length=20) key = models.CharField( unique=True, max_length=CODE_KEY_LENGTH, default=KeyGenerator(CODE_KEY_LENGTH), db_index=True) issue = models.PositiveIntegerField( editable=False, default=TimestampGenerator()) completed = models.PositiveIntegerField( default=0) scope = models.ManyToManyField(AccessRange) refresh_token = models.CharField( unique=False, blank=True, null=True, max_length=REFRESH_TOKEN_LENGTH, default="", db_index=True) token = models.CharField( unique=False, blank=True, max_length=ACCESS_TOKEN_LENGTH, default="", db_index=True)
class Authorization(models.Model): user = models.ForeignKey(User) scope = models.ForeignKey(Scope) application = models.ForeignKey(Application) payload = models.TextField(null=True, blank=True) active = models.BooleanField(default=False) created_at = models.PositiveIntegerField(editable=False, default=TimestampGenerator()) activated_at = models.PositiveIntegerField(null=True) revoked_at = models.PositiveIntegerField(null=True) access_token = models.ForeignKey(AccessToken, null=True) nonce = models.CharField(null=True, blank=True, max_length=100, default=KeyGenerator(10)) device = models.ForeignKey(Device, null=True)
def get_queryset(self): now = TimestampGenerator()() return AccessToken.objects.filter(user=self.request.user, expire__gt=now)
def get_queryset(self): now = TimestampGenerator()() return Client.objects.filter( accesstoken__user=self.request.user, accesstoken__expire__gt=now, )
def request(request, req_id): """ Receive an authorization code from the server. The request object is used to generate the URL. """ # client => server : create account # server => client: client configuration # client => server: authorize request # server => client: respond with authorization code # XXX Rationalize the URL. Right now it is client/request/aaa # it could easily be request/aaa or callback/aaa log.debug("In apps.client.views.request - entered") if request.META.has_key('HTTP_REFERRER'): log.debug("Referrer = %s " % (request.META['HTTP_REFERRER'])) try: # The oauthRequest object is the state object for the request. It # keeps track of what the user asked and is updated when new # information is received from the server. Lookup that object # first. req = OauthRequest.objects.get(key=req_id) log.debug("Found request = %s " % vars(req)) # Find the code code_key = request.GET.get('code') log.debug("Received code = %s " % code_key) # => Check where the code has been used. Code object has been # deleted. So it cant be used. This is a hack to make things # work with oauth2app if ((req.code == code_key) and (req.completed != 0)): log.error("Duplicate callback. Should not come here") raise Exception("Code already used") #=> Check if the code exists. try: code = Code.objects.get(key=code_key) except: code = None pass if code is not None: # Giving token refresh request triggers a callback to this # looks like (based on the redirect_uri specified") raise Exception("Duplicate code returned") # XXX expire is set automatically. But eventually it must be # transmitted from the server. For some reason the server is # not sending the expiration information. code = Code.objects.create(user=req.user, client=req.client, redirect_uri=request.path, key=code_key) # copy the scope information into the code from the initial # request. This information is not available in the callback # from the server code.scope.add(*req.scope.all()) code.save() log.debug("saved code = %s " % vars(code)) log.debug("code scope = %s " % code.scope) # XXX This is not being used. May be it can be removed. req.completed = TimestampGenerator()() req.code = code_key # we dont store code object because it # will be deleted req.save() log.debug("saved request = %s " % vars(req)) except: traceback.print_exc() pass #client = Client.objects.all()[:1][0] client = req.client # Add this to the code objects template = { "client": client, "basic_auth": "Basic %s" % b64encode(client.key + ":" + client.secret), "codes": Code.objects.filter(client=client).select_related(), "access_tokens": AccessToken.objects.filter(client=client).select_related() } template["error_description"] = request.GET.get("error_description") return render_to_response('client/client.html', template, RequestContext(request))
def refresh_token(request): """ Handle a request from the user for refreshing a token. """ # <form method="post" action="http://localhost:8000/oauth2/token" # class="authenticate"> # <input type="hidden" name="grant_type" value="refresh_token" /> # <input type="hidden" name="refresh_token" value="38d6122e30" /> # <input type="hidden" name="client_id" value="d53d90894c157ab" /> # <input type="hidden" name="scope" value="" /> # <input type="submit" value="38d6122e30"/> # </form> log.debug("in refresh_token") if request.method != "GET": return HttpResponseRedirect("/") # Obtain and lookup a refresh token refresh_token_key = request.GET.get('refresh_token') try: token = AccessToken.objects.get(refresh_token=refresh_token_key) req = OauthRequest.objects.get(refresh_token=refresh_token_key) client = req.client # Start constructing the request that must be sent to the resource # server. params = {} params['client_id'] = settings.RESOURCE_CLIENT_KEY params['grant_type'] = 'refresh_token' params['refresh_token'] = token.refresh_token # Dont need to specify the redirect_uri as we dont need a call # back from the server. Just the json response is enough. params['redirect_uri'] = \ "http://%s/client/request/%s" % (request.get_host(), req.key) # => set the scope of the refresh. Not sure why scope is required # again because it has been specific while obtaining the # authorization. The scope cant be any different. log.debug("type req.scope.all() = %s " % type(req.scope.all())) all_keys = [s.key for s in req.scope.all()] log.debug("all_scopes = %s " % all_keys) if len(all_keys) > 0: params['scope'] = all_keys[0] else: params['scope'] = "" # => params to ready log.debug("params = %s " % params) # Obtain the authentication basic_auth = get_auth() headers = {'Authorization': basic_auth} log.debug("headers = %s " % headers) # Constructing the call url = settings.ACCESS_TOKEN_URL + "/?" + urlencode(params) log.debug("url = %s " % url) # Call the server r = requests.post(url, data="", headers=headers) log.debug("received headers = %s " % r.headers) if r.headers['content-type'] != 'application/json': # Should probably delete the token log.error("Received error from server %s" % r.content) raise Exception("Possible error in request to the server") # => Now store the token for future access purposes grant_data = json.loads(r.content) log.debug("grant data = %s " % grant_data) if grant_data.has_key('error'): # Dont change anything content = grant_data else: # => Update the token state token.token = grant_data['access_token'] token.refresh_token = grant_data['refresh_token'] now = TimestampGenerator()() token.expire = now + int(grant_data['expire_in']) token.save() # Update the request state req.token = grant_data['access_token'] req.refresh_token = grant_data['refresh_token'] req.save() # response content = {'refresh_token': req.refresh_token, 'token': req.token} # wrap if necessary... try: callback = request.GET.get('callback') json_data = "%s(%s);" % (callback, json.dumps(content)) except: json_data = json.dumps(content) # XXX May be this should be the response instead #next = "/client/%s" % client.key #log.debug("Redirecting to %s " % next) #return HttpResponseRedirect(next) # => Send the response back log.debug("Response = %s " % json_data) response = HttpResponse(json_data, content_type="application/json") return response except: traceback.print_exc() raise Exception("Invalid refresh token")