wcs/help/fr/api-auth.page

236 lines
7.0 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<page xmlns="http://projectmallard.org/1.0/"
type="topic" id="api-auth" xml:lang="fr">
<info>
<link type="guide" xref="index#api" />
<revision docversion="0.1" date="2013-01-04" status="draft"/>
<revision docversion="0.2" date="2015-12-18" status="draft"/>
<credit type="author">
<name>Frédéric Péters</name>
<email>fpeters@entrouvert.com</email>
</credit>
<desc>Clé dutilisation, utilisateurs, sessions, signatures, etc.</desc>
</info>
<title>Authentification</title>
<section>
<title>Usager concerné</title>
<p>
Pour les appels concernant un usager particulier (tel que la récupération de la
liste de ses formulaires en cours), lusager est précisé en ajoutant une query
string avec un paramètre <code>email</code> (pour trouver lusager selon son
adresse électronique) ou un paramètre <code>NameID</code> (pour trouver
lusager selon son NameID SAML).
</p>
</section>
<section id="req-security-shared-secret">
<title>Signature des requêtes</title>
<p>
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;
lalgorithme de hash à employer est passé en paramètre.
</p>
<note><p>En ce qui concerne lalgorithme de hash, il est préconisé dutiliser
SHA-256 par respect du <link
href="http://references.modernisation.gouv.fr/securite">Référentiel Général
de Sécurité (RGS)</link>.</p></note>
<p>
La signature est à calculer sur la query string encodée complète, en
enlevant les paramètres terminaux <code>algo</code>, <code>timestamp</code>,
<code>nonce</code>, <code>orig</code> et <code>signature</code> sils sont
présents.</p>
<p>La formule de calcul de la signature est la suivante :</p>
<code>
BASE64(HMAC-HASH(query_string+'algo=HASH&amp;timestamp=' + timestamp + '&amp;nonce=' + nonce '&amp;orig=" + orig, clé))
</code>
<list>
<item><p><code>timestamp</code> est la date dans la zone GMT au format ISO8601
en se limitant à la précision des secondes (ex : 2012-04-04T12:34:00Z),
</p></item>
<item><p><code>nonce</code> est un aléa, typiquement la réprésentation hexa
dun nombre pseudo-aléatoire de 128 bits,</p></item>
<item><p><code>orig</code> est une chaîne précisant lémetteur de la
requête,</p></item>
<item><p>algo est une chaîne représentant lalgorithme de hachage utilisé, sont
définis : sha1, sha256, sha512 pour les trois algorithmes correspondant.
Lutilisation dune valeur différente nest pas définie. Lalgorithme sha256
est préconisé.</p></item>
</list>
<p>
La query string définitive est ainsi :
</p>
<code>
<var>qs_initial</var>&amp;algo=<var>algo</var>&amp;timestamp=<var>timestamp</var>&amp;nonce=<var>nonce</var>&amp;orig=<var>orig</var>&amp;signature=<var>signature</var>
</code>
</section>
<section>
<title>Configuration des clés partagées</title>
<p>
Les clés partagées doivent être définies dans le fichier
<code>site-options.cfg</code>, dans une section <code>[api-secrets]</code>, par
exemple :
</p>
<code>
[api-secrets]
intranet = 12345
</code>
</section>
<section>
<title>Exemples de code de signature</title>
<p>
Voici des exemples de code pour créer des URLs signées selon lalgorithme
expliqué ci-dessus.
</p>
<listing>
<title>Python</title>
<code mime="text/x-python">
#! /usr/bin/env python3
import base64
import datetime
import hashlib
import hmac
import random
import urllib.parse
def sign_url(url, key, algo='sha256', orig=None, timestamp=None, nonce=None):
parsed = urllib.parse.urlparse(url)
new_query = sign_query(parsed.query, key, algo, orig, timestamp, nonce)
return urllib.parse.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:].rstrip('L')
new_query = query
if new_query:
new_query += '&amp;'
new_query += urllib.parse.urlencode((('algo', algo), ('timestamp', timestamp), ('nonce', nonce)))
if orig is not None:
new_query += '&amp;' + urllib.parse.urlencode({'orig': orig})
signature = base64.b64encode(sign_string(new_query, key, algo=algo))
new_query += '&amp;' + urllib.parse.urlencode({'signature': signature})
return new_query
def sign_string(s, key, algo='sha256', timedelta=30):
if not isinstance(key, bytes):
key = key.encode('utf-8')
if not isinstance(s, bytes):
s = s.encode('utf-8')
digestmod = getattr(hashlib, algo)
hash = hmac.HMAC(key, digestmod=digestmod, msg=s)
return hash.digest()
# usage:
url = sign_url('https://www.example.net/uri/?arg=val&amp;arg2=val2', 'user-key', orig='user')
</code>
</listing>
<listing>
<title>PHP</title>
<code mime="application/x-php">
&lt;?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'] . '&amp;';
}
$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 .= '&amp;' . 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&amp;arg2=val2", "user", "user-key");
?&gt;
</code>
</listing>
<listing>
<title>Shell (bash)</title>
<code mime="application/x-shellscript">
#!/bin/bash
url="http://www.example.net/uri/?arg=val&amp;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&lt;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);
nonce=$(od -N16 -txL /dev/urandom | cut -c8- | tr -d " ")
qs="algo=sha256&amp;timestamp=$now&amp;nonce=$nonce&amp;orig=$orig"
sig=$(rawurlencode $(echo -n "$qs" | openssl dgst -binary -sha256 -hmac "$key" | base64))
signed="${url}?$qs&amp;signature=$sig"
echo "$signed"
</code>
</listing>
</section>
</page>