La consommation de webservices REST, ou "API REST" est devenue incontournable. Une authentification avec OAuth 2 est souvent requise, avec ou sans action de l'utilisateur de l'application afin de s'identifier sur le site du fournisseur de l'API.
Grâce aux types httpRequete et httpRéponse ces appels en WLangage se font sans difficulté particulière, à condition de connaître le "principe" d'échange avec le serveur...
Principe :
- une première prise de contact avec l'API permet d'obtenir au minimum un token, c'est donc juste une première phase d'authentification,
- les appels suivants sont les appels réels des fonctions de l'API afin d'avoir des données. Ils se font en spécifiant dans les paramètres le token reçu au premier appel.
En pratique :
- soit c'est l'utilisateur qui va s'authentifier directement via la page fournie par le fournisseur de l'API. Dans ce cas le premier appel au webservice pour l'authentification se fera avec la fonction AuthIdentifie qui recevra les paramètres dans une variable oauth2parametres. Le token nécessaire aux appels suivants est alors reçu dans une variable AuthToken.
- soit l'authentification complète est faite par programmation. Cela permet par exemple à l'utilisateur de fournir son couple utilisateur/mot de passe dans les champs de l'application, ou un choix de paramétrage, sans avoir à passer par l'interface de connexion du fournisseur de l'API.
L'application devra alors fournir :
- pour l'authentification les identifiants ET le couple utilisateur/mot de passe, qui doivent être donnés via une requête POST avec un contenu "grant_type=password".
La réponse sera généralement un JSON contenant :
- le token,
- des informations sur la validité du token,
- et fréquemment une nouvelle URL qui sera celle à utiliser pour consommer les prochaines fonctions du webservice.
- pour les appels suivants, on donnera le token d'authentification dans une entête "Authorization = Bearer", et on utilisera la nouvelle URL obtenue à l'authentification.
Voici deux solutions pour effectuer cette authentification entièrement par programmation, sans faire appel à la page de connexion du prestataire. Quelque soit le fournisseur, c'est le même principe qui va s'appliquer. Seul le format et la structure de la réponse sera variable. C'est le plus souvent du JSON, et le plus souvent un membre de la structure aura "token" dans son nom ...
Solution 1 pour l'authentification (donc obtenir le token) : utilisation d'une unique variable httpRequete ...
httpToken_Requete est une httpRequête httpToken_Réponse est une httpRéponse
sCléClient est une chaîne sCléSecret est une chaîne sUtilisateur est une chaîne sMotPasse est une chaîne
sUtilisateur = "utilisateur@domain.net" sMotPasse = "Gg334OJn3n..." sCléClient = "Q65dQf3S2Dd..." sCléSecret = "ECF89ADFB...."
httpToken_Requete..Méthode = httpPost httpToken_Requete..URL = "https://adresse-authentification/services/oauth2/token"
httpToken_Requete..Contenu = "grant_type=password&username="+sUtilisateur+"&password="+sMotPasse+"&client_id="+sCléClient+"&client_secret="+sCléSecret
httpToken_Réponse = HTTPEnvoie(httpToken_Requete)
jToken est un JSON = httpToken_Réponse..Contenu
La variable jToken contient alors le nécessaire pour tous les appels suivants au webservice :
- jToken.instance_url : l'adresse à laquelle envoyer les appels suivants,
- jToken.access_token : le token à donner en entête.
Un exemple de réponse :
En fonction du prestataire le nom des membres dans le JSON seront différents, mais le principe est toujours le même puisqu'il s'agit d'une implémentation de OAuth2.
Solution 2 pour l'authentification (donc pour obtenir le token) : utilisation d'une variable requête, combinée avec les fonctions de création d'un formulaire HTTP ...
httpToken_Requete est une httpRequête httpToken_Réponse est une httpRéponse
sCléClient est une chaîne sCléSecret est une chaîne sUtilisateur est une chaîne sMotPasse est une chaîne
sUtilisateur = "utilisateur@domain.net" sMotPasse = "Gg334OJn3n..." sCléClient = "Q65dQf3S2Dd..." sCléSecret = "ECF89ADFB...."
httpToken_Requete..Méthode = httpPost httpToken_Requete..URL = "https://adresse-authentification/services/oauth2/token" httpToken_Requete..ContentType = typeMimeFormulaireSimple
HTTPCréeFormulaire("FORM") HTTPAjouteParamètre("FORM","grant_type","password") HTTPAjouteParamètre("FORM","username",sUtilisateur) HTTPAjouteParamètre("FORM","password",sMotPasse) HTTPAjouteParamètre("FORM","client_id",sCléClient) HTTPAjouteParamètre("FORM","client_secret",sCléSecret) httpToken_Réponse = HTTPEnvoieFormulaire("FORM",httpToken_Requete)
jToken est un JSON = httpToken_Réponse..Contenu
Dans le cas générale les deux méthodes sont équivalentes. Cette seconde méthode ajoute quelques lignes de code, mais limite les risques d'erreur de saisie en étant plus lisible que la "concaténation à rallonge". Cette seconde méthode devient par contre incontournable si la requête doit être en "multipart/form-data" (cf typeMimeFormulaireMultiPartie), c'est parfois demandé par un fournisseur d'API REST.
Appel des fonctions du webservice REST : que l'authentification soit faite avec la solution 1 ou 2, il suffit d'ajouter le token dans l'entête des appels :
httpReqAPI est un httpRequête httpRéponse est un httpRéponse J_reponse est un JSON
httpReqAPI..Méthode = httpGet httpReqAPI..URL = jToken.instance_url+"/services/data/v50.0/mafonction" httpReqAPI..ContentType = "application/json" httpReqAPI..Entête["Authorization"] = "Bearer "+jToken.access_token
httpRéponse = HTTPEnvoie(httpReqAPI) SI httpRéponse..CodeEtat <> 200 ALORS
SINON J_reponse = httpRéponse..Contenu Trace(J_reponse..FormatJSON) FIN
Bon à savoir dans ce domaine :
- attention au codage ANSI/UNICODE : les fournisseurs d'API attendent des données en ANSI dans le cas général. Le code ci-dessus sera donc immédiatement opérationnel si la configuration du projet a des chaînes ANSI en exécution :
Si l'application est déployée dans différentes langues qui utilisent des alphabets non latin, donc avec des chaînes en UNICODE, il faudra déclarer les chaînes envoyées à l'API en ANSI : sCléClient est une chaînes ANSI...
- Si le type JSON est très pratique pour accéder au contenu d'une réponse, il facilite également les appels. Voici un exemple lorsque l'authentification se fait plus simplement en "Authorization = Bearer null". Dans ce cas un simple JSON avec "userName" et "password" est attendu :
TestRequete est un restRequête Test_Réponse est un restRéponse TestRequete..URL = "https://adresse-authentification/services/authentication/login" TestRequete..Méthode = httpPost TestRequete..Entête["Accept"] = "application/json" TestRequete..Entête["Authorization"] = "Bearer null" TestRequete..Entête["Content-Type"] = "application/json"
jsAuthentification est un JSON jsAuthentification.username = "monutilisateur" jsAuthentification.password = "MkOzdTlkPAwSSE=" TestRequete..Contenu = jsAuthentification..FormatJSON
Test_Réponse = RESTEnvoie(TestRequete)
- La mise au point des échanges avec un service d'authentification peut être facilitée en analyant le contenu complet des échanges HTTP. C'est possible avec :
|