Ejemplo n.º 1
0
def check_nonce():
    """
    This function is an agaveflask authentication callback used to process the existence of a query parameter,
    x-nonce, an alternative authentication mechanism to JWT.
    
    When an x-nonce query parameter is provided, the request context is updated with the identity of the user owning
    the actor to which the nonce belongs. Note that the roles of said user will not be calculated so, in particular, 
    any privileged action cannot be taken via a nonce. 
    """
    logger.debug("top of check_nonce")
    try:
        nonce_id = request.args['x-nonce']
    except KeyError:
        raise PermissionsException("No JWT or nonce provided.")
    logger.debug("checking nonce with id: {}".format(nonce_id))
    # the nonce encodes the tenant in its id:
    g.tenant = Nonce.get_tenant_from_nonce_id(nonce_id)
    g.api_server = get_api_server(g.tenant)
    logger.debug("tenant associated with nonce: {}".format(g.tenant))
    # get the actor_id base on the request path
    actor_id = get_db_id()
    logger.debug("db_id: {}".format(actor_id))
    level = required_level(request)
    Nonce.check_and_redeem_nonce(actor_id, nonce_id, level)
    # if we were able to redeem the nonce, update auth context with the actor owner data:
    logger.debug("nonce valid and redeemed.")
    nonce = Nonce.get_nonce(actor_id, nonce_id)
    g.user = nonce.owner
    # update roles data with that stored on the nonce:
    g.roles = nonce.roles
    # now, manually call our authorization function:
    authorization()
Ejemplo n.º 2
0
    def post(self, actor_id):
        """Create a new nonce for an actor."""
        logger.debug("top of POST /actors/{}/nonces".format(actor_id))
        dbid = Actor.get_dbid(g.tenant, actor_id)
        try:
            Actor.from_db(actors_store[dbid])
        except KeyError:
            logger.debug("did not find actor: {}.".format(actor_id))
            raise ResourceError(
                "No actor found with id: {}.".format(actor_id), 404)
        args = self.validate_post()
        logger.debug("nonce post args validated: {}.".format(actor_id))

        # supply "provided" fields:
        args['tenant'] = g.tenant
        args['api_server'] = g.api_server
        args['db_id'] = dbid
        args['owner'] = g.user
        args['roles'] = g.roles

        # create and store the nonce:
        nonce = Nonce(**args)
        Nonce.add_nonce(dbid, nonce)
        logger.info("nonce added for actor: {}.".format(actor_id))
        return ok(result=nonce.display(), msg="Actor nonce created successfully.")
Ejemplo n.º 3
0
 def lookup_nonce(self, oauth_consumer, oauth_token, nonce):
     
     if oauth_token is None:
         return None
     
     logger.warning("!!! In GAEOAuthDataStore.lookup_nonce  key_:%s, consumer_key: %s, token_key:%s"%(nonce,oauth_consumer.key_,oauth_token.key_))
     
     nonces = Nonce.all()\
         .filter('consumer_key =',oauth_consumer.key_)\
         .filter('token_key =',oauth_token.key_)\
         .filter('key_ =',nonce).fetch(1000)
     
     if len(nonces) == 1:
         nonce = nonces[0]
         return nonce.key_
     elif len(nonces) == 0:
         #create a nonce
         nonce_obj = Nonce(consumer_key=oauth_consumer.key_, 
             token_key=oauth_token.key_,
             key_=nonce)
         nonce_obj.put()
         return None
     else:
         raise Exception('More then one nonce matches consumer_key "%s", \
             token_key "%s", key_ "%S"'%(oauth_consumer.key,oauth_token.key, nonce))
Ejemplo n.º 4
0
    def get(self, request):
        """
        This function initializes the authentication process 
        It builds a challenge which is sent to the client
        """

        # Creates a new nonce associated to this session
        nonce = Nonce()
        nonce.save()

        # Gets the callback uri
        callback_uri = self.get_callback_uri(request)

        # Builds the challenge (bitid uri)
        bitid_uri = bitid.build_uri(callback_uri, nonce.nid)

        # Gets the qrcode uri
        qrcode = bitid.qrcode(bitid_uri)

        context = {
            "callback_uri": callback_uri,
            "bitid_uri": bitid_uri,
            "qrcode": qrcode
        }

        return render(request, self.template_name, context)
Ejemplo n.º 5
0
 def useNonce(self, server_url, timestamp, salt):
     if abs(timestamp - time.time()) > oid_nonce.SKEW:
         return False
     
     try:
         nonce = Nonce( server_url=server_url, timestamp=timestamp, salt=salt)
         nonce.save()
     except:
         raise
     else:
         return 1
Ejemplo n.º 6
0
 def delete(self, actor_id, nonce_id):
     """Delete a nonce."""
     logger.debug("top of DELETE /actors/{}/nonces/{}".format(actor_id, nonce_id))
     dbid = Actor.get_dbid(g.tenant, actor_id)
     try:
         Actor.from_db(actors_store[dbid])
     except KeyError:
         logger.debug("did not find actor: {}.".format(actor_id))
         raise ResourceError(
             "No actor found with id: {}.".format(actor_id), 404)
     Nonce.delete_nonce(dbid, nonce_id)
     return ok(result=None, msg="Actor nonce deleted successfully.")
Ejemplo n.º 7
0
    def validate_timestamp_and_nonce(self,
                                     client_key,
                                     timestamp,
                                     nonce,
                                     request_token=None,
                                     access_token=None):
        token = True
        req_token = True
        client = Client.query(Client.client_key == client_key).get()

        if client:
            nonce = Nonce.query(Nonce.nonce == nonce,
                                Nonce.timestamp == timestamp,
                                Nonce.client == client.key).get()

            if nonce:
                if request_token:
                    req_token = nonce.request_token.get()
                    if req_token and req_token.token == request_token:
                        return False
                if access_token:
                    token = nonce.access_token.get()
                    if token and token.token == access_token:
                        return False
            return True
        else:
            return False
def save_nonce(client_key, timestamp, nonce, request_token, access_token):
    n = Nonce(client_key=client_key,
              timestamp=timestamp,
              nonce=nonce,
              request_token=request_token,
              access_token=access_token)
    nonces.append(n)
    return n
Ejemplo n.º 9
0
    def save_timestamp_and_nonce(self,
                                 client_key,
                                 timestamp,
                                 nonce,
                                 request_token=None,
                                 access_token=None):
        nonce = Nonce(nonce, timestamp)
        nonce.client = Client.query.filter_by(client_key=client_key).one()

        if request_token:
            nonce.token = RequestToken.query.filter_by(
                token=request_token).one()

        if access_token:
            nonce.token = AccessToken.query.filter_by(token=access_token).one()

        db_session.add(nonce)
        db_session.commit()
Ejemplo n.º 10
0
 def get(self, actor_id):
     logger.debug("top of GET /actors/{}/nonces".format(actor_id))
     dbid = Actor.get_dbid(g.tenant, actor_id)
     try:
         Actor.from_db(actors_store[dbid])
     except KeyError:
         logger.debug("did not find actor: {}.".format(actor_id))
         raise ResourceError(
             "No actor found with id: {}.".format(actor_id), 404)
     nonces = Nonce.get_nonces(actor_id=dbid)
     return ok(result=[n.display() for n in nonces], msg="Actor nonces retrieved successfully.")
Ejemplo n.º 11
0
 def get(self, actor_id, nonce_id):
     """Lookup details about a nonce."""
     logger.debug("top of GET /actors/{}/nonces/{}".format(actor_id, nonce_id))
     dbid = Actor.get_dbid(g.tenant, actor_id)
     try:
         Actor.from_db(actors_store[dbid])
     except KeyError:
         logger.debug("did not find actor: {}.".format(actor_id))
         raise ResourceError(
             "No actor found with id: {}.".format(actor_id), 404)
     nonce = Nonce.get_nonce(actor_id=dbid, nonce_id=nonce_id)
     return ok(result=nonce.display(), msg="Actor nonce retrieved successfully.")
Ejemplo n.º 12
0
 def validate_post(self):
     parser = Nonce.request_parser()
     try:
         args = parser.parse_args()
     except BadRequest as e:
         msg = 'Unable to process the JSON description.'
         if hasattr(e, 'data'):
             msg = e.data.get('message')
         raise DAOError("Invalid nonce description: {}".format(msg))
     # additional checks
     if 'level' in args:
         if not args['level'] in PERMISSION_LEVELS:
             raise DAOError("Invalid nonce description. "
                            "The level attribute must be one of: {}".format(PERMISSION_LEVELS))
     if Config.get('web', 'case') == 'snake':
         if 'max_uses' in args:
             self.validate_max_uses(args['max_uses'])
     else:
         if 'maxUses' in args:
             self.validate_max_uses(args['maxUses'])
     return args
 def setUp(self):
     self.user = User(username='******', password='******')
     self.client = Client(user=self.user,
                          redirect_uris=[REDIRECT_URI],
                          realms=['read'],
                          client_key=CONSUMER_KEY,
                          client_secret=CONSUMER_SECRET)
     self.request_token = RequestToken(client=self.client,
                                       token=REQUEST_TOKEN,
                                       secret=REQUEST_TOKEN_SECRET,
                                       redirect_uri=REDIRECT_URI,
                                       realms=['read'],
                                       user=self.user)
     self.access_token = AccessToken(client=self.client,
                                     user=self.user,
                                     realms=[REDIRECT_URI],
                                     token=ACCESS_TOKEN,
                                     secret=ACCESS_TOKEN_SECRET)
     self.nonce = Nonce(client_key=self.client.client_key,
                        timestamp=TIMESTAMP,
                        nonce=NONCE,
                        request_token=REQUEST_TOKEN,
                        access_token=ACCESS_TOKEN)
Ejemplo n.º 14
0
    def save_timestamp_and_nonce(self,
                                 client_key,
                                 timestamp,
                                 nonce,
                                 request_token=None,
                                 access_token=None):

        client = Client.find_one({'client_key': client_key})

        if client:
            nonce = Nonce(nonce, timestamp)
            nonce.client_id = client['_id']

            if request_token:
                req_token = RequestToken.find_one({'token': request_token})
                nonce.request_token_id = req_token['_id']

            if access_token:
                token = AccessToken.find_one({'token': access_token})
                nonce.access_token_id = token['_id']

            nonce.insert()
Ejemplo n.º 15
0
    def validate_timestamp_and_nonce(self,
                                     client_key,
                                     timestamp,
                                     nonce,
                                     request_token=None,
                                     access_token=None):

        token = True
        req_token = True
        client = Client.find_one({'client_key': client_key})

        if client:
            nonce = Nonce.find_one({
                'nonce': nonce,
                'timestamp': timestamp,
                'client_id': client['_id']
            })

            if nonce:
                if request_token:
                    req_token = RequestToken.find_one({
                        '_id':
                        nonce['request_token_id'],
                        'token':
                        request_token
                    })

                if access_token:
                    token = RequestToken.find_one({
                        '_id':
                        nonce['request_token_id'],
                        'token':
                        access_token
                    })

        return token and req_token and nonce != None
Ejemplo n.º 16
0
    def useNonce(self, server_url, timestamp, salt):
        if abs(timestamp - time.time()) > openid_store.nonce.SKEW:
            return False

        query = [
            Q(server_url__exact=server_url),
            Q(timestamp__exact=timestamp),
            Q(salt__exact=salt),
        ]
        try:
            ononce = Nonce.objects.get(reduce(operator.and_, query))
        except Nonce.DoesNotExist:
            ononce = Nonce(server_url=server_url,
                           timestamp=timestamp,
                           salt=salt)
            ononce.save()
            return True

        ononce.delete()

        return False
Ejemplo n.º 17
0
    def save_timestamp_and_nonce(self,
                                 client_key,
                                 timestamp,
                                 nonce,
                                 request_token=None,
                                 access_token=None):
        client = Client.query(Client.client_key == client_key).get()

        if client:
            nonce = Nonce(nonce=nonce, timestamp=timestamp, client=client.key)

            if request_token:
                req_token = RequestToken.query(
                    RequestToken.token == request_token).get()
                nonce.request_token = req_token.key

            if access_token:
                token = AccessToken.query(
                    AccessToken.token == access_token).get()
                nonce.access_token = token.key

            nonce.put()
Ejemplo n.º 18
0
    def post(self, code=None):
        response = RESPONSE.copy()
        if not code:
            desc = "There is/are missing parameters in the request."
            response["response"] = "MissingParameters"
            response["description"] = desc
            response["code"] = 463

        if "X-Signature" in self.request.headers:
            c_sig = self.request.headers['X-Signature']
            s_data = "&".join([
                "POST",
                urllib.quote(self.request.uri),
                urllib.quote(self.request.body)
            ])
            s_sig = generate_signature(LOGIN_KEY, s_data)
            logging.info("v: " + s_sig)
            if c_sig == s_sig:
                try:
                    body = json.loads(self.request.body)
                except:
                    desc = "The request body is not in a valid JSON format."
                    response["response"] = "InvalidJSONFormat"
                    response["description"] = desc
                    response["code"] = 406
                else:
                    if "nonce" in body and "timestamp" in body:
                        new = False
                        nn = Nonce.get_by_id(body["nonce"])
                        if nn:
                            expiry = datetime.datetime.now()
                            expiry = int(time.mktime(expiry.timetuple()))
                            expiry -= int(nn.timestamp)
                            expiry /= 60
                            expiry /= 60
                            if expiry <= 10:
                                new = True
                            else:
                                desc = "This request seems to be expired already"
                                response["response"] = "RequestExpired"
                                response["description"] = desc
                                response["code"] = 464
                        else:
                            n = Nonce(id=body["nonce"])
                            n.nonce = body["nonce"]
                            n.timestamp = int(body["timestamp"])
                            n.put()
                            new = True

                        if new:
                            logincode = LoginCode.get_by_id(str(code))
                            if logincode:
                                s = logincode.session.get()
                                if s.expires >= datetime.datetime.now():
                                    user = s.owner.get()
                                    if user:
                                        t_id = generate_uuid() + generate_uuid(
                                        )
                                        token = Token(id=t_id)
                                        token.token = t_id
                                        token.session = s.key
                                        token.token_type = "api"
                                        token.put()
                                        response = user.to_object(token=t_id)
                                        response["response"] = "Successful"
                                        response["expires"] = time.mktime(
                                            s.expires.timetuple())
                                        response["code"] = 200
                                    else:
                                        s.status = False
                                        s.put()
                                        response[
                                            "response"] = "UserUnavailable"
                                        response[
                                            "description"] = "This user seems to be unavailable"
                                        response["code"] = 404
                                else:
                                    response["response"] = "SessionExpired"
                                    response[
                                        "description"] = "This session seems to be expired already"
                                    response["code"] = 465
                            else:
                                response["response"] = "LoginCodeDoesNotExist"
                                response[
                                    "description"] = "This login code does not exist."
                                response["code"] = 404
                    else:
                        response["response"] = "MissingParameters"
                        response[
                            "description"] = "There is/are missing parameters in the request."
                        response["code"] = 463
            else:
                response["response"] = "InvalidSignature"
                response[
                    "description"] = "The request signature is invalid or has been tampered."
                response["code"] = 460
        else:
            response["response"] = "MissingParameters"
            response[
                "description"] = "There is/are missing parameters in the request."
            response["code"] = 463

        wrap_response(self, response)
Ejemplo n.º 19
0
def check_nonce():
    """
    This function is an agaveflask authentication callback used to process the existence of a query parameter,
    x-nonce, an alternative authentication mechanism to JWT.
    
    When an x-nonce query parameter is provided, the request context is updated with the identity of the user owning
    the actor to which the nonce belongs. Note that the roles of said user will not be calculated so, in particular, 
    any privileged action cannot be taken via a nonce. 
    """
    logger.debug("top of check_nonce")
    # first check whether the request is even valid -
    if hasattr(request, 'url_rule'):
        logger.debug("request.url_rule: {}".format(request.url_rule))
        if hasattr(request.url_rule, 'rule'):
            logger.debug("url_rule.rule: {}".format(request.url_rule.rule))
        else:
            logger.info("url_rule has no rule.")
            raise ResourceError(
                "Invalid request: the API endpoint does not exist or the provided HTTP method is not allowed.",
                405)
    else:
        logger.info("Request has no url_rule")
        raise ResourceError(
            "Invalid request: the API endpoint does not exist or the provided HTTP method is not allowed.",
            405)
    try:
        nonce_id = request.args['x-nonce']
    except KeyError:
        raise PermissionsException("No JWT or nonce provided.")
    logger.debug("checking nonce with id: {}".format(nonce_id))
    # the nonce encodes the tenant in its id:
    g.tenant = Nonce.get_tenant_from_nonce_id(nonce_id)
    g.api_server = get_api_server(g.tenant)
    logger.debug(
        "tenant associated with nonce: {}; api_server assoicated with nonce: {}"
        .format(g.tenant, g.api_server))
    # get the actor_id base on the request path
    actor_id, actor_identifier = get_db_id()
    logger.debug("db_id: {}; actor_identifier: {}".format(
        actor_id, actor_identifier))
    level = required_level(request)

    # if the actor_identifier is an alias, then the nonce must be attached to that, so we must pass that in the
    # nonce check:
    if is_hashid(actor_identifier):
        Nonce.check_and_redeem_nonce(actor_id=actor_id,
                                     alias=None,
                                     nonce_id=nonce_id,
                                     level=level)
    else:
        alias_id = Alias.generate_alias_id(tenant=g.tenant,
                                           alias=actor_identifier)
        Nonce.check_and_redeem_nonce(actor_id=None,
                                     alias=alias_id,
                                     nonce_id=nonce_id,
                                     level=level)
    # if we were able to redeem the nonce, update auth context with the actor owner data:
    logger.debug("nonce valid and redeemed.")
    if is_hashid(actor_identifier):
        nonce = Nonce.get_nonce(actor_id=actor_id,
                                alias=None,
                                nonce_id=nonce_id)
    else:
        nonce = Nonce.get_nonce(actor_id=None,
                                alias=alias_id,
                                nonce_id=nonce_id)
    g.user = nonce.owner
    # update roles data with that stored on the nonce:
    g.roles = nonce.roles
    # now, manually call our authorization function:
    authorization()