Documentation en ligne

Authentification

Usager concerné

Pour les appels concernant un usager particulier (tel que la récupération de la liste de ses formulaires en cours), l'usager est précisé en ajoutant une query string avec un paramètre email (pour trouver l'usager selon son adresse électronique) ou un paramètre NameID (pour trouver l'usager selon son NameID SAML).

Signature des requêtes

Les appels aux API doivent être signés, cela passe par une clé partagée à configurer des deux cotés de la liaison, la signature est du type HMAC; l'algorithme de hash à employer est passé en paramètre.

En ce qui concerne l'algorithme de hash, il est préconisé d'utiliser SHA-256 par respect du Référentiel Général de Sécurité (RGS).

La signature est à calculer sur la query string encodée complète, en enlevant les paramètres terminaux algo, timestamp, orig et signature. La formule de calcul de la signature est la suivante :

BASE64(HMAC-HASH(query_string+'algo=HASH&timestamp=' + timestamp + '&orig=" + orig, clé))
  • timestamp est la date dans la zone GMT au format ISO8601 en se limitant à la précision des secondes (ex : 2012-04-04T12:34:00Z),

  • orig est une chaîne précisant l'émetteur de la requête,

  • algo est une chaîne représentant l'algorithme de hachage utilisé, sont définis : sha1, sha256, sha512 pour les trois algorithmes correspondant. L'utilisation d'une valeur différente n'est pas définie.

La query string définitive est ainsi :

qs_initial&algo=algo&timestamp=ts&orig=orig&signature=signature

Configuration des clés partagées

Les clés partagées doivent être définies dans le fichier site-options.cfg, dans une section [api-secrets], par exemple :

[api-secrets]
intranet = 12345

Exemples de code de signature

Voici des exemples de code pour créer des URLs signées selon l'algorithme expliqué ci-dessus.

Python

#!/usr/bin/env python2

import base64
import hmac
import hashlib
import datetime
import urllib
import urlparse
import random

def sign_url(url, key, algo='sha256', orig=None, timestamp=None, nonce=None):
    parsed = urlparse.urlparse(url)
    new_query = sign_query(parsed.query, key, algo, orig, timestamp, nonce)
    return urlparse.urlunparse(parsed[:4] + (new_query,) + parsed[5:])

def sign_query(query, key, algo='sha256', orig=None, timestamp=None, nonce=None):
    if timestamp is None:
        timestamp = datetime.datetime.utcnow()
    timestamp = timestamp.strftime('%Y-%m-%dT%H:%M:%SZ')
    if nonce is None:
        nonce = hex(random.getrandbits(128))[2:-1]
    new_query = query
    if new_query:
        new_query += '&'
    new_query += urllib.urlencode((
        ('algo', algo),
        ('timestamp', timestamp),
        ('nonce', nonce)))
    if orig is not None:
        new_query += '&' + urllib.urlencode({'orig': orig})
    signature = base64.b64encode(sign_string(new_query, key, algo=algo))
    new_query += '&' + urllib.urlencode({'signature':signature})
    return new_query

def sign_string(s, key, algo='sha256', timedelta=30):
    digestmod = getattr(hashlib, algo)
    hash = hmac.HMAC(key, digestmod=digestmod, msg=s)
    return hash.digest()

# usage:
url = sign_url('http://www.example.net/uri/?arg=val&arg2=val2', 'user-key', orig='user')

PHP

<?php

function sign_url(string $url, string $orig, string $key) {
	$parsed_url = parse_url($url);
	$timestamp =  gmstrftime("%Y-%m-%dT%H:%M:%SZ");
	$nonce = bin2hex(random_bytes(16));
	$new_query = '';
	if (isset($parsed_url['query'])) {
		$new_query .= $parsed_url['query'] . '&';
	}
	$new_query .= http_build_query(array(
		'algo' => 'sha256',
		'timestamp' => $timestamp,
		'nonce' => $nonce,
		'orig' => $orig));
	$signature = base64_encode(hash_hmac('sha256', $new_query, $key, $raw_output = true));
	$new_query .= '&' . http_build_query(array('signature' => $signature));
	$scheme   = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
	$host     = isset($parsed_url['host']) ? $parsed_url['host'] : '';
	$port     = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
	$user     = isset($parsed_url['user']) ? $parsed_url['user'] : '';
	$pass     = isset($parsed_url['pass']) ? ':' . $parsed_url['pass']  : '';
	$pass     = ($user || $pass) ? "$pass@" : '';
	$path     = isset($parsed_url['path']) ? $parsed_url['path'] : '';
	$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
	return "$scheme$user$pass$host$port$path?$new_query$fragment";
}

# usage:
url = sign_url("http://www.example.net/uri/?arg=val&arg2=val2", "user", "user-key");

?>

Shell (bash)

#!/bin/bash

url="http://www.example.net/uri/?arg=val&arg2=val2"
orig="user"
key="user-key"

function rawurlencode() {
  local string="${1}"
  local strlen=${#string}
  local encoded=""
  local pos c o
  for ((pos=0; pos<strlen; pos++)); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  echo "${encoded}"
}

now=$(date -u +%FT%TZ);
qs="algo=sha256&timestamp=$now&orig=$orig"
sig=$(rawurlencode $(echo -n "$qs" | openssl dgst -binary -sha256 -hmac "$key" | base64))
signed="${url}?$qs&signature=$sig"
echo "$signed"

Dernière mise à jour le 26 janvier 2020 13:25 — Éditer