Re: Basic Authentication in the header - Authorization : Basic <key>

'Björn Pedersen' via cherrypy-users <cherrypy-users-/[email protected]> Tue, 10 Apr 2018 22:43:56 -0700 (PDT)
Newsgroups gmane.comp.python.cherrypy
Message-ID <[email protected]>
import cherrypy

def check_auth():
  needs_auth = cherrypy.request.config.get('auth.require', False)
  if needs_auth and not cherrypy.request.headers.get('X-HTTP-APIKEY', None) 
=="1234":
     raise cherrypy.HTTPError(401)


cherrypy.tools.auth = cherrypy.Tool('before_handler', check_auth, priority=
50)


def needsauth():
    '''A decorator that sets auth.require config
    variable.'''

    def decorate(f):
        if not hasattr(f, '_cp_config'):
            f._cp_config = dict()
        if 'auth.require' not in f._cp_config:
            f._cp_config['auth.require'] = []
        f._cp_config['auth.require'] = True
        return f

    return decorate


class main(object):
    _cp_config = {'tools.auth.on': True,}
    @cherrypy.expose
    @needsauth()
    def myfunction(self):
        print 1
        return '<html>Hi</html>'

cherrypy.quickstart(main())






Am Dienstag, 10. April 2018 21:44:19 UTC+2 schrieb ElliotB:
>
> Thanks for that, Björn, however, I'm not sure if the decorator is fully 
> working.  Can you try it yourself?  I added a function to the above code:
>     def generate(self, length=8):
>       print("in the function called generate now, past security" )
>       return ''.join(random.sample(string.hexdigits, int(length)))
>
> Then, whenI assure there is **NO** header set (see Postman screenshot) 
> the request goes through without violating the authentication of the 
> string which is '12345'
>
> I don't believe the function check_auth is called.  I do see that the two 
> functions, needsauth and decorate are indeed called.
> Again, sorry, but can you test the code yourself (see prior posts) and let 
> me know if you can run it with and without a header with a key 
> of X-HTTP-APIKEY and a value of 12345?
> I'd like to see if the two conditions, validated and unvalidated can be 
> shown.
> thanks
>
> On Monday, April 9, 2018 at 10:09:29 AM UTC-4, Björn Pedersen wrote:
>>
>> Im fault,
>>
>> it should habe been 
>> @needsauth()  (and no dummy arg)
>>
>> Björn
>>
>> Am Freitag, 6. April 2018 05:43:49 UTC+2 schrieb ElliotB:
>>>
>>> Björn
>>> Thanks for the quick reply.  However, Björn, I set up 'quickstart' and 
>>> implemented your code example and had two situations.
>>> 1. if the needsauth function does not have a single parameter, Cherrypy 
>>> returns this:
>>>         class HelloWorld(object):
>>>               File "/Volumes/NAOMI 
>>> PIX/Caremarkets/Cherrypy/Authentication.py", line 36, in HelloWorld
>>>               @needsauth
>>>         TypeError: needsauth() takes 0 positional arguments but 1 was 
>>> given
>>>
>>> So, at this time, I simply put in a dummy argument.!!!??!?!?
>>>
>>> 2. With the dummy argument in the needsauth function, when running this 
>>> code below, I am rewarded with this traceback:
>>>    upon running the following     :   
>>>
>>>               http://locahost:8080/myfun
>>>
>>>
>>> 500 Internal Server Error
>>>
>>> The server encountered an unexpected condition which prevented it from 
>>> fulfilling the request.
>>>
>>> Traceback (most recent call last):
>>>   File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/cherrypy/_cprequest.py", line 631, in respond
>>>     self._do_respond(path_info)
>>>   File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/cherrypy/_cprequest.py", line 690, in _do_respond
>>>     response.body = self.handler()
>>>   File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/cherrypy/lib/encoding.py", line 264, in __call__
>>>     ct.params['charset'] = self.find_acceptable_charset()
>>>   File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/cherrypy/lib/encoding.py", line 173, in find_acceptable_charset
>>>     if encoder(self.default_encoding):
>>>   File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/cherrypy/lib/encoding.py", line 114, in encode_string
>>>     for chunk in self.body:
>>> TypeError: 'HelloWorld' object is not iterable
>>>
>>> Powered by CherryPy 14.0.0 <http://www.cherrypy.org/>
>>>
>>>
>>> My code now:
>>>
>>> import cherrypy
>>>
>>>
>>> class HelloWorld(object):
>>>     @cherrypy.expose
>>>     
>>>     def index(self):
>>>         return "Hello world!"
>>>
>>>  
>>>
>>>     def check_auth():
>>>       needs_auth = cherrypy.request.config.get('auth.require', False)
>>>       print ("in check_auth")
>>>       if needs_auth and not cherrypy.request.header.get('X-HTTP-APIKEY', 
>>> None) == '12345':
>>>          raise cherrypy.HTTPError(404) 
>>>
>>>     cherrypy.tools.auth = cherrypy.Tool('before_handler', check_auth, 
>>> priority=50)
>>>
>>>     def needsauth(dummy):      #  if I don't put in a parameter:
>>>         """
>>>
>>>                   class HelloWorld(object):
>>>               File "/Volumes/NAOMI 
>>> PIX/Caremarkets/Cherrypy/Authentication.py", line 36, in HelloWorld
>>>               @needsauth
>>>         TypeError: needsauth() takes 0 positional arguments but 1 was 
>>> given
>>>
>>>         """
>>>         '''A decorator that sets auth.require config
>>>         variable.'''
>>>         print("in needsauth")
>>>
>>>         def decorate(f):
>>>             if not hasattr(f, '_cp_config'):
>>>                 f._cp_config = dict()
>>>             if 'auth.require' not in f._cp_config:
>>>                 f._cp_config['auth.require'] = []
>>>             f._cp_config['auth.require'] = True
>>>             return f
>>>
>>>         return decorate
>>>
>>>     @cherrypy.expose
>>>     @needsauth
>>>     def myfun():
>>>       print("in myfunction now, past security")
>>>       return
>>>
>>>     @cherrypy.expose
>>>     def stop(self):
>>>         """
>>>         Stop the server
>>>         """
>>>         cherrypy.engine.exit()
>>>         cherrypy.engine.stop()
>>>
>>>
>>> if __name__ == '__main__':
>>>
>>>     cherrypy.server.socket_host = '0.0.0.0' # put it here 
>>>     cherrypy.quickstart(HelloWorld(), '/')
>>>
>>>
>>>   - - - - - - - -
>>>
>>>
>>> Ideas?  Again, really new to Cherrypy so your help is much appreciated.
>>>
>>> Thanks
>>>
>>>
>>>
>>> On Thursday, April 5, 2018 at 5:21:02 AM UTC-4, Björn Pedersen wrote:
>>>>
>>>> Hi, 
>>>>
>>>> I would not recommend to mix API-Key auth and Basic Auth. 
>>>> Send it as e.g X-HTTP-APIKEY header, and in your handler function (or 
>>>> some tool function) 
>>>> inspect cherrypy.request.header
>>>>
>>>> using a tool function:
>>>>
>>>>
>>>> def check_auth():
>>>>   needs_auth = cherrypy.request.config.get('auth.require', False)
>>>>   if needs_auth and not cherrypy.request.header.get('X-HTTP-APIKEY', 
>>>> None) == <your key here>:
>>>>      raise cherrypy.HTTPError(404) 
>>>>
>>>> cherrypy.tools.auth = cherrypy.Tool('before_handler', check_auth, 
>>>> priority=50)
>>>>
>>>> def needsauth():
>>>>     '''A decorator that sets auth.require config
>>>>     variable.'''
>>>>
>>>>     def decorate(f):
>>>>         if not hasattr(f, '_cp_config'):
>>>>             f._cp_config = dict()
>>>>         if 'auth.require' not in f._cp_config:
>>>>             f._cp_config['auth.require'] = []
>>>>         f._cp_config['auth.require'] = True
>>>>         return f
>>>>
>>>>     return decorate
>>>>
>>>> @cherrypy.expose
>>>> @needsauth
>>>> def myfunction(....):
>>>>   .....
>>>>
>>>>
>>>> Björn
>>>>
>>>>
>>>>
>>>>
>>>> Am Donnerstag, 5. April 2018 08:14:06 UTC+2 schrieb ElliotB:
>>>>>
>>>>> I've reviewed the documentation at 
>>>>> http://cherrypy.readthedocs.io/en/latest/basics.html#authentication in 
>>>>> order to understand how to send my API call to Cherrypy and validate an API 
>>>>> key that I'll have in the header of the HTTP request that I'll send from my 
>>>>> client side program. The header will follow Basic Authorization with the 
>>>>> header having the following example key and value Example: Authorization: 
>>>>> Basic YWxhZGRpbjpvcGVuc2VzYW1l
>>>>>
>>>>> Then I want the Cherrypy function that I write to run only after some 
>>>>> authorization has be completed. From the client, I'll call my function 
>>>>> like: https:///myfunction?param1=value&param2=value&param3=value with the 
>>>>> Basic Authorization header set up as seen above
>>>>>
>>>>> and in Cherrypy I'll code the function like:
>>>>>
>>>>>  @cherrypy.expose
>>>>>     def myfunction(self, param1=1,param2=cat,param3=dog):
>>>>>             # do my work in the function 
>>>>>         return 
>>>>>
>>>>> Note: the function will not have a user enter any credentials. The 
>>>>> call will pre-populate the basic authorization header programmatically.
>>>>>
>>>>> Can you set up the Cherrypy code example in such a way to explicitly 
>>>>> show me how this can be achieved. Assume a beginner with Cherrypy (e.g. did 
>>>>> the first 5 or so tutorials only ( 
>>>>> http://docs.cherrypy.org/en/latest/tutorials.html#tutorials ). Thanks 
>>>>> much.
>>>>>
>>>>>

-- 
You received this message because you are subscribed to the Google Groups "cherrypy-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cherrypy-users+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
To post to this group, send email to cherrypy-users-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
Visit this group at https://groups.google.com/group/cherrypy-users.
For more options, visit https://groups.google.com/d/optout.