Méthode GET/.well-known /did.json
Servir le document d'identité décentralisée d'une marque sur son propre nom de domaine, en mode délégué. Point d'entrée public, résolu d'après le nom d'hôte appelé.
Sur cette page
Vous récupérez le document d'identité décentralisée d'une marque, publié sous le nom de domaine de cette marque. Ce document liste les clefs publiques avec lesquelles la marque signe ses passeports numériques de produit. En quittant cette page, vous saurez appeler cette adresse, lire chaque champ du document, et distinguer un domaine qui n'est pas encore reconnu d'un domaine reconnu pour lequel aucune marque n'a été déclarée.
Adresse complète, avec un domaine d'exemple :
GET https://id.exemple-sas.example/.well-known/did.jsonCe point d'entrée ne se lit pas comme les autres. Le chemin est toujours le même
pour tout le monde. C'est le nom d'hôte appelé qui désigne la marque. Le
serveur lit l'en-tête Host de votre requête, cherche la marque qui a déclaré
ce nom de domaine en mode délégué, et sert le document de cette marque.
Le même point d'entrée répond aussi sous le préfixe /v1, à
https://id.exemple-sas.example/v1/.well-known/did.json. Les deux adresses
appellent le même code. Aucun résolveur did:web n'utilise cette seconde forme :
la spécification impose le chemin /.well-known/did.json à la racine du
domaine. Appelez la forme sans préfixe.
#Autorisation
Aucune, point d'entrée public. Vous n'envoyez ni clef d'API, ni session, ni
en-tête d'origine. La réponse est la même pour tout le monde. C'est ce qui
permet à un vérificateur tiers de contrôler la signature d'un passeport avec une
bibliothèque did:web standard, sans compte chez nous.
#Plafond d'appels
Aucun plafond propre à ce point d'entrée. Ce chemin relève du compteur général de l'API, compté par adresse réseau appelante sur une tranche de 60 secondes.
Ce compteur de repli est commun à tous les chemins qui n'ont pas de plafond
propre. Les appels que vous adressez à l'un d'eux entament donc le budget des
autres. Le préfixe /v1 ne crée pas un second budget.
Chaque réponse porte les en-têtes X-RateLimit-Limit, X-RateLimit-Remaining
et X-RateLimit-Reset. Lisez X-RateLimit-Remaining pour savoir combien
d'appels il vous reste dans la fenêtre en cours. X-RateLimit-Reset porte
l'instant de bascule vers la fenêtre suivante, en secondes depuis le
1er janvier 1970.
Prévoyez le code 429 dans votre client et respectez l'en-tête Retry-After
qu'il porte. La valeur du compteur général peut changer sans préavis : réglez
votre cadence sur les en-têtes de vos réponses, et n'inscrivez aucun nombre en
dur dans votre code.
#Paramètres de chemin et de requête
Ce point d'entrée n'a aucun paramètre de chemin et aucun paramètre de requête. Le chemin est fixe et identique pour toutes les marques.
#En-têtes
| Nom | Type | Obligatoire | Description |
|---|---|---|---|
Host | string | oui | Le nom d'hôte qui désigne la marque. C'est le seul élément de la requête que le serveur lit pour choisir la réponse. Votre client HTTP le remplit automatiquement à partir de l'adresse que vous appelez. |
Le serveur ramène ce nom d'hôte en minuscules et en retire le numéro de port
avant de chercher la marque. ID.Exemple-SAS.example et
id.exemple-sas.example:443 désignent donc la même marque.
Aucun autre en-tête n'est requis.
#Corps de la requête
Aucun. Cette requête n'a pas de corps.
#Requête d'exemple
Document d'identité de la marque fictive Exemple SAS, publié sur son domaine
délégué id.exemple-sas.example.
curl -i https://id.exemple-sas.example/.well-known/did.jsonconst reponse = await fetch(
"https://id.exemple-sas.example/.well-known/did.json",
);
if (reponse.status === 404) {
console.log("Aucune marque n'est publiée sous ce nom de domaine.");
} else if (reponse.ok) {
const document = await reponse.json();
console.log(document.id);
for (const methode of document.verificationMethod) {
console.log(methode.id, methode.publicKeyJwk.crv);
}
console.log(document.assertionMethod);
} else {
console.log(reponse.status, await reponse.json());
}import requests
response = requests.get(
"https://id.exemple-sas.example/.well-known/did.json",
timeout=30,
)
if response.status_code == 404:
print("Aucune marque n'est publiée sous ce nom de domaine.")
elif response.ok:
document = response.json()
print(document["id"])
for methode in document["verificationMethod"]:
print(methode["id"], methode["publicKeyJwk"]["crv"])
print(document["assertionMethod"])
else:
print(response.status_code, response.json())#Réponse d'exemple
Code HTTP 200OK
Code HTTP 200. Une marque qui a fait tourner sa clef une fois publie deux
méthodes de vérification, l'ancienne et la nouvelle.
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/jws-2020/v1"
],
"id": "did:web:id.exemple-sas.example",
"verificationMethod": [
{
"id": "did:web:id.exemple-sas.example#key-1",
"type": "JsonWebKey2020",
"controller": "did:web:id.exemple-sas.example",
"publicKeyJwk": {
"kty": "EC",
"crv": "P-256",
"x": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"y": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
}
},
{
"id": "did:web:id.exemple-sas.example#key-2",
"type": "JsonWebKey2020",
"controller": "did:web:id.exemple-sas.example",
"publicKeyJwk": {
"kty": "EC",
"crv": "P-256",
"x": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC",
"y": "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
}
}
],
"assertionMethod": [
"did:web:id.exemple-sas.example#key-1",
"did:web:id.exemple-sas.example#key-2"
],
"authentication": [
"did:web:id.exemple-sas.example#key-1",
"did:web:id.exemple-sas.example#key-2"
]
}La réponse compte cinq champs et rien d'autre.
| Champ | Type | Description |
|---|---|---|
@context | string[] | Les deux vocabulaires qui donnent leur sens aux autres champs. Toujours https://www.w3.org/ns/did/v1 puis https://w3id.org/security/suites/jws-2020/v1, dans cet ordre. |
id | string | L'identifiant décentralisé de la marque, de la forme did:web: suivi du nom de domaine appelé. C'est la valeur que porte le champ issuer des passeports signés par cette marque. |
verificationMethod | object[] | La liste des clefs publiques de la marque. Une entrée par clef. Voir le tableau ci-dessous. |
assertionMethod | string[] | Les identifiants des clefs autorisées à signer un passeport, dans le même ordre que verificationMethod. |
authentication | string[] | La même liste d'identifiants que assertionMethod. |
Chaque entrée de verificationMethod porte quatre champs.
| Champ | Type | Description |
|---|---|---|
id | string | L'identifiant de la clef, de la forme <identifiant de la marque>#key-<numéro de version>. C'est la valeur que porte l'en-tête kid d'un passeport signé, et c'est elle qui vous dit quelle clef employer. |
type | string | Toujours JsonWebKey2020. |
controller | string | L'identifiant décentralisé de la marque. Même valeur que le champ id du document. |
publicKeyJwk | object | La clef publique au format JSON Web Key. Une clef sur courbe elliptique NIST P-256 : kty vaut EC, crv vaut P-256, x et y sont les deux coordonnées du point public, encodées en base64url. |
La réponse porte aussi ces en-têtes.
| En-tête | Contenu |
|---|---|
Content-Type | application/json. |
Cache-Control | no-store, max-age=0. La réponse ne doit être conservée dans aucun cache intermédiaire. |
X-Request-Id | L'identifiant de votre appel chez nous. Donnez cette valeur au support quand vous signalez une réponse inattendue. |
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset | Votre budget d'appels, voir la section Plafond d'appels. |
#Ce que contient la liste des clefs
Les clefs sont rendues de la plus ancienne version à la plus récente, par numéro de version croissant.
Une clef retirée du service reste dans le document tant qu'elle n'a pas été
révoquée. C'est voulu : un passeport signé sous une ancienne version continue de
se vérifier après une rotation. Prenez la clef dont l'identifiant correspond à
l'en-tête kid du passeport que vous vérifiez, jamais la dernière de la liste.
Une clef révoquée disparaît du document. Les signatures produites avec elle cessent alors de se vérifier, et c'est le résultat attendu.
Une marque qui n'a encore aucune clef reçoit un document valide dont
verificationMethod, assertionMethod et authentication sont des listes
vides. Prévoyez ce cas dans votre code.
#Faire pointer votre domaine
Trois façons d'héberger le document existent, et une seule passe par cette adresse chez nous.
| Mode | Où vit le document | Adresse résolue |
|---|---|---|
| Plateforme | chez nous, sous notre nom de domaine | https://api.sealtrust.io/brand/{brand_id}/did.json |
| Auto-hébergé | chez vous, vous servez le fichier vous-même | https://votre-domaine/.well-known/did.json |
| Délégué | chez nous, sous votre nom de domaine | https://votre-domaine/.well-known/did.json |
Le mode plateforme est celui appliqué par défaut. Le mode délégué est celui que cette page décrit. Le mode appliqué à votre marque est posé par SealTrust. Écrivez à contact@sealtrust.io pour en changer.
#Erreurs
Le corps d'une réponse d'erreur porte un champ detail, sauf pour le 400 décrit
ci-dessous. Toute réponse porte un en-tête X-Request-Id, l'identifiant de votre
appel chez nous.
| Code | Condition | Que faire |
|---|---|---|
| 400 | Le nom de domaine appelé n'est pas déclaré chez nous. La réponse est du texte brut, Invalid host header, sans champ detail. Une requête sans en-tête Host, ou avec un en-tête Host vide, reçoit le même 400. | Contactez le support pour faire déclarer votre domaine délégué avant de mettre l'identité en service. |
| 404 | Aucune marque n'a déclaré ce nom de domaine comme son domaine d'identité en mode délégué. detail vaut No DID Document for this host. | Vérifiez le nom de domaine appelé. Une marque en mode plateforme ou en mode auto-hébergé ne répond jamais ici, même si son domaine pointe vers nous. |
| 422 | Le document d'identité de la marque trouvée ne peut pas être construit. detail porte le motif du refus. | Signalez-le au support en indiquant le nom de domaine appelé. Vous ne pouvez rien corriger de votre côté. |
| 429 | Trop d'appels depuis votre adresse réseau. La réponse porte l'en-tête Retry-After, en secondes. | Attendez le nombre de secondes indiqué par Retry-After, puis réessayez. Espacez vos appels : le compteur est partagé avec tous les autres chemins qui n'ont pas de plafond propre. |
| 500 | Une erreur inattendue s'est produite pendant le traitement de votre appel. detail vaut Internal Server Error. | Réessayez. Si l'erreur persiste, contactez le support en indiquant la valeur de X-Request-Id. |
#Voir aussi
GET /brand/{brand_id}/did.json, récupérer les clefs publiques de signature d'une marque.GET /passport/{identifier}/vc/verify, contrôler la signature du justificatif et lire les données révélées.- Confiance et preuves, ce que chaque preuve établit et comment un tiers refait la vérification.
Cette page vous a-t-elle été utile ?
Votre réponse ouvre un courriel pré-rempli dans votre messagerie, à destination de contact@sealtrust.io. Vous le relisez avant de l'envoyer.