[Python] Best practices mbt API Token renewal

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Yariva
  • Registratie: November 2012
  • Laatst online: 11:38

Yariva

Moderator Internet & Netwerken

Power to the people!

Topicstarter
Voor een Flask (Python web server) projectje babbel ik met een API. Deze API werkt middels token based authentication. De eerste API call is het verkrijgen van het token middels gebruikersnaam + wachtwoord. Hierna krijg je een token dat na een aantal uur verloopt. Output ziet er als volgt uit:

{“code”:200,”success”:true,”data”:{“token”:”Z1q=j2bdwx56NR14KFcTi7P$”,”expires”:”2015-07-09 20:05:28″}}

Mijn vraag, was is de beste manier om om te gaan met het verlopen van het token? Ik zou een while loopje ergens kunnen schrijven (bijvoorbeeld in mijn __init__ bestand(?)) die non-stop checkt hoever de houdbaarheid van het token is. Wanneer hij onder een uur komt kan het script een request inschieten naar de API om de expiration date op te schuiven.

Een 2de methode is voor iedere keer dat de applicatie word gebruikt (een gebruiker drukt op een knopje met "haal data van API op") een nieuw token vragen. Dit lijkt mij enorm inefficiënt. Dit zou nu kunnen werken met 5 - 7 gebruikers en is de methode die ik nu gebruik. Echter is het idee dat de applicatie, en niet een gebruiker, de token aanvraagt en beheerd veel aantrekkelijker dan dat ik die API volblaf met nieuwe token aanvragen voor iedere handeling van iedere gebruiker.

Weten jullie hier een aantal tips voor / hoe hebben jullie dit gefixt in een omgeving?

Mensen zijn gelijk, maar sommige zijn gelijker dan andere | Humans need not apply

Alle reacties


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik ben niet super bekend met de materie, maar check gewoon voordat je een request doet of je token nog geldig is en zo niet dan request je even een nieuwe, slaat die ergens op en ga door waar je gebleven was.

Wellicht heb je hier iets aan, maar dan moet je dus wel werken met acces tokens en refresh tokens (en dat haal ik niet uit je topicstart):
https://auth0.com/blog/re...hey-and-when-to-use-them/
https://tools.ietf.org/html/rfc6749#page-10

[ Voor 68% gewijzigd door RobIII op 23-10-2019 12:01 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • +1 Henk 'm!

  • Marco1994
  • Registratie: Juli 2012
  • Laatst online: 16:20
Wij krijgen van onze api meestal een Token-Expired header icm een 401 terug. In onze middleware checken we als we een 401 en een Token-Expired header krijgen. Als dat zo is ververs je je token. Vervolgens vuur je opnieuw je originele request

[ Voor 6% gewijzigd door Marco1994 op 23-10-2019 12:17 ]


Acties:
  • 0 Henk 'm!

  • Yariva
  • Registratie: November 2012
  • Laatst online: 11:38

Yariva

Moderator Internet & Netwerken

Power to the people!

Topicstarter
Interessant, dank voor de input. Ik heb het opgelost door de volgende functie toe te voegen aan mijn class:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def checkTokenRenewal(self):
    # Pak de huidige tijd
    current_time = datetime.now().isoformat(' ', 'seconds')
    # Wanneer het token verlopen is
    if(current_time >= self.token_expires):
        # Maak een API call om het token te verlengen.
        r = requests.patch("URL", headers={"token":self.token})
        data = json.loads(r.text)
        # Als de API met success terug komt
        if(data["success"]):
            # Zet de token expire data naar de nieuw verkregen datum / tijd.
            self.token_expires = data["data"]["expires"]
        else:
            # Raise customerror
            raise TokenException()

Deze functie pak ik vervolgens in mijn overige functies waarbij er een API call word gemaakt. Dat betekend dat, wanneer het token nog geldig is, de volgende berekeningen altijd worden gemaakt:
- Huidige tijd berekenen
- Check of het token verlopen is dmv een IF statement met de token expire data
code:
1
2
3
def maakEenCooleApiCall(self, data):
    self.checkTokenRenewal()
    #Doe overige meuk...

Mogelijk kan het nog efficiënter, maar hier ben ik al een stuk blijer mee.

Mensen zijn gelijk, maar sommige zijn gelijker dan andere | Humans need not apply


Acties:
  • +2 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Yariva schreef op woensdag 23 oktober 2019 @ 14:28:
code:
1
2
3
4
5
def checkTokenRenewal(self):
    # Pak de huidige tijd
    current_time = datetime.now().isoformat(' ', 'seconds')
    # Wanneer het token verlopen is
    if(current_time >= self.token_expires):
Meh... hou er rekening mee dat je klok mogelijk (flink) afwijkt van de andere kant. Ik zou dus ook zeker een minuut of 5 "marge" houden. Maar either way, je moet toch de 'exceptie' afvangen dat de andere kant zegt "nope, niet (meer) geldig token". Doe op dat moment gewoon wat @Marco1994 zegt et voila. De "client side" check op datum/expired is alleen maar een "optimalisatie".

[ Voor 31% gewijzigd door RobIII op 23-10-2019 14:43 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • +1 Henk 'm!

  • Ben(V)
  • Registratie: December 2013
  • Laatst online: 16:43
Even een paar opmerkingen:

Als je geen object gebruikt maar een simpele functie moet je natuurlijk ook geen "self." gebruiken, dat heeft geen nut.
Elke request die je uitstuurt moet een timeout hebben, want als je geen antwoordt krijgt hangt je programma voor eeuwig.
Als je json data terug krijgt en je zet dat om in een dict om vervolgens ervan uit te gaan dat wat je krijgt de juist benamingen heeft en dat is niet zo, dan crashed je programma.
Dus altijd get get() gebruiken, als de json dan niet correct is krijg je gewoon een "None" value en geen crash
Als bijvoorbeeld in jouw geval data["data"]["expires"] niet in die jason zit gaat het mis.

Hier een opzetje hoe je een token object maakt in plaats van een functie
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class token():
    def __init__():
        self.token_expires = datetime.now().isoformat(' ', 'seconds')
        self.get_token()

    def get_token(self):
        self.token = None
        # hier de code om het token op te halen

    def refresh_token(self):
        if self.token_expires > datetime.now().isoformat(' ', 'seconds'):
            return self.check_token
        else:
            try:
                Result = requests.patch("URL", headers={"token":self.token}, timeout=10)
                if Result.ok:
                    data = json.loads(Result.text)
                    if "success" in data:
                        self.token_expires = data.get("data").get("expires")   
                    else:
                            # geen succes dan vraag een nieuw totken op
                        self.get_token()
                    return self.token
                else:
                   raise Exception('Timeout on tokencall')
            except EXCEPTION as error:
                ......
                return None
                # hier een actie als je geen antwoordt krijgt of een andere exceptie.
                # kijk na welke exception van request kunt krijgen en bedenk de juiste actie

    # Hiermee initialiseer je een token
Token = token()
    # Hiermee refresh je een token indien nodig
if Token.refresh_token():
    .......

All truth passes through three stages: First it is ridiculed, second it is violently opposed and third it is accepted as being self-evident.

Pagina: 1