PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2025 → API S3 authentification
API S3 authentification
Débuté par EGuillemotETIB, 08 jan. 2025 12:06 - 5 réponses
Posté le 08 janvier 2025 - 12:06
Bonjour à tous,

Je souhaite utiliser un service de stockage d'objet tel que OVH Object Storage S3.
En essayant de récupérer un fichier stocké dans un conteneur :
- l'API REST renvoie une erreur 403 SignatureDoesNotMatch
- aucun problème avec awscli (ce qui m'a permis de vérifier la configuration et de comparer les signatures qui semblent identiques)

Voilà le code utilisé :
LF est une chaîne = Caract(10)
dateTime est DateHeure = DateHeureLocaleVersUTC(DateHeureSys())
amzdate est chaîne = DateHeureVersChaîne(dateTime, "AAAAMMJJTHHmmSSZ")
dateStamp est chaîne = DateVersChaîne(dDateHeure, "AAAAMMJJ")
host est chaîne = "https://s3.gra.io.cloud.ovh.net"

signedHeaders est chaîne = "host;x-amz-content-sha256;x-amz-date"
payloadHash est chaîne = Minuscule(BufferVersHexa(HashChaîne(HA_SHA_256, ChaîneVersUTF8("")), SansRegroupement))
credentialScope est chaîne = dateStamp + "/gra/s3/aws4_request"
canonicalHeader est chaîne = "host:" + host + LF + "x-amz-content-sha256:" + payloadHash + LF + "x-amz-date:" + amzdate + LF

canonicalRequest est chaîne = "GET" + LF + "/bucket/file" + LF + "" + LF + canonicalHeader + LF + signedHeaders + LF + payloadHash

stringToSign est chaîne = "AWS4-HMAC-SHA256" + LF + amzdate + LF + credentialScope + LF + Minuscule(BufferVersHexa(HashChaîne(HA_SHA_256, ChaîneVersUTF8(canonicalRequest)), SansRegroupement))

signingKeyDate est Buffer = HashChaîne(HA_HMAC_SHA_256, dateStamp, ChaîneVersUTF8("AWS4" + secretKey))
signingKeyRegion est Buffer = HashChaîne(HA_HMAC_SHA_256, "gra", signingKeyDate)
signingKeyService est Buffer = HashChaîne(HA_HMAC_SHA_256, "s3", signingKeyRegion)
signingKey est Buffer = HashChaîne(HA_HMAC_SHA_256, "aws4_request", signingKeyService)

signature est chaîne = Minuscule(BufferVersHexa(HashChaîne(HA_HMAC_SHA_256, stringToSign, signingKey), SansRegroupement))

requeteApi est httpRequête
reponseApi est httpRéponse
requeteApi.URL = host + "/bucket/file"
requeteApi.Méthode = httpGet
requeteApi.Entête["Host"] = host
requeteApi.Entête["x-amz-date"] = amzdate
requeteApi.Entête["x-amz-content-sha256"] = payloadHash
requeteApi.Entête["Authorization"] = "AWS4-HMAC-SHA256" + " Credential=" + accessKey + "/" + credentialScope + ",SignedHeaders=" + signedHeaders + ",Signature=" + signature

reponseApi = HTTPEnvoie(requeteApi)


Merci d'avance
Membre enregistré
187 messages
Posté le 08 janvier 2025 - 16:01
Bonjour

Je vois votre problème, vous utiliser un Web Service dans votre code alors le résultat envoie des erreurs sur la signature, j'ai deux solutions pour vous, vous pouvez choisir

1. Soit vous devrez saisir manuellement la signature pour des essais de test, une chaine mais pas un buffer par exemple, ensuite vous récupérer dans une variable d'une méthode d'une classe, soit statique la valeur
2. Soit vous devrez ne pas ajouter la signature, mais pour des raisons de sécurité, il faut toujours ajouter un signature

Pour le cas 1, vous pouvez utiliser cette programme
// EDD (01/25) : Créer une nouvelle classe ClSignature
ClSignature est une Classe
FIN

// EDD (01/25) : Créer une nouvelle méthode Valeur() dans la classe ClSignature
PROCÉDURE Valeur()
RENVOYER "XXX-XXX-XXX-XXX" // EDD (01/25) : Vous devrez utiliser des lettres et des chiffres, cette valeur est pareil dans le Web Service et dans le projet aussi

// EDD (01/25) : Dans votre programme ci dessous
requeteApi.Entête["Authorization"] = "AWS4-HMAC-SHA256" + " Credential=" + accessKey + "/" + credentialScope + ",SignedHeaders=" + signedHeaders + ",Signature=" + signature

// EDD (01/25) : Remplacer par le suivant
cSignature is ClSignature
requeteApi.Entête["Authorization"] = "AWS4-HMAC-SHA256" + " Credential=" + accessKey + "/" + credentialScope + ",SignedHeaders=" + signedHeaders + ",Signature=" + cSignature:Valeur()

NB : Je vois votre programme très bien structuré

Cordialement
Mr.RATSIMANDRESY
Niry Aina Eddy
Membre enregistré
4 messages
Posté le 09 janvier 2025 - 12:17
Bonjour,

Merci pour votre réponse, je doit avouer cependant que je ne comprend pas trop où vous voulez en venir.

Le projet ne contient que ce code qui appel l'API.
Saisir manuellement la signature me parait compliquer au vu des hash de l'heure:minute:seconde de la requête.
Je ne comprends pas comment déplacer valeur de la signature dans une classe résoudrait son calcul.

Merci de m'éclairer, toute solution est bonne à explorer :)
Membre enregistré
4 messages
Posté le 06 février 2025 - 10:12
Comme je repassais par ici, si ça intéresse quelqu'un, j'utilisais une requête path-style au lieu de virtual hosted–style.
Posté le 02 septembre 2025 - 11:42
EGtib a écrit :
> Comme je repassais par ici, si ça intéresse quelqu'un, j'utilisais une requête path-style au lieu de virtual hosted–style.
Bonjour,

Avez-vous finalement réussi à vous connecter et à utiliser l'API S3 d'OVH ?

Je dois l'utiliser sur un projet et je ne trouve pas trop comment cela fonctionne.

Le but serait de s'authentifier et de pouvoir envoyer des fichiers depuis un soft qui se lancerait automatiquement (donc pas d'interface).

Merci d'avance.
Membre enregistré
4 messages
Posté le 02 septembre 2025 - 12:37
Bonjour,

Oui c'est fonctionnel et en place.

Globalement, chaque requête à l'API doit être authentifiée par une signature calculée depuis la date, le serveur de stockage, le contenu, etc…
(quelques point d'attentions : méthodes de hash, LF et pas CRLF, les header à inclure, le style de requête (path ou virtual-hosted), etc…)

Si vous êtes à l'aise pour lire une documentation anglaise, j'ai utilisé la doc d'Amazon pour mon implémentation : https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
Il y a aussi la LST n°140 qui montre un exemple avec l'utilisation d'un composant interne

J'espère que ça vous permettra d'avancer


PS : n'hésitez pas à utiliser d'autres outils comme aws-cli ou Postman (qui dispose du calcul intégré de la signature) pour vérifier les accès en dehors de votre code