dataclass-rest icon indicating copy to clipboard operation
dataclass-rest copied to clipboard

Authorization (question)

Open nightblure opened this issue 1 year ago • 5 comments

Hi!

Does your wrapper have the ability to send requests with an authentication token? As a client I could provide an endpoint and authorization data, and in return I could receive, for example, a json web token. This assumes correct operation in a concurrent environment within one service instance and caching of the token until it expires

nightblure avatar Aug 01 '24 13:08 nightblure

It depends on a logic required for token and concrete http backend. Here are some trivial examples https://github.com/annetutil/annetbox/blob/main/src/annetbox/base/client_sync.py#L149 https://github.com/reagento/dataclass-rest/blob/develop/examples/vkapi_example.py#L43

As you need refreshable token the simpliest way is to put that logic into do_request method:

class Client(RequestsClient):
    def do_request(self, request: HttpRequest) -> Any:
         token = get_token()  # you logic
         self.session.headers["Authorization"] = f"Token {token}"
         super().do_request(request)

From library side we can probably extend HttpRequest object with headers and add explicit authorization callback. But probably it is not required

Tishka17 avatar Aug 01 '24 14:08 Tishka17

I think your example works, but clearly in a suboptimal way. a token usually has a lifetime and it would be better for us to use the same token until the current one expires


By the optimal solution I mean your code but with the changes that the wrapper knows when to send a request to receive a token, and when not necessary, and it caches the token if it is still valid

Moreover, you will need to cache the token either locally (if there is one instance of the service), or in a shared data source such as postgresql, redis, and etc. (in the case of, for example, several k8s pods or several wsgi/asgi processes)

nightblure avatar Aug 01 '24 14:08 nightblure

I did not mean you need to get new token every time in that method. You can implement your own logic here. There are so many options that I can't imagine now how framework can provide any help here

Tishka17 avatar Aug 01 '24 21:08 Tishka17

Understood Thanks!

nightblure avatar Aug 03 '24 14:08 nightblure

In version 0.5 we have reques.headers field. So this code can be done in more cleaner if the Session is shared

class Client(RequestsClient):
    def do_request(self, request: HttpRequest) -> Any:
         token = get_token()  # you logic
         request.headers["Authorization"] = f"Token {token}"
         super().do_request(request)

Tishka17 avatar Mar 21 '25 12:03 Tishka17