Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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,
     )
Exemplo n.º 5
0
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))
Exemplo n.º 6
0
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")