Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Intégrer Python Social Auth à une app Django

+5 votes

Actuellement ce que je vais décrire marche au poil :

je suis dans un formulaire qui permet à l'utilisateur de choisir d'activer un service de son choix dans une liste déroulante. A l'issue de son choix je créé dans une table UserService ; l'id du service, du user et le token péché chez twitter par exemple.

Tout ceci est fait "main" (je le recode pour chaque service selon la couverture de fonctionnalité des lib Python) pour chaque service tiers.

Ca c'etait l'intro du truc ;)

Maintenant mon désiderata :

Comme je trouve ca pénible, j'aimerai avoir recours à python-social-auth qui semble couvrir ce besoin.
On notera que j'en ai absolument rien a faire que python-social-auth permette au quidam de se connecter à mon app avec un compte fb / twitter / G+ et j'en passe, je ne suis interesse que par la gestion du "workflow oauth(2)" que je ne veux plus gérer :P

Mais j'ai parcouru la doc en long en large et en travers et je n'ai pas trouvé le moyen de "simplement" déclencher une requete vers le service tiers pour avoir soit le token, soit vérifier que mon token est bon soit requeter un nouveau token.

Tout ce que j'ai trouvé, c'est qu'il faut faire un lien dans une page web, qui fasse :

<a href="{% url 'social:begin' 'twitter' %}">Connexion</a>

Mais cette façon de faire ne colle pas à mon besoin.

Ou alors le fait d'utiliser python-social-auth m'impose d'en passer par un pauvre lien ? et c'est python-social-auth qui finira par créé le couple token/user dans ses propres tables ?

L'un de vous a-t-il déjà, au mieux, requêter un service tiers avec python-social-auth sans passer par un lien "social:begin" si oui comment on s'y prend ? ou peut-on m'expliquer / me confirmer que python-social-auth gere tout tout seul et que je suis OBLIGE de passer par un lien ??

demandé 28-Jul-2015 par foxmask (2,862 points)

2 Réponses

0 votes
 
Meilleure réponse

en fait c'est simple comme un couple de lignes.

Dans mon cas ce que j'ai besoin c'est :

  1. un lien qui envoie l'utilisateur vers le service (requete du token)
  2. qui lui demande l'autorisation (requete de l'autorisation) à ce que mon appli accède à ses données pour peupler ledit service d'informations qu'il aura collecté
  3. une fois acceptée la requête, retour à l'url callback (celle de son application vers une page de remerciement), qui dans le dos de l'utilisateur, va vérifier l'accesstoken, lequel accesstoken sauvegarder pour une prochaine requete au service

Tout ceci se fait les doigts dans le nez avec Requests OAuthlib
Mais plutôt que de paraphraser la doc je vais juste indiquer ici comment je suis arrivé à mes fins.
Dans la doc on arrête le processus pour demander où on redirige l'utilisateur à la fin

Question de goût, je n'ai pas utilisé le OAuth1 helper mais OAuth1Session plus concis et clair pour moi

from requests_oauthlib import OAuth1Session
class MonServiceMachin(object):
    def auth(self, request):
    """
        let's auth the user to the Service
    """
    callback_url = 'http://%s%s' % (
        request.get_host(), reverse('mon_callback'))

    request_token = self.get_request_token()

    # Save the request token information for later
    request.session['oauth_token'] = request_token['oauth_token']
    request.session['oauth_token_secret'] = request_token[
        'oauth_token_secret']

    # URL to redirect user to, to authorize your app
    auth_url_str = '%s?oauth_token=%s&oauth_callback=%s'
    auth_url = auth_url_str % (self.AUTH_URL,
                   request_token['oauth_token'],
                   callback_url)

    return auth_url

    def get_request_token(self):
        """
       get a token
    """
    oauth = OAuth1Session(self.consumer_key,
                  client_secret=self.consumer_secret)
    return oauth.fetch_request_token(self.REQ_TOKEN)

    def callback(self, request):
    """
        Called from the Service when the user accept to activate it
    """

    try:
       # modele qui stock le couple oauth_token*
       us = UserService.objects.get(...)
        access_token = self.get_access_token(
        request.session['oauth_token'],
        request.session['oauth_token_secret'],
        request.GET.get('oauth_verifier', '')
        )
        us.token = access_token.get('oauth_token') + \
        '#TH#' + access_token.get('oauth_token_secret')

        # 3) and save everything
        us.save()
    except KeyError:
        return '/'

    return 'monservice/callback.html'


    def get_access_token(self, oauth_token, oauth_token_secret,
                     oauth_verifier):

    oauth = OAuth1Session(self.consumer_key,
                  client_secret=self.consumer_secret,
                  resource_owner_key=oauth_token,
                  resource_owner_secret=oauth_token_secret,
                  verifier=oauth_verifier)
    oauth_tokens = oauth.fetch_access_token(self.ACC_TOKEN)

    return oauth_tokens

Du coup pour chaque nouveau service, je n'ai que ca à faire. modulo le service qui accepte Oauth, ou module la lib qui fourni deja la gestion de l'auth.

répondu 12-Aou-2015 par foxmask (2,862 points)
+2 votes

Je ne connais pas la lib, mais à un moment de données avec ces méchanismes d'auth, tu dois avoir un lien spécifique, car tu redirige l'utilisateur chez eux, qui ensuite le redirige chez toi. Ca fait partie du processus d'authentification. Il n'y a pas moyen de faire une requête et d'avoir le token : l'utilisateur doit faire une action chez le service tier, puis la redirection de ce dernier t'envoies un token.

Même quand tu utilises une app, par exemple un client twitter, le client ouvre une URL sur twitter pour récupérer un code d'activation sur l'interface de son compte, et ensuite seulement le code est passé dans le client qui fait la requête.

En prime, pour ne rien gater, chaque API d'auth est un peu différente pour chaque service.

répondu 2-Aou-2015 par Sam (4,980 points)

tu te doutes que je sais tout ça pour avoir pu gerer quelques services comme twitter.
L'intérêt de la question c'est de savoir comment je peux utiliser la machinerie de l'authentification sans devoir me farcir tout le reste de la lib, c'est à dire entre autre, "obliger" l'utilisateur à se connecter à son app à partir de la lib.

exemple de comment ca marche :

j'ai une appliA et je ne gere pas la connexion à mon site web. Je délègue ca à un site tiers tels twitter faceboo google etc. Une fois "connecté", mon appliA a accès au token que le site tiers m'a délivré.

Comment je veux que ca marche :

j'ai une appliB qui gere les comptes des utilisateurs, et à un moment donné l'un d'eux veut ajouter ce service pour s'en servir. C'est là que je eux exploiter la lib du topic qui a déjà tout ce qu'il faut dans le code pour gerer le workflow d'authentification & autorisation. Dans le code je n'ai pas trouvé le point d'entrée pour ca, je ne vois que le cas préciser au dessus...

Ahhhh, tu veux écrire un nouveau backend en utilisant la lib ! Là ça va dépendre du type d'auth. Si c'est super custo, tu peux hériter directement de https://github.com/omab/python-social-auth/blob/master/social/backends/base.py. Sinon, tu as des trucs pour chaque use case, par exemple, c'est le protocole Oauth : https://github.com/omab/python-social-auth/blob/master/social/backends/oauth.py. Après tous les backends sont utilisés de la même façon : https://github.com/omab/python-social-auth/blob/master/social/apps/django_app/views.py

Merci @Sam pour le petit topo sur les mécanismes d'authentification ;P

...