Authentification par user token pour utilisation d'API

Tags: #<Tag:0x00007f1001a60528>
Authentification par user token pour utilisation d'API
0

Bonjour,

Je cherche à utliser les user tokens plutôt qu’un basic authentication pour utiliser mon API. J’ai suivi cette documentation https://www.simplicite.io/resources/documentation/02-integration/services-auth.md

J’ai pu récupérer mon user token mais quand je l’utilise comme décrit dans la partie “Use access token for service calls” pour faire un GET, j’ai des problèmes.

  • Avec le header X-Simplicite-Authorization: Bearer => j’ai l’erreur “Simplicite authentication error: No login”
  • En paramètre dans la requête x_simplicite_authorization= avec le header Authorization: Bearer => j’ai l’erreur “No login”

NB : J’ai mis le paramètre système USE_USERTOKEN à yes. De plus, l’utilisateur pour lequel j’ai généré le token fait partie d’un group qui a pour grant une fonction read sur mon service.

Merci d’avance.

Indiquez moi:

  • La version, le patchlevel et la révision de votre instance Simplicité (vous pouvez voir cette information en appelant le endpoint heath check /health), merci de systématiquement indiquer ces infos lors de vos demandes de support.
  • Les différents appels que vous effectuez (ex: les commandes curl exactes)

Je viens de faire un test sur une instance cloud 4.0 à jour sur la branche release:

> curl -ks -u <monuser>:<monpassword> https://<moninstance>.simplicite.io/health
[Platform]
Status=OK
Version=4.0.P23
BuiltOn=2019-06-04 15:53 (revision a8b660f5b43b7a477b5d8f394db792bec6dd519b)
(...)

Mon test:

  1. je récupère un token API:
> curl -ks -u <monuser>:<monpassword> https://<moninstance>.simplicite.io/api/login?_output=token
{"authtoken":"FafvzAhCPANk284FCDzkbV2OoZ0GLtguvVizbtQNxpBbFKLvvR","authtokenexpiry":1559824974000}
  1. puis j’utilise ce token, d’abord avec le header standard Authorization:
> curl -ks -H "Authorization: Bearer FafvzAhCPANk284FCDzkbV2OoZ0GLtguvVizbtQNxpBbFKLvvR" https://<moninstance>.simplicite.io/api/rest/User
[{"row_id":"1","usr_login":"designer","usr_lang":"ENU","usr_image_id":"381",(...)]
  1. puis avec le header spécifique X-Simplicite-Authorization:
>  curl -ks -H "X-Simplicite-Authorization: Bearer FafvzAhCPANk284FCDzkbV2OoZ0GLtguvVizbtQNxpBbFKLvvR" https://<moninstance>.simplicite.io/api/rest/User
[{"row_id":"1","usr_login":"designer","usr_lang":"ENU","usr_image_id":"381",(...)]
  1. enfin avec le token en parametre d’URL _x_simplicite_authorization_:
> curl -ks https://<moninstance>.simplicite.io/api/rest/User?_x_simplicite_authorization_=R4ePWxjFthcf9xksbV9jCzi2uEpmWGdmBmHY4FFyOy0u67ne9h
[{"row_id":"1","usr_login":"designer","usr_lang":"ENU","usr_image_id":"381",(...)]

Bref, je n’ai pas de pb (en tout cas tant que le token n’est pas expiré).

Pouvez vous m’expliquer le contexte de vos appels API ?

Je pose la question car vous trouverez des exemples d’utilisation des services REST sur notre GitHub (https://github.com/simplicitesoftware), soit en accès direct, soit via des librairies helper qui gèrent le token de manière transparente. En général en s’inspirant de ces exemples et/ou en utilisant les librairies helper on a pas de pb.

Je vous suggère aussi de regarder ce que fait la page de test des API disponible sur /api.

Bonjour David,

Merci pour ta réponse et pardon pour ma réponse tardive, j’étais en congés.

Version et release, je suis en :

Version=4.0.P23c
BuiltOn=2019-05-14 15:24 (revision 8a480950b3895a9516a00f4c5344a3cfed3806d1)

J’ai récupéré le user token en me connectant via navigateur à https://[base path]/api/login

J’ai ensuite cherché à utilisé ce token dans un GET dans Postman :

https://[base path]/sites/v1/sites (c’est un uri mapping)

  • Avec le header Authorization: Bearer [user token] => j’ai l’erreur “No login”
  • Avec le header X-Simplicite-Authorization: Bearer [user token] => j’ai l’erreur “Simplicite authentication error: No login”
  • En paramètre dans la requête https://[base path]/sites/v1/sites?x_simplicite_authorization=[user token] => j’ai l’erreur “No login”

J’arrive à faire utiliser les API avec une Basic Authent mais des clients doivent passer par Apigee et la Basic Authent n’est donc pas possible sinon elle s’appliquerait à Apigee et pas à Simplicité. Je cherche donc à pouvoir fournir le user token avec un header spéficique à Simplicité (X-Simplicite-Authorization serait bien) pour pouvoir à la fois m’authentifier à Apigee puis à Simplicité une fois Apigee passé.

Déjà ton socle n’est plus à jour, et tu es calé sur la branche prerelease (image Docker beta) or la P23 a été releasée depuis mi mai (cf. Simplicite 4.0 release P23) et plusieurs fois amendée de corrections critiques.

Bref tu devrais basculer rapidement sur la branche release (image Docker lastest). En effet on va bientôt commencer à pousser la P24 sur la branche prerelease, et les premiers temps c’est toujours un peu chaotique, je ne pense pas que tu veuille subir ça.

Pour mémoire, ne pas utiliser la branche release était une situation transitoire pour vous qui n’a plus de raison d’être puisqu’il y a désormais ce dont vous avez besoin sur la branche release.

Sinon, la syntaxe GET pour être “browser-navbar-friendly” c’est ?_x_simplicite_authorization_=<montoken> pas ?x_simplicite_authorization=<montoken> (il manque des _)

Pour les autres types de calls HTTP plus sérieux (i.e. je veux dire pas juste de la consultation humaine via une URL tapée dans la navbar d’un browser web), il faut passer le token nominalement i.e. via un header HTTP:

  • soit le standard Authorization (peut poser pb dans des pages web qui font des calls Ajax)
  • soit le custom X-Simplicite-Authorization

Dans les 2 cas il faut mettre Bearer <montoken> comme valeur.

Cf les exemples curl de mon post précédent. Ce qui marche en curl marche avec Postman (il faut juste mettre les bonnes chose au bon endroit).

Je ne pense pas que le fait d’être en URI mapping change grand chose, je vais vérifier.

Et pour rappel un token a une durée de validité.

J’ai testé le fait d’être en URI mapping ne change rien:

> curl -ks -u <username>:<password> https://sitesdev.renault.simplicite.io/api/login?_output=token
{"authtoken":"2hdkxO7wMgXd5JRlWY8i2e7pQZehJmTSlTCf9BfmSYN8Ibqgas","authtokenexpiry":1561041064000}

> curl -ks -H "X-Simplicite-Authorization: Bearer 2hdkxO7wMgXd5JRlWY8i2e7pQZehJmTSlTCf9BfmSYN8Ibqgas" https://sitesdev.renault.simplicite.io/sites/v1/sites
{"sites":[{"identifier":"SIT41593203","endDate":"","cityPostalCode":"76530","description":"","cityId":"88","countryId":"81","cityName":"GRAND COURONNE","activeStatus":"ACTIVE","countryCode":"FR","name":"CKD GD COUGRAND","countryName":"France","row_id":"37","effectiveDate":"2019-03-13"},(...)]}

PS:

J’ai ensuite fait le test d’invalider le token ci-dessus:

> curl -ks -H "X-Simplicite-Authorization: Bearer 2hdkxO7wMgXd5JRlWY8i2e7pQZehJmTSlTCf9BfmSYN8Ibqgas" https://sitesdev.renault.simplicite.io/api/logout

Après, si je le réutilise, j’ai bien un message qui dit que le token n’est pas valide (je veux dire pas un message qui dit “pas de login”):

> curl -ks -H "X-Simplicite-Authorization: Bearer 2hdkxO7wMgXd5JRlWY8i2e7pQZehJmTSlTCf9BfmSYN8Ibqgas" https://sitesdev.renault.simplicite.io/sites/v1/sites
Simplicite authentication error: Invalid token

Bref, si tu as un message qui parle du login alors que tu pense passer un token c’est que tu fais un truc de travers.

Au passage tu auras noté le changement de format de la réponse GET en recherche. C’est suite aux évolutions récentes du composant de mapping demandées par @bmo suite à des “non conformités” aux normes d’API Renault qui n’avaient bizarrement pas été détectées jusqu’ici.

Ces évolutions ont été backportées sur la release P23 pour ne pas vous obliger à attendre la P24 pour en bénéficier. Je dis cela pour te motiver encore plus à te mettre à jour ;-)

Je viens de faire la mise à jour en release :

Version=4.0.P23
BuiltOn=2019-06-19 13:21 (revision a10e298efb83c69c5a72a31e70861463d73438fa)

J’ai bien fait mes requêtes avec le Bearer <user token> comme tu décris mais j’ai toujours le No login. J’ai fait un test plus simple : générer le token puis l’utiliser dans l’interface de test d’API <base path>/api et j’ai là aussi un No login que ça soit sur /api/rest ou sur mon service sites/v1/sites. C.f. ci-dessous :

Alors qu’en mettant l’utilisateur et mot de passe utilisés pour générer ce token (sur <base path>/api/login directement en basic authent, ça marche bien.

Edit : la log système de l’erreur No login => 2019-06-19 17:15:05,458 ERROR [com.simplicite.webapp.servlets.api.RESTServlet] SIMPLICITE|http://a76646e6fac4:8080||ERROR|system|com.simplicite.webapp.servlets.api.RESTServlet|getWebServicesFactory||Event: Simplicite authentication error: No login

Je n’ai jamais utilisé la page de test avec des URI mappées…

Franchement teste avec curl c’est quand même la manière la plus simple, basique, claire et la plus fiable pour faire des test d’appels HTTP, surtout avec le flag -v

Quand ça marche avec curl ça marche avec n’importe quel autre outil qui fait des requêtes HTTP (moyennant de lui faire faire la même chose que curl)

Perso j’utilise aussi Postman avec lequel je n’ai jamais eu de pb pour appeler les APIs Simplicité.

On parle d’appels sur les instances déployées sur notre serveur cloud ou sur une instance déployée chez vous ?

Si ça se trouve il y a un truc quelque part sur votre réseau qui filtre/modifie les headers HTTP et peut être pas de la même manière en fonction de l’URL, va savoir…

Peux tu commencer par tester exactement ce que je fais dans mes posts à savoir sur https://sitesdev.simplicite.io. Si moi j’y arrive et pas toi c’est que soit tu fais pas exactement ce que je fais, soit qu’il y a un pb de tuyauterie subtil sur votre réseau.

Je suis sous Windows donc je ne peux (à ma connaissance) pas faire de CURL, les GET de base je les faisais avec Postman.

Ces tentatives qui finissent en No login sont sur nos instances déployées sur AWS. Je viens de tester sur l’instance sitesdev sur votre serveur cloud et je n’y ai pas de problème de No login. Est-ce qu’à ta connaissance il peut y avoir une configuration qui ait mal été déployée ou selon toi ça vient du réseau ?

https://curl.haxx.se/windows/

OK donc ça marche sur notre serveur et pas sur vos instances, donc c’est pas un pb Simplicité mais donc plutôt un pb de tuyauterie (pour investiguer un pb il faut éliminer les causes une par une, sinon on peut chercher longtemps…)

Chez nous il n’y a rien de phénoménalement compliqué:

  • niveauTomcat on déploie exactement la même chose que ce que vous déployez via nos images Docker (à moins que vous ne fassiez des images “sur mesure” subtiles auquel cas il faut me dire ce que vous faites)
  • en frontal on a un reverse proxy NGINX avec la config suivante:
server {
    listen 80;
    server_name sitesdev.renault.simplicite.io;
    location / {
        return 301 https://sitesdev.renault.simplicite.io$request_uri;
    }
}
server {
    listen 443 ssl;
    server_name sitesdev.renault.simplicite.io;
    ssl_certificate /etc/ssl/renault.simplicite.io.crt;
    ssl_certificate_key /etc/ssl/renault.simplicite.io.key;
    access_log /var/log/nginx/sitesdev.renault.simplicite.io.log main;
    location / {
        if ($request_method = 'OPTIONS') {
            add_header Access-Control-Allow-Origin $http_origin;
            add_header Access-Control-Allow-Credentials true;
            add_header Access-Control-Allow-Headers Content-Type,Authorization,X-Requested-With,X-HTTP-Method-Override,X-Simplicite-Authorization;
            add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,HEAD,OPTIONS;
            add_header Access-Control-Max-Age 1728000;
            add_header Content-Type text/plain;
            add_header Content-Length 0;
            return 204;
        }
        if ($request_method = 'GET') {
            add_header Access-Control-Allow-Origin $http_origin always;
            add_header Access-Control-Allow-Credentials true always;
            add_header Access-Control-Expose-Headers X-Simplicite-SessionID;
        }
        if ($request_method = 'POST') {
            add_header Access-Control-Allow-Origin $http_origin always;
            add_header Access-Control-Allow-Credentials true always;
            add_header Access-Control-Expose-Headers X-Simplicite-SessionID;
        }
        proxy_redirect off;
        proxy_buffering off;
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_pass http://localhost:10283;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Comme tu le vois c’est lui qui gère le CORS, mais quand on fait des appels hors du contexte d’un browser (typiquement via curl ou des outils genre Postman) ou sur la même URL c’est sans objet.

Fais tes requêtes curl avec -v (et sans le -s) ça sera plus verbeux et tu verras peut être mieux ce qu’il se passe.

Toujours pour éliminer les cause potentielles j’ai viré les clauses NGINX relatives aux CORS, ça marche toujours parfaitement avec curl et Postman:

Voilà la config NGINX de cette instance mise à jour:

server {
    listen 80;
    server_name sitesdev.renault.simplicite.io;
    location / {
        return 301 https://sitesdev.renault.simplicite.io$request_uri;
    }
}
server {
    listen 443 ssl;
    server_name sitesdev.renault.simplicite.io;
    ssl_certificate /etc/ssl/renault.simplicite.io.crt;
    ssl_certificate_key /etc/ssl/renault.simplicite.io.key;
    access_log /var/log/nginx/sitesdev.renault.simplicite.io.log main;
    location / {
        proxy_redirect off;
        proxy_buffering off;
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_pass http://localhost:10283;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Là pour le coup on peut pas vraiment faire plus simple.