JWT (Json Web Token) pour utiliser avec une api google

Bonsoir,

J’en appelle à la communauté en espérant que quelqu’un ait déjà eu affaire au problème auquel je suis confronté.

Pour faire simple mon entreprise souhaite que je développe au sein de notre logiciel une passerelle pour avoir les données des pages google my business que nous gérons via l’API de google donc sans interface et qu’un rapport soit édité de manière automatisé.

Je me suis penché depuis jeudi sur la doc de google et miracle il existe bien une solution de serveur à serveur qui existe sans qu’aucune interface ne soit nécessaire.

Tout content je débute donc le process pour y arriver et je bloque … sur la première étape qui est de générer un JWT ou plus communément appelé un Json Web Token.

En fait je bloque sur la dernière étape qui consiste à générer une signature au JWT au moyen d’une clé privé que google me fournit voici mon code pour que ça soit plus parlant :

// JWT HEADER
OB FIXER($jwtHeader_o;JWT Header alg;JWT Digest RS256;JWT Header typ;“JWT”)
$jwtHeader_t:=JSON Stringify($jwtHeader_o)

$phpExecute_b:=PHP Exécuter(Dossier 4D(Dossier Resources courant)+“GMB”+Séparateur dossier+“JWT_function.php”;“base64url_encode”;$jwtHeaderEncode_t;$jwtHeader_t)

// JWT CLAIM SET
$ts_el:=ogTimestamp (Date du jour;Heure courante)
$tsPlus1Heure_el:=$ts_el+3600
OB FIXER($jwtClaimSet_o;JWT Claim iss;"xxxxxxxx@xxxxxxxxxx.iam.gserviceaccount.com";“scope”;“https://www.googleapis.com/auth/prediction”;JWT Claim aud;“https://oauth2.googleapis.com/token”;JWT Claim iat;$ts_el;JWT Claim exp;$tsPlus1Heure_el)
$jwtClaimSet_t:=JSON Stringify($jwtClaimSet_o)

$phpExecute_b:=PHP Exécuter(Dossier 4D(Dossier Resources courant)+“GMB”+Séparateur dossier+“JWT_function.php”;“base64url_encode”;$jwtClaimSetEncode_t;$jwtClaimSet_t)

// JWT SIGNATURE

$serviceAccountFileChemin_t:=Dossier 4D(Dossier Resources courant)+“GMB”+Séparateur dossier+“serviceAccountFile.json”
$serviceAccountFile_t:=Document vers texte($serviceAccountFileChemin_t;“utf-8”;Document avec CRLF)
$serviceAccountFile_o:=JSON Parse($serviceAccountFile_t)

$privateKey_t:=OB Lire($serviceAccountFile_o;“private_key”)

$sourceData_t:=$jwtHeaderEncode_t+"."+$jwtClaimSetEncode_t

CONVERTIR DEPUIS TEXTE($privateKey_t;“utf-8”;$privateKey_b)
CONVERTIR DEPUIS TEXTE($sourceData_t;“utf-8”;$sourceData_b)

$jwtSignatureEncode_t:=RSASHA256 ($sourceData_b;$privateKey_b;Crypto BASE64)

$jwtAssertionEncode_t:=$jwtHeaderEncode_t+"."+$jwtClaimSetEncode_t+"."+$jwtSignatureEncode_t

AJOUTER À TABLEAU($intituleHeader_at;“Content-Type”)
AJOUTER À TABLEAU($valueHeader_at;“application/x-www-form-urlencoded”)

$data_t:=“grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=”+$jwtAssertionEncode_t

APPELER SUR ERREUR(“gestionErreurLogiciel”)
$etat_el:=HTTP Request(HTTP méthode POST;“https://oauth2.googleapis.com/token”;$data_t;$reponse_t;$intituleHeader_at;$valueHeader_at)
APPELER SUR ERREUR("")

J’ai essayé beaucoup de chose d’abord je suis passé par les méthodes traditionnelles de 4D avec la balise ENCODER BASE64, puis j’ai essayé le plugin de miyako (https://github.com/miyako/4d-plugin-jwt/) puis un autre plugin de miyako (https://github.com/miyako/4d-plugin-common-crypto), je dois bloquer sur quelque chose de bête mais je ne vois pas quoi…

Merci par avance.

urlencoding, base64 and base64urlencoding are not the same.

I think Google switched from one to the other some time ago, but I am not sure.

in 4D code,

urlencoding looks like

<code 4D>
C_TEXT($1;$0;$escaped)

C_LONGINT($i)
C_BOOLEAN($shouldEscape)
C_BLOB($data)

For ($i;1;Length($1))
$char:=Substring($1;$i;1)
$code:=Character code($char)
$shouldEscape:=False
Case of
: ($code=45)
: ($code=46)
: ($code>47) & ($code<58)
: ($code>63) & ($code<91)
: ($code=95)
: ($code>96) & ($code<123)
: ($code=126)
Else
$shouldEscape:=True
End case
If ($shouldEscape)
CONVERT FROM TEXT($char;“utf-8”;$data)
For ($j;0;BLOB size($data)-1)
$hex:=String($data{$j};"&x")
$escaped:=$escaped+"%"+Substring($hex;Length($hex)-1)
End for
Else
$escaped:=$escaped+$char
End if
End for

$0:=$escaped
</code 4D>

base64urlencoding looks like

<code 4D>
//modified Base64 for URL

C_TEXT($1;$src;$0;$dst)

$src:=$1

C_BLOB($data)
CONVERT FROM TEXT($src;“utf-8”;$data)
BASE64 ENCODE($data;$dst)

$dst:=Replace string($dst;"+";"-";)
$dst:=Replace string($dst;"/";"_";
)
$dst:=Replace string($dst;"=";"";*)

$0:=$dst
</code 4D>

I execute already this method (base64urlencoding) with PHP function, but the problem is with signature JWT that Google doesn’t recognize… I don’t know how to build it correctly :smiley:

Bonjour,

Ci-joint un composant qui implémente JWT avec du code 4D natif (sans php).

J’ai des “test vectors” à l’intérieur.

En v14, mais convertible sans problème dans une version plus récente (utilisera le SHA 256 native à partir de 4D v17).

https://forums.4d.com/4DBB_Main/x_User/4275/files/33455439.zip

HTH

Merci bien je vais essayer avec votre composant :).

Bon je viens d’essayer et je n’ai pas de meilleur résultat, google me renvoi toujours l’erreur : {\n “error”: “invalid_request”,\n “error_description”: “Missing required parameter: assertion”\n}

Donc soit ma signature n’est pas bonne, soit je construis mal ma requête http pourtant je pense qu’elle est correctement formatée…

Bonjour,

Le problème est probablement avec le “payload” et pas avec JWT…

here is a functional example with the accounts removed

https://forums.4d.com/4DBB_Main/x_User/298210/files/33463911.zip

Realy, realy, realy thanks you Keisuke.

Since 3 days I search and test and test but not success… until your help :smiley:

This request is very picky !