summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2020-12-02 09:58:55 +0100
committerVivien Kraus <vivien@planete-kraus.eu>2021-06-05 16:15:59 +0200
commitbb3b41cd36d1eb88f6a44aaa9a3667599d1b657b (patch)
treed9f1ec99e768ae26ea904cd8b13f7c567e581db8
parent9e4ffd421e33679ab4ae7a3e605dd64d8ff693e1 (diff)
Parse and issue OIDC ID tokens
-rw-r--r--doc/webid-oidc.texi102
-rw-r--r--po/fr.po281
-rw-r--r--po/webid-oidc.pot247
-rw-r--r--src/scm/webid-oidc/Makefile.am6
-rw-r--r--src/scm/webid-oidc/errors.scm95
-rw-r--r--src/scm/webid-oidc/oidc-id-token.scm201
6 files changed, 692 insertions, 240 deletions
diff --git a/doc/webid-oidc.texi b/doc/webid-oidc.texi
index 70df6d4..c9c164a 100644
--- a/doc/webid-oidc.texi
+++ b/doc/webid-oidc.texi
@@ -118,11 +118,77 @@ are @emph{strings}, but we hope that in the future SRFI-180 will be
more closely respected.
@menu
+* The ID token::
* The access token::
* The DPoP proof::
* Generic JWTs::
@end menu
+@node The ID token
+@section The ID token
+
+The ID token is a special JWT that the application keeps for
+itself. It is signed by the identity provider, and contains the
+following claims:
+
+@table @emph
+@item webid
+the URI of the user’s webid;
+@item iss
+the URI of the identity provider (issuer);
+@item sub
+the username (the webid-oidc issuer puts the webid again here, but it
+could be any string);
+@item aud
+the ID of the client application that is intended to receive the ID
+token;
+@item nonce
+some random data to change the signature;
+@item exp
+an UTC time (in seconds) for when the token expires;
+@item iat
+the time when it was issued.
+@end table
+
+There are functions to work with ID tokens in
+@emph{(webid-oidc oidc-id-token)}.
+
+@deffn function id-token? @var{object}
+Check that @var{object} is a decoded ID token.
+@end deffn
+
+The following helper functions convert URIs to the URIs from
+@emph{(web uri)} and times to @emph{(srfi srfi-19)} dates.
+
+@deffn function id-token-webid @var{token}
+@deffnx function id-token-iss @var{token}
+@deffnx function id-token-sub @var{token}
+@deffnx function id-token-aud @var{token}
+@deffnx function id-token-nonce @var{token}
+@deffnx function id-token-exp @var{token}
+@deffnx function id-token-iat @var{token}
+Get the suitable field from the payload of @var{token}.
+@end deffn
+
+ID tokens can be signed and encoded as a string, or decoded.
+
+@deffn function id-token-decode @var{token} @var{[#http-get]}
+Decode @var{token}, as a string, into a decoded token. The signature
+verification will need to fetch the oidc configuration of the claimed
+issuer, and check the signature against the published keys. The
+@code{http-get} optional keyword argument can set a different
+implementation of @code{http-get} from @emph{(web client)}. Return
+@code{#f} if it failed, or the decoded token otherwise.
+@end deffn
+
+@deffn function id-token-encode @var{token} @var{key}
+Encode @var{token} and sign it with the issuer’s @var{key}.
+@end deffn
+
+@deffn function issue-id-token @var{issuer-key} @var{#alg} @var{#webid} @var{#iss} @var{#sub} @var{#aud} @var{#exp} @var{#iat}
+Create an ID token, and encode it with @var{issuer-key}.
+@end deffn
+
@node The access token
@section The access token
@@ -400,6 +466,22 @@ The @var{value} of the typ field in the DPoP proof header is
incorrect.
@end deftp
+@deftp {exception type} &incorrect-sub-field @var{value}
+The @var{value} of the sub field is incorrect.
+@end deftp
+
+@deftp {exception type} &incorrect-iss-field @var{value}
+The @var{value} of the iss field is incorrect.
+@end deftp
+
+@deftp {exception type} &incorrect-nonce-field @var{value}
+The @var{value} of the nonce field in the DPoP proof is incorrect.
+@end deftp
+
+@deftp {exception type} &incorrect-htm-field @var{value}
+The @var{value} of the htm field in the DPoP proof is incorrect.
+@end deftp
+
@deftp {exception type} &not-a-client-manifest @var{value} @var{cause}
The @var{client-manifest} is incorrect.
@end deftp
@@ -533,6 +615,26 @@ code.
The @var{authorization-code} cannot be signed.
@end deftp
+@deftp {exception type} &not-an-id-token @var{value} @var{cause}
+The @var{value} is not an ID token.
+@end deftp
+
+@deftp {exception type} &not-an-id-token-header @var{value} @var{cause}
+The @var{value} is not an ID token header.
+@end deftp
+
+@deftp {exception type} &not-an-id-token-payload @var{value} @var{cause}
+The @var{value} is not an ID token payload.
+@end deftp
+
+@deftp {exception type} &cannot-decode-id-token @var{value} @var{cause}
+The @var{value} string is not an encoding of a valid ID token.
+@end deftp
+
+@deftp {exception type} &cannot-encode-id-token @var{id-token} @var{key} @var{cause}
+The @var{id-token} cannot be signed.
+@end deftp
+
@node Cannot fetch data on the web
@section Cannot fetch data on the web
In the client (local and public parts), resource server and identity
diff --git a/po/fr.po b/po/fr.po
index ae51015..3562362 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -126,101 +126,101 @@ msgstr "Utilisation : generate-random [NOMBRE D'OCTETS]\n"
msgid "Usage: generate-key [NUMBER OF BITS | CURVE]\n"
msgstr "Utilisation : generate-key [NOMBRE DE BITS | COURBE]\n"
-#: src/scm/webid-oidc/errors.scm:718
+#: src/scm/webid-oidc/errors.scm:788
msgid "that’s how it is"
msgstr "c’est comme ça"
-#: src/scm/webid-oidc/errors.scm:723
+#: src/scm/webid-oidc/errors.scm:793
#, scheme-format
msgid "the value ~s is not a base64 string (because ~a)"
msgstr "la valeur ~s n’est pas une chaîne base64 (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:726
+#: src/scm/webid-oidc/errors.scm:796
#, scheme-format
msgid "the value ~s is not JSON (because ~a)"
msgstr "la valeur ~s n’est pas du JSON (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:729
+#: src/scm/webid-oidc/errors.scm:799
#, scheme-format
msgid "the value ~s is not Turtle (because ~a)"
msgstr "la valeur ~s n’est pas du Turtle (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:732
+#: src/scm/webid-oidc/errors.scm:802
#, scheme-format
msgid "the value ~s does not identify an elleptic curve"
msgstr "la valeur ~s n’identifie pas une courbe elliptique"
-#: src/scm/webid-oidc/errors.scm:737
+#: src/scm/webid-oidc/errors.scm:807
#, scheme-format
msgid "the value ~s does not identify a JWK (because ~a)"
msgstr "la valeur ~s n’identifie pas une JWK (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:739
+#: src/scm/webid-oidc/errors.scm:809
#, scheme-format
msgid "the value ~s does not identify a JWK"
msgstr "la valeur ~s n’identifie pas une JWK"
-#: src/scm/webid-oidc/errors.scm:744
+#: src/scm/webid-oidc/errors.scm:814
#, scheme-format
msgid "the value ~s does not identify a public JWK (because ~a)"
msgstr "la valeur ~s n’identifie pas une JWK publique (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:746
+#: src/scm/webid-oidc/errors.scm:816
#, scheme-format
msgid "the value ~s does not identify a public JWK"
msgstr "la valeur ~s n’identifie pas une JWK publique"
-#: src/scm/webid-oidc/errors.scm:751
+#: src/scm/webid-oidc/errors.scm:821
#, scheme-format
msgid "the value ~s does not identify a private JWK (because ~a)"
msgstr "la valeur ~s n’identifie pas une JWK privée (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:753
+#: src/scm/webid-oidc/errors.scm:823
#, scheme-format
msgid "the value ~s does not identify a private JWK"
msgstr "la valeur ~s n’identifie pas une JWK privée"
-#: src/scm/webid-oidc/errors.scm:758
+#: src/scm/webid-oidc/errors.scm:828
#, scheme-format
msgid "the value ~s does not identify a JWKS (because ~a)"
msgstr "la valeur ~s n’identifie pas un JWKS (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:760
+#: src/scm/webid-oidc/errors.scm:830
#, scheme-format
msgid "the value ~s does not identify a JWKS"
msgstr "la valeur ~s n’identifie pas un JWKS"
-#: src/scm/webid-oidc/errors.scm:763
+#: src/scm/webid-oidc/errors.scm:833
#, scheme-format
msgid "the value ~s does not identify a hash algorithm"
msgstr "la valeur ~s n’identifie pas un algorithme de hachage"
-#: src/scm/webid-oidc/errors.scm:766
+#: src/scm/webid-oidc/errors.scm:836
#, scheme-format
msgid "the value ~s is not an alist or misses key ~s"
msgstr "la valeur ~s n’est pas une alist ou il manque la clé ~s"
-#: src/scm/webid-oidc/errors.scm:769
+#: src/scm/webid-oidc/errors.scm:839
#, scheme-format
msgid "the value ~s is not a JWS header (because ~a)"
msgstr "la valeur ~s n’est pas un header JWS (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:772
+#: src/scm/webid-oidc/errors.scm:842
#, scheme-format
msgid "the value ~s is not a JWS payload (because ~a)"
msgstr "la valeur ~s n’est pas un contenu JWS (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:775
+#: src/scm/webid-oidc/errors.scm:845
#, scheme-format
msgid "the value ~s is not a JWS (because ~a)"
msgstr "la valeur ~s n’est pas un JWS (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:778
+#: src/scm/webid-oidc/errors.scm:848
#, scheme-format
msgid "the string ~s cannot be split in 3 parts with ~s"
msgstr "la chaîne ~s ne peut pas être découpée en 3 parties avec ~s"
-#: src/scm/webid-oidc/errors.scm:781
+#: src/scm/webid-oidc/errors.scm:851
#, scheme-format
msgid ""
"all key candidates failed to verify signature ~s with algorithm ~s and "
@@ -229,17 +229,17 @@ msgstr ""
"aucune clé candidate n’a pu vérifier la signature ~s avec l’algorithme ~s et "
"le contenu ~a (il y en avait ~a : ~s)"
-#: src/scm/webid-oidc/errors.scm:784
+#: src/scm/webid-oidc/errors.scm:854
#, scheme-format
msgid "I cannot decode JWS ~a (because ~a)"
msgstr "je n’ai pas pu décoder le JWS encodé par ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:787
+#: src/scm/webid-oidc/errors.scm:857
#, scheme-format
msgid "I cannot encode JWS ~a (because ~a)"
msgstr "je n’ai pas pu encoder le JWS ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:790
+#: src/scm/webid-oidc/errors.scm:860
#, scheme-format
msgid ""
"the server request unexpectedly failed with code ~a and reason phrase ~s"
@@ -247,318 +247,336 @@ msgstr ""
"la requête au serveur a échoué de façon inattendue avec un code ~a et une "
"raison ~s"
-#: src/scm/webid-oidc/errors.scm:795
+#: src/scm/webid-oidc/errors.scm:865
#, scheme-format
msgid "the header ~a should not have the value ~s"
msgstr "l’en-tête ~a ne devrait pas avoir la valeur ~s"
-#: src/scm/webid-oidc/errors.scm:797
+#: src/scm/webid-oidc/errors.scm:867
#, scheme-format
msgid "the header ~a should be present"
msgstr "l’en-tête ~a devrait être présent"
-#: src/scm/webid-oidc/errors.scm:800
+#: src/scm/webid-oidc/errors.scm:870
#, scheme-format
msgid "the server response wasn't expected: ~s (because ~a)"
msgstr "la réponse du serveur est inattendue : ~s (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:806
+#: src/scm/webid-oidc/errors.scm:876
#, scheme-format
msgid "the value ~s is not an OIDC configuration (because ~a)"
msgstr "la valeur ~s n’est pas une configuration OIDC (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:811
+#: src/scm/webid-oidc/errors.scm:881
#, scheme-format
msgid "the webid field is incorrect: ~s"
msgstr "le champ webid est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:812
+#: src/scm/webid-oidc/errors.scm:882
msgid "the webid field is missing"
msgstr "le champ webid est manquant"
-#: src/scm/webid-oidc/errors.scm:816
+#: src/scm/webid-oidc/errors.scm:886
+#, scheme-format
+msgid "the sub field is incorrect: ~s"
+msgstr "le champ sub est incorrect : ~s"
+
+#: src/scm/webid-oidc/errors.scm:887
+msgid "the sub field is missing"
+msgstr "le champ sub est manquant"
+
+#: src/scm/webid-oidc/errors.scm:891
#, scheme-format
msgid "the iss field is incorrect: ~s"
msgstr "le champ iss est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:817
+#: src/scm/webid-oidc/errors.scm:892
msgid "the iss field is missing"
msgstr "le champ iss est manquant"
-#: src/scm/webid-oidc/errors.scm:821
+#: src/scm/webid-oidc/errors.scm:896
#, scheme-format
msgid "the aud field is incorrect: ~s"
msgstr "le champ aud est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:822
+#: src/scm/webid-oidc/errors.scm:897
msgid "the aud field is missing"
msgstr "le champ aud est manquant"
-#: src/scm/webid-oidc/errors.scm:826
+#: src/scm/webid-oidc/errors.scm:901
#, scheme-format
msgid "the iat field is incorrect: ~s"
msgstr "le champ iat est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:827
+#: src/scm/webid-oidc/errors.scm:902
msgid "the iat field is missing"
msgstr "le champ iat est manquant"
-#: src/scm/webid-oidc/errors.scm:831
+#: src/scm/webid-oidc/errors.scm:906
#, scheme-format
msgid "the exp field is incorrect: ~s"
msgstr "le champ exp est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:832
+#: src/scm/webid-oidc/errors.scm:907
msgid "the exp field is missing"
msgstr "le champ exp est manquant"
-#: src/scm/webid-oidc/errors.scm:836
+#: src/scm/webid-oidc/errors.scm:911
#, scheme-format
msgid "the cnf/jkt field is incorrect: ~s"
msgstr "le champ cnf/jkt est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:837
+#: src/scm/webid-oidc/errors.scm:912
msgid "the cnf/jkt field is missing"
msgstr "le champ cnf/jkt est manquant"
-#: src/scm/webid-oidc/errors.scm:841
+#: src/scm/webid-oidc/errors.scm:916
#, scheme-format
msgid "the client-id field is incorrect: ~s"
msgstr "le champ client-id est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:842
+#: src/scm/webid-oidc/errors.scm:917
msgid "the client-id field is missing"
msgstr "le champ client-id est manquant"
-#: src/scm/webid-oidc/errors.scm:846
+#: src/scm/webid-oidc/errors.scm:921
#, scheme-format
msgid "the redirect_uris field is incorrect: ~s"
msgstr "le champ redirect_uris est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:847
+#: src/scm/webid-oidc/errors.scm:922
msgid "the redirect_uris field is missing"
msgstr "le champ redirect_uris est manquant"
-#: src/scm/webid-oidc/errors.scm:851
+#: src/scm/webid-oidc/errors.scm:926
#, scheme-format
msgid "the typ field is incorrect: ~s"
msgstr "le champ typ est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:852
+#: src/scm/webid-oidc/errors.scm:927
msgid "the typ field is missing"
msgstr "le champ typ est manquant"
-#: src/scm/webid-oidc/errors.scm:856
+#: src/scm/webid-oidc/errors.scm:931
#, scheme-format
msgid "the jwk field is incorrect: ~s (because ~a)"
msgstr "le champ jwk est incorrect : ~s (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:858
+#: src/scm/webid-oidc/errors.scm:933
msgid "the jwk field is missing"
msgstr "le champ jwk est manquant"
-#: src/scm/webid-oidc/errors.scm:862
+#: src/scm/webid-oidc/errors.scm:937
#, scheme-format
msgid "the jti field is incorrect: ~s"
msgstr "le champ jti est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:863
+#: src/scm/webid-oidc/errors.scm:938
msgid "the jti field is missing"
msgstr "le champ jti est manquant"
-#: src/scm/webid-oidc/errors.scm:867
+#: src/scm/webid-oidc/errors.scm:942
+#, scheme-format
+msgid "the nonce field is incorrect: ~s"
+msgstr "le champ nonce est incorrect : ~s"
+
+#: src/scm/webid-oidc/errors.scm:943
+msgid "the nonce field is missing"
+msgstr "le champ nonce est manquant"
+
+#: src/scm/webid-oidc/errors.scm:947
#, scheme-format
msgid "the htm field is incorrect: ~s"
msgstr "le champ htm est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:868
+#: src/scm/webid-oidc/errors.scm:948
msgid "the htm field is missing"
msgstr "le champ htm est manquant"
-#: src/scm/webid-oidc/errors.scm:872
+#: src/scm/webid-oidc/errors.scm:952
#, scheme-format
msgid "the htu field is incorrect: ~s"
msgstr "le champ htu est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:873
+#: src/scm/webid-oidc/errors.scm:953
msgid "the htu field is missing"
msgstr "le champ htu est manquant"
-#: src/scm/webid-oidc/errors.scm:875
+#: src/scm/webid-oidc/errors.scm:955
#, scheme-format
msgid "~s is not an access token (because ~a)"
msgstr "~s n’est pas un jeton d’accès (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:878
+#: src/scm/webid-oidc/errors.scm:958
#, scheme-format
msgid "~s is not an access token header (because ~a)"
msgstr "~s n’est pas un en-tête de jeton d’accès (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:881
+#: src/scm/webid-oidc/errors.scm:961
#, scheme-format
msgid "~s is not an access token payload (because ~a)"
msgstr "~s n’est pas un contenu de jeton d’accès (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:884
+#: src/scm/webid-oidc/errors.scm:964
#, scheme-format
msgid "~s is not a DPoP proof (because ~a)"
msgstr "~s n’est pas une preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:887
+#: src/scm/webid-oidc/errors.scm:967
#, scheme-format
msgid "~s is not a DPoP proof header (because ~a)"
msgstr "~s n’est pas un en-tête de preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:890
+#: src/scm/webid-oidc/errors.scm:970
#, scheme-format
msgid "~s is not a DPoP proof payload (because ~a)"
msgstr "~s n’est pas un contenu de preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:893
+#: src/scm/webid-oidc/errors.scm:973
#, scheme-format
msgid "I cannot fetch the issuer configuration of ~a (because ~a)"
msgstr ""
"je n’ai pas pu récupérer la configuration de l’émetteur ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:900
+#: src/scm/webid-oidc/errors.scm:980
#, scheme-format
msgid "I cannot fetch the JWKS of ~a at ~a (because ~a)"
msgstr "je n’ai pas pu récupérer le JWKS de ~a à ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:911
+#: src/scm/webid-oidc/errors.scm:991
#, scheme-format
msgid "the HTTP method is signed for ~s, but ~s was requested"
msgstr "la méthode HTTP a été signée pour ~s, mais ~s a été demandé"
-#: src/scm/webid-oidc/errors.scm:914
+#: src/scm/webid-oidc/errors.scm:994
#, scheme-format
msgid "the HTTP uri is signed for ~a, but ~a was requested"
msgstr "l’uri HTTP a été signé pour ~a, mais ~a a été demandé"
-#: src/scm/webid-oidc/errors.scm:917
+#: src/scm/webid-oidc/errors.scm:997
#, scheme-format
msgid "the date is ~a, but the DPoP proof is signed in the future at ~a"
msgstr "la date est ~a, mais la preuve DPoP a été signée dans le futur à ~a"
-#: src/scm/webid-oidc/errors.scm:921
+#: src/scm/webid-oidc/errors.scm:1001
#, scheme-format
msgid "the date is ~a, but the DPoP proof was signed too long ago at ~a"
msgstr ""
"la date est ~a, mais la preuve DPoP a été signée il y a trop longtemps à ~a"
-#: src/scm/webid-oidc/errors.scm:930
+#: src/scm/webid-oidc/errors.scm:1010
#, scheme-format
msgid "the key ~s does not hash to ~a"
msgstr "la clé ~s ne donne pas un hash de ~a"
-#: src/scm/webid-oidc/errors.scm:932
+#: src/scm/webid-oidc/errors.scm:1012
#, scheme-format
msgid "the key confirmation of ~s failed (because ~a)"
msgstr "la confirmation de clé de ~s a échoué (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:934
+#: src/scm/webid-oidc/errors.scm:1014
#, scheme-format
msgid "the key confirmation of ~s failed"
msgstr "la confirmation de la clé ~s a échoué"
-#: src/scm/webid-oidc/errors.scm:936
+#: src/scm/webid-oidc/errors.scm:1016
#, scheme-format
msgid "the jti ~s has already been found (because ~a)"
msgstr "le jti ~s a déjà été trouvé (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:939
+#: src/scm/webid-oidc/errors.scm:1019
#, scheme-format
msgid "I cannot decode ~s as an access token (because ~a)"
msgstr "je n’ai pas pu décoder ~s comme jeton d’accès (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:942
+#: src/scm/webid-oidc/errors.scm:1022
#, scheme-format
msgid "I cannot encode ~s as an access token with key ~s (because ~a)"
msgstr ""
"je n’ai pas pu encoder ~s comme un jeton d’accès avec la clé ~s (parce que "
"~a)"
-#: src/scm/webid-oidc/errors.scm:945
+#: src/scm/webid-oidc/errors.scm:1025
#, scheme-format
msgid "I cannot decode ~s as a DPoP proof (because ~a)"
msgstr "je n’ai pas pu décoder ~s comme preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:948
+#: src/scm/webid-oidc/errors.scm:1028
#, scheme-format
msgid "I cannot encode ~s as a DPoP proof (because ~a)"
msgstr "je n’ai pas pu encoder ~s comme une preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:951
+#: src/scm/webid-oidc/errors.scm:1031
#, scheme-format
msgid "I could not fetch a RDF graph at ~a (because ~a)"
msgstr "je n’ai pas pu récupérer de graphe RDF à ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:954
+#: src/scm/webid-oidc/errors.scm:1034
#, scheme-format
msgid "~s is not a client manifest (because ~a)"
msgstr "~s n’est pas un manifeste client (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:957
+#: src/scm/webid-oidc/errors.scm:1037
#, scheme-format
msgid "~s does not authorize redirection URI ~a"
msgstr "~s n’autorise pas l’URI de redirection ~a"
-#: src/scm/webid-oidc/errors.scm:960
+#: src/scm/webid-oidc/errors.scm:1040
msgid "I cannot serve a public manifest"
msgstr "je ne peux pas servir un manifeste public"
-#: src/scm/webid-oidc/errors.scm:962
+#: src/scm/webid-oidc/errors.scm:1042
#, scheme-format
msgid "~a does not have a client manifest registration triple"
msgstr "~a n’a pas de triplet d’enregistrement de manifeste client"
-#: src/scm/webid-oidc/errors.scm:965
+#: src/scm/webid-oidc/errors.scm:1045
#, scheme-format
msgid "the client manifest at ~a is advertised for ~a"
msgstr "le manifeste client ~a est publié pour ~a"
-#: src/scm/webid-oidc/errors.scm:968
+#: src/scm/webid-oidc/errors.scm:1048
#, scheme-format
msgid "I could not fetch the client manifest of ~a (because ~a)"
msgstr "je n’ai pas pu récupérer le manifeste client de ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:971
+#: src/scm/webid-oidc/errors.scm:1051
#, scheme-format
msgid "~s is not an authorization code (because ~a)"
msgstr "~s n’est pas un code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:974
+#: src/scm/webid-oidc/errors.scm:1054
#, scheme-format
msgid "~s is not an authorization code header (because ~a)"
msgstr "~s n’est pas un en-tête de code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:977
+#: src/scm/webid-oidc/errors.scm:1057
#, scheme-format
msgid "~s is not an authorization code payload (because ~a)"
msgstr "~s n’est pas un contenu de code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:980
+#: src/scm/webid-oidc/errors.scm:1060
#, scheme-format
msgid "the current time is ~a, and the authorization code expired at ~a"
msgstr ""
"la date est actuellement ~a, et le code d’autorisation a expiré à la date ~a"
-#: src/scm/webid-oidc/errors.scm:984
+#: src/scm/webid-oidc/errors.scm:1064
#, scheme-format
msgid "I cannot decode ~s as an authorization code (because ~a)"
msgstr "je n’ai pas pu décoder ~s comme un code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:987
+#: src/scm/webid-oidc/errors.scm:1067
#, scheme-format
msgid "I cannot encode ~s as an authorization code (because ~a)"
msgstr "je n’ai pas pu encoder ~s comme un code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:990
+#: src/scm/webid-oidc/errors.scm:1070
#, scheme-format
msgid "there is no such refresh token as ~s"
msgstr "il n’y a pas de jeton de rafraîchissement ~s"
-#: src/scm/webid-oidc/errors.scm:993
+#: src/scm/webid-oidc/errors.scm:1073
#, scheme-format
msgid ""
"the refresh token is bound to a key confirmed as ~s, but it is used with key "
@@ -567,93 +585,96 @@ msgstr ""
"Le jeton de rafraîchissement est lié à une clé confirmée par ~s, mais il est "
"utilisé avec la clé ~s"
-#: src/scm/webid-oidc/errors.scm:998
+#: src/scm/webid-oidc/errors.scm:1076
+#, scheme-format
+msgid "I cannot decode ~s as an ID token (because ~a)"
+msgstr "je n’ai pas pu décoder ~s comme jeton d’identité (parce que ~a)"
+
+#: src/scm/webid-oidc/errors.scm:1079
+#, scheme-format
+msgid "I cannot encode ~s as an ID token (because ~a)"
+msgstr "je n’ai pas pu encoder ~s comme un jeton d’identité (parce que ~a)"
+
+#: src/scm/webid-oidc/errors.scm:1082
+#, scheme-format
+msgid "~s is not an ID token (because ~a)"
+msgstr "~s n’est pas un jeton d’identité (parce que ~a)"
+
+#: src/scm/webid-oidc/errors.scm:1085
+#, scheme-format
+msgid "~s is not an ID token header (because ~a)"
+msgstr "~s n’est pas un en-tête de jeton d’identité (parce que ~a)"
+
+#: src/scm/webid-oidc/errors.scm:1088
+#, scheme-format
+msgid "~s is not an ID token payload (because ~a)"
+msgstr "~s n’est pas un contenu de jeton d’identité (parce que ~a)"
+
+#: src/scm/webid-oidc/errors.scm:1093
msgid "that’s it"
msgstr "c’est tout"
-#: src/scm/webid-oidc/errors.scm:1002
+#: src/scm/webid-oidc/errors.scm:1097
#, scheme-format
msgid "~a and ~a"
msgstr "~a et ~a"
-#: src/scm/webid-oidc/errors.scm:1005
+#: src/scm/webid-oidc/errors.scm:1100
#, scheme-format
msgid "~a, ~a"
msgstr "~a, ~a"
-#: src/scm/webid-oidc/errors.scm:1009
+#: src/scm/webid-oidc/errors.scm:1104
#, scheme-format
msgid "the signature ~a does not match key ~s with payload ~a"
msgstr "la signature ~a ne correspond pas à la clé ~s avec le contenu ~a"
-#: src/scm/webid-oidc/errors.scm:1012
+#: src/scm/webid-oidc/errors.scm:1107
msgid "there is an undefined variable"
msgstr "il y a une variable non définie"
-#: src/scm/webid-oidc/errors.scm:1014
+#: src/scm/webid-oidc/errors.scm:1109
#, scheme-format
msgid "the origin is ~a"
msgstr "l’origine est ~a"
-#: src/scm/webid-oidc/errors.scm:1017
+#: src/scm/webid-oidc/errors.scm:1112
#, scheme-format
msgid "a message is attached: ~a"
msgstr "un message est attaché : ~a"
-#: src/scm/webid-oidc/errors.scm:1020
+#: src/scm/webid-oidc/errors.scm:1115
#, scheme-format
msgid "the values ~s are problematic"
msgstr "les valeurs ~s sont problématiques"
-#: src/scm/webid-oidc/errors.scm:1023
+#: src/scm/webid-oidc/errors.scm:1118
msgid "there is a kind and args"
msgstr "il y a un type et des arguments"
-#: src/scm/webid-oidc/errors.scm:1025
+#: src/scm/webid-oidc/errors.scm:1120
msgid "there is an assertion failure"
msgstr "il y a un échec d’assertion"
-#: src/scm/webid-oidc/errors.scm:1027
+#: src/scm/webid-oidc/errors.scm:1122
#, scheme-format
msgid "the program quits with code ~a"
msgstr "le programme quitte avec le code ~a"
-#: src/scm/webid-oidc/errors.scm:1030
+#: src/scm/webid-oidc/errors.scm:1125
msgid "the program cannot recover from this exception"
msgstr "le programme ne peut pas récupérer après cette exception"
-#: src/scm/webid-oidc/errors.scm:1032
+#: src/scm/webid-oidc/errors.scm:1127
msgid "there is an error"
msgstr "il y a une erreur"
-#: src/scm/webid-oidc/errors.scm:1034
+#: src/scm/webid-oidc/errors.scm:1129
#, scheme-format
msgid "Unhandled exception type ~a."
msgstr "Type d’exception non pris en charge ~a."
#, scheme-format
-#~ msgid "the sub field is incorrect: ~s"
-#~ msgstr "le champ sub est incorrect : ~s"
-
-#~ msgid "the sub field is missing"
-#~ msgstr "le champ sub est manquant"
-
-#, scheme-format
-#~ msgid "the nonce field is incorrect: ~s"
-#~ msgstr "le champ nonce est incorrect : ~s"
-
-#~ msgid "the nonce field is missing"
-#~ msgstr "le champ nonce est manquant"
-
-#, scheme-format
-#~ msgid "I cannot decode ~s as an ID token (because ~a)"
-#~ msgstr "je n’ai pas pu décoder ~s comme jeton d’identité (parce que ~a)"
-
-#, scheme-format
-#~ msgid "I cannot encode ~s as an ID token (because ~a)"
-#~ msgstr "je n’ai pas pu encoder ~s comme un jeton d’identité (parce que ~a)"
-
-#, scheme-format
#~ msgid "the grant type ~s is not supported"
#~ msgstr "le type d’octroi ~s n’est pas supporté "
@@ -664,18 +685,6 @@ msgstr "Type d’exception non pris en charge ~a."
#~ msgstr "il n’y a pas de jeton de rafraîchissement dans la requête"
#, scheme-format
-#~ msgid "~s is not an ID token (because ~a)"
-#~ msgstr "~s n’est pas un jeton d’identité (parce que ~a)"
-
-#, scheme-format
-#~ msgid "~s is not an ID token header (because ~a)"
-#~ msgstr "~s n’est pas un en-tête de jeton d’identité (parce que ~a)"
-
-#, scheme-format
-#~ msgid "~s is not an ID token payload (because ~a)"
-#~ msgstr "~s n’est pas un contenu de jeton d’identité (parce que ~a)"
-
-#, scheme-format
#~ msgid ""
#~ "I couldn’t set the locale to ~s as an approximation of the client locale "
#~ "~s"
diff --git a/po/webid-oidc.pot b/po/webid-oidc.pot
index d79d173..29a9bb6 100644
--- a/po/webid-oidc.pot
+++ b/po/webid-oidc.pot
@@ -122,496 +122,539 @@ msgstr ""
msgid "Usage: generate-key [NUMBER OF BITS | CURVE]\n"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:718
+#: src/scm/webid-oidc/errors.scm:788
msgid "that’s how it is"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:723
+#: src/scm/webid-oidc/errors.scm:793
#, scheme-format
msgid "the value ~s is not a base64 string (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:726
+#: src/scm/webid-oidc/errors.scm:796
#, scheme-format
msgid "the value ~s is not JSON (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:729
+#: src/scm/webid-oidc/errors.scm:799
#, scheme-format
msgid "the value ~s is not Turtle (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:732
+#: src/scm/webid-oidc/errors.scm:802
#, scheme-format
msgid "the value ~s does not identify an elleptic curve"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:737
+#: src/scm/webid-oidc/errors.scm:807
#, scheme-format
msgid "the value ~s does not identify a JWK (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:739
+#: src/scm/webid-oidc/errors.scm:809
#, scheme-format
msgid "the value ~s does not identify a JWK"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:744
+#: src/scm/webid-oidc/errors.scm:814
#, scheme-format
msgid "the value ~s does not identify a public JWK (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:746
+#: src/scm/webid-oidc/errors.scm:816
#, scheme-format
msgid "the value ~s does not identify a public JWK"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:751
+#: src/scm/webid-oidc/errors.scm:821
#, scheme-format
msgid "the value ~s does not identify a private JWK (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:753
+#: src/scm/webid-oidc/errors.scm:823
#, scheme-format
msgid "the value ~s does not identify a private JWK"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:758
+#: src/scm/webid-oidc/errors.scm:828
#, scheme-format
msgid "the value ~s does not identify a JWKS (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:760
+#: src/scm/webid-oidc/errors.scm:830
#, scheme-format
msgid "the value ~s does not identify a JWKS"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:763
+#: src/scm/webid-oidc/errors.scm:833
#, scheme-format
msgid "the value ~s does not identify a hash algorithm"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:766
+#: src/scm/webid-oidc/errors.scm:836
#, scheme-format
msgid "the value ~s is not an alist or misses key ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:769
+#: src/scm/webid-oidc/errors.scm:839
#, scheme-format
msgid "the value ~s is not a JWS header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:772
+#: src/scm/webid-oidc/errors.scm:842
#, scheme-format
msgid "the value ~s is not a JWS payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:775
+#: src/scm/webid-oidc/errors.scm:845
#, scheme-format
msgid "the value ~s is not a JWS (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:778
+#: src/scm/webid-oidc/errors.scm:848
#, scheme-format
msgid "the string ~s cannot be split in 3 parts with ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:781
+#: src/scm/webid-oidc/errors.scm:851
#, scheme-format
msgid ""
"all key candidates failed to verify signature ~s with algorithm ~s and "
"payload ~a (there were ~a: ~s)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:784
+#: src/scm/webid-oidc/errors.scm:854
#, scheme-format
msgid "I cannot decode JWS ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:787
+#: src/scm/webid-oidc/errors.scm:857
#, scheme-format
msgid "I cannot encode JWS ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:790
+#: src/scm/webid-oidc/errors.scm:860
#, scheme-format
msgid ""
"the server request unexpectedly failed with code ~a and reason phrase ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:795
+#: src/scm/webid-oidc/errors.scm:865
#, scheme-format
msgid "the header ~a should not have the value ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:797
+#: src/scm/webid-oidc/errors.scm:867
#, scheme-format
msgid "the header ~a should be present"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:800
+#: src/scm/webid-oidc/errors.scm:870
#, scheme-format
msgid "the server response wasn't expected: ~s (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:806
+#: src/scm/webid-oidc/errors.scm:876
#, scheme-format
msgid "the value ~s is not an OIDC configuration (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:811
+#: src/scm/webid-oidc/errors.scm:881
#, scheme-format
msgid "the webid field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:812
+#: src/scm/webid-oidc/errors.scm:882
msgid "the webid field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:816
+#: src/scm/webid-oidc/errors.scm:886
+#, scheme-format
+msgid "the sub field is incorrect: ~s"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:887
+msgid "the sub field is missing"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:891
#, scheme-format
msgid "the iss field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:817
+#: src/scm/webid-oidc/errors.scm:892
msgid "the iss field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:821
+#: src/scm/webid-oidc/errors.scm:896
#, scheme-format
msgid "the aud field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:822
+#: src/scm/webid-oidc/errors.scm:897
msgid "the aud field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:826
+#: src/scm/webid-oidc/errors.scm:901
#, scheme-format
msgid "the iat field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:827
+#: src/scm/webid-oidc/errors.scm:902
msgid "the iat field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:831
+#: src/scm/webid-oidc/errors.scm:906
#, scheme-format
msgid "the exp field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:832
+#: src/scm/webid-oidc/errors.scm:907
msgid "the exp field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:836
+#: src/scm/webid-oidc/errors.scm:911
#, scheme-format
msgid "the cnf/jkt field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:837
+#: src/scm/webid-oidc/errors.scm:912
msgid "the cnf/jkt field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:841
+#: src/scm/webid-oidc/errors.scm:916
#, scheme-format
msgid "the client-id field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:842
+#: src/scm/webid-oidc/errors.scm:917
msgid "the client-id field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:846
+#: src/scm/webid-oidc/errors.scm:921
#, scheme-format
msgid "the redirect_uris field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:847
+#: src/scm/webid-oidc/errors.scm:922
msgid "the redirect_uris field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:851
+#: src/scm/webid-oidc/errors.scm:926
#, scheme-format
msgid "the typ field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:852
+#: src/scm/webid-oidc/errors.scm:927
msgid "the typ field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:856
+#: src/scm/webid-oidc/errors.scm:931
#, scheme-format
msgid "the jwk field is incorrect: ~s (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:858
+#: src/scm/webid-oidc/errors.scm:933
msgid "the jwk field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:862
+#: src/scm/webid-oidc/errors.scm:937
#, scheme-format
msgid "the jti field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:863
+#: src/scm/webid-oidc/errors.scm:938
msgid "the jti field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:867
+#: src/scm/webid-oidc/errors.scm:942
+#, scheme-format
+msgid "the nonce field is incorrect: ~s"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:943
+msgid "the nonce field is missing"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:947
#, scheme-format
msgid "the htm field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:868
+#: src/scm/webid-oidc/errors.scm:948
msgid "the htm field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:872
+#: src/scm/webid-oidc/errors.scm:952
#, scheme-format
msgid "the htu field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:873
+#: src/scm/webid-oidc/errors.scm:953
msgid "the htu field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:875
+#: src/scm/webid-oidc/errors.scm:955
#, scheme-format
msgid "~s is not an access token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:878
+#: src/scm/webid-oidc/errors.scm:958
#, scheme-format
msgid "~s is not an access token header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:881
+#: src/scm/webid-oidc/errors.scm:961
#, scheme-format
msgid "~s is not an access token payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:884
+#: src/scm/webid-oidc/errors.scm:964
#, scheme-format
msgid "~s is not a DPoP proof (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:887
+#: src/scm/webid-oidc/errors.scm:967
#, scheme-format
msgid "~s is not a DPoP proof header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:890
+#: src/scm/webid-oidc/errors.scm:970
#, scheme-format
msgid "~s is not a DPoP proof payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:893
+#: src/scm/webid-oidc/errors.scm:973
#, scheme-format
msgid "I cannot fetch the issuer configuration of ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:900
+#: src/scm/webid-oidc/errors.scm:980
#, scheme-format
msgid "I cannot fetch the JWKS of ~a at ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:911
+#: src/scm/webid-oidc/errors.scm:991
#, scheme-format
msgid "the HTTP method is signed for ~s, but ~s was requested"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:914
+#: src/scm/webid-oidc/errors.scm:994
#, scheme-format
msgid "the HTTP uri is signed for ~a, but ~a was requested"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:917
+#: src/scm/webid-oidc/errors.scm:997
#, scheme-format
msgid "the date is ~a, but the DPoP proof is signed in the future at ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:921
+#: src/scm/webid-oidc/errors.scm:1001
#, scheme-format
msgid "the date is ~a, but the DPoP proof was signed too long ago at ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:930
+#: src/scm/webid-oidc/errors.scm:1010
#, scheme-format
msgid "the key ~s does not hash to ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:932
+#: src/scm/webid-oidc/errors.scm:1012
#, scheme-format
msgid "the key confirmation of ~s failed (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:934
+#: src/scm/webid-oidc/errors.scm:1014
#, scheme-format
msgid "the key confirmation of ~s failed"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:936
+#: src/scm/webid-oidc/errors.scm:1016
#, scheme-format
msgid "the jti ~s has already been found (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:939
+#: src/scm/webid-oidc/errors.scm:1019
#, scheme-format
msgid "I cannot decode ~s as an access token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:942
+#: src/scm/webid-oidc/errors.scm:1022
#, scheme-format
msgid "I cannot encode ~s as an access token with key ~s (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:945
+#: src/scm/webid-oidc/errors.scm:1025
#, scheme-format
msgid "I cannot decode ~s as a DPoP proof (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:948
+#: src/scm/webid-oidc/errors.scm:1028
#, scheme-format
msgid "I cannot encode ~s as a DPoP proof (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:951
+#: src/scm/webid-oidc/errors.scm:1031
#, scheme-format
msgid "I could not fetch a RDF graph at ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:954
+#: src/scm/webid-oidc/errors.scm:1034
#, scheme-format
msgid "~s is not a client manifest (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:957
+#: src/scm/webid-oidc/errors.scm:1037
#, scheme-format
msgid "~s does not authorize redirection URI ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:960
+#: src/scm/webid-oidc/errors.scm:1040
msgid "I cannot serve a public manifest"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:962
+#: src/scm/webid-oidc/errors.scm:1042
#, scheme-format
msgid "~a does not have a client manifest registration triple"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:965
+#: src/scm/webid-oidc/errors.scm:1045
#, scheme-format
msgid "the client manifest at ~a is advertised for ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:968
+#: src/scm/webid-oidc/errors.scm:1048
#, scheme-format
msgid "I could not fetch the client manifest of ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:971
+#: src/scm/webid-oidc/errors.scm:1051
#, scheme-format
msgid "~s is not an authorization code (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:974
+#: src/scm/webid-oidc/errors.scm:1054
#, scheme-format
msgid "~s is not an authorization code header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:977
+#: src/scm/webid-oidc/errors.scm:1057
#, scheme-format
msgid "~s is not an authorization code payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:980
+#: src/scm/webid-oidc/errors.scm:1060
#, scheme-format
msgid "the current time is ~a, and the authorization code expired at ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:984
+#: src/scm/webid-oidc/errors.scm:1064
#, scheme-format
msgid "I cannot decode ~s as an authorization code (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:987
+#: src/scm/webid-oidc/errors.scm:1067
#, scheme-format
msgid "I cannot encode ~s as an authorization code (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:990
+#: src/scm/webid-oidc/errors.scm:1070
#, scheme-format
msgid "there is no such refresh token as ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:993
+#: src/scm/webid-oidc/errors.scm:1073
#, scheme-format
msgid ""
"the refresh token is bound to a key confirmed as ~s, but it is used with key "
"~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:998
+#: src/scm/webid-oidc/errors.scm:1076
+#, scheme-format
+msgid "I cannot decode ~s as an ID token (because ~a)"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1079
+#, scheme-format
+msgid "I cannot encode ~s as an ID token (because ~a)"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1082
+#, scheme-format
+msgid "~s is not an ID token (because ~a)"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1085
+#, scheme-format
+msgid "~s is not an ID token header (because ~a)"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1088
+#, scheme-format
+msgid "~s is not an ID token payload (because ~a)"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1093
msgid "that’s it"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1002
+#: src/scm/webid-oidc/errors.scm:1097
#, scheme-format
msgid "~a and ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1005
+#: src/scm/webid-oidc/errors.scm:1100
#, scheme-format
msgid "~a, ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1009
+#: src/scm/webid-oidc/errors.scm:1104
#, scheme-format
msgid "the signature ~a does not match key ~s with payload ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1012
+#: src/scm/webid-oidc/errors.scm:1107
msgid "there is an undefined variable"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1014
+#: src/scm/webid-oidc/errors.scm:1109
#, scheme-format
msgid "the origin is ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1017
+#: src/scm/webid-oidc/errors.scm:1112
#, scheme-format
msgid "a message is attached: ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1020
+#: src/scm/webid-oidc/errors.scm:1115
#, scheme-format
msgid "the values ~s are problematic"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1023
+#: src/scm/webid-oidc/errors.scm:1118
msgid "there is a kind and args"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1025
+#: src/scm/webid-oidc/errors.scm:1120
msgid "there is an assertion failure"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1027
+#: src/scm/webid-oidc/errors.scm:1122
#, scheme-format
msgid "the program quits with code ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1030
+#: src/scm/webid-oidc/errors.scm:1125
msgid "the program cannot recover from this exception"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1032
+#: src/scm/webid-oidc/errors.scm:1127
msgid "there is an error"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1034
+#: src/scm/webid-oidc/errors.scm:1129
#, scheme-format
msgid "Unhandled exception type ~a."
msgstr ""
diff --git a/src/scm/webid-oidc/Makefile.am b/src/scm/webid-oidc/Makefile.am
index d18d5fc..56b50ec 100644
--- a/src/scm/webid-oidc/Makefile.am
+++ b/src/scm/webid-oidc/Makefile.am
@@ -12,7 +12,8 @@ dist_webidoidcmod_DATA += \
%reldir%/fetch.scm \
%reldir%/client-manifest.scm \
%reldir%/authorization-code.scm \
- %reldir%/refresh-token.scm
+ %reldir%/refresh-token.scm \
+ %reldir%/oidc-id-token.scm
webidoidcgo_DATA += \
%reldir%/errors.go \
%reldir%/stubs.go \
@@ -27,4 +28,5 @@ webidoidcgo_DATA += \
%reldir%/fetch.go \
%reldir%/client-manifest.go \
%reldir%/authorization-code.go \
- %reldir%/refresh-token.go
+ %reldir%/refresh-token.go \
+ %reldir%/oidc-id-token.go
diff --git a/src/scm/webid-oidc/errors.scm b/src/scm/webid-oidc/errors.scm
index e8ab5af..b0e9a19 100644
--- a/src/scm/webid-oidc/errors.scm
+++ b/src/scm/webid-oidc/errors.scm
@@ -249,6 +249,16 @@
(raise-exception
((record-constructor &incorrect-webid-field) value)))
+(define-public &incorrect-sub-field
+ (make-exception-type
+ '&incorrect-sub-field
+ &external-error
+ '(value)))
+
+(define-public (raise-incorrect-sub-field value)
+ (raise-exception
+ ((record-constructor &incorrect-sub-field) value)))
+
(define-public &incorrect-iss-field
(make-exception-type
'&incorrect-iss-field
@@ -349,6 +359,16 @@
(raise-exception
((record-constructor &incorrect-jti-field) value)))
+(define-public &incorrect-nonce-field
+ (make-exception-type
+ '&incorrect-nonce-field
+ &external-error
+ '(value)))
+
+(define-public (raise-incorrect-nonce-field value)
+ (raise-exception
+ ((record-constructor &incorrect-nonce-field) value)))
+
(define-public &incorrect-htm-field
(make-exception-type
'&incorrect-htm-field
@@ -707,6 +727,56 @@
(raise-exception
((record-constructor &invalid-key-for-refresh-token) key jkt)))
+(define-public &not-an-id-token
+ (make-exception-type
+ '&not-an-id-token
+ &external-error
+ '(value cause)))
+
+(define-public (raise-not-an-id-token value cause)
+ (raise-exception
+ ((record-constructor &not-an-id-token) value cause)))
+
+(define-public &not-an-id-token-header
+ (make-exception-type
+ '&not-an-id-token-header
+ &external-error
+ '(value cause)))
+
+(define-public (raise-not-an-id-token-header value cause)
+ (raise-exception
+ ((record-constructor &not-an-id-token-header) value cause)))
+
+(define-public &not-an-id-token-payload
+ (make-exception-type
+ '&not-an-id-token-payload
+ &external-error
+ '(value cause)))
+
+(define-public (raise-not-an-id-token-payload value cause)
+ (raise-exception
+ ((record-constructor &not-an-id-token-payload) value cause)))
+
+(define-public &cannot-decode-id-token
+ (make-exception-type
+ '&cannot-decode-id-token
+ &external-error
+ '(value cause)))
+
+(define-public (raise-cannot-decode-id-token value cause)
+ (raise-exception
+ ((record-constructor &cannot-decode-id-token) value cause)))
+
+(define-public &cannot-encode-id-token
+ (make-exception-type
+ '&cannot-encode-id-token
+ &external-error
+ '(id-token key cause)))
+
+(define-public (raise-cannot-encode-id-token id-token key cause)
+ (raise-exception
+ ((record-constructor &cannot-encode-id-token) id-token key cause)))
+
(define*-public (error->str err #:key (max-depth #f))
(if (record? err)
(let* ((type (record-type-descriptor err))
@@ -810,6 +880,11 @@
(if value
(format #f (G_ "the webid field is incorrect: ~s") value)
(format #f (G_ "the webid field is missing")))))
+ ((&incorrect-sub-field)
+ (let ((value (get 'value)))
+ (if value
+ (format #f (G_ "the sub field is incorrect: ~s") value)
+ (format #f (G_ "the sub field is missing")))))
((&incorrect-iss-field)
(let ((value (get 'value)))
(if value
@@ -861,6 +936,11 @@
(if value
(format #f (G_ "the jti field is incorrect: ~s") value)
(format #f (G_ "the jti field is missing")))))
+ ((&incorrect-nonce-field)
+ (let ((value (get 'value)))
+ (if value
+ (format #f (G_ "the nonce field is incorrect: ~s") value)
+ (format #f (G_ "the nonce field is missing")))))
((&incorrect-htm-field)
(let ((value (get 'value)))
(if value
@@ -992,6 +1072,21 @@
((&invalid-key-for-refresh-token)
(format #f (G_ "the refresh token is bound to a key confirmed as ~s, but it is used with key ~s")
(get 'jkt) (get 'key)))
+ ((&cannot-decode-id-token)
+ (format #f (G_ "I cannot decode ~s as an ID token (because ~a)")
+ (get 'value) (recurse (get 'cause))))
+ ((&cannot-encode-id-token)
+ (format #f (G_ "I cannot encode ~s as an ID token (because ~a)")
+ (get 'value) (recurse (get 'cause))))
+ ((&not-an-id-token)
+ (format #f (G_ "~s is not an ID token (because ~a)")
+ (get 'value) (recurse (get 'cause))))
+ ((&not-an-id-token-header)
+ (format #f (G_ "~s is not an ID token header (because ~a)")
+ (get 'value) (recurse (get 'cause))))
+ ((&not-an-id-token-payload)
+ (format #f (G_ "~s is not an ID token payload (because ~a)")
+ (get 'value) (recurse (get 'cause))))
((&compound-exception)
(let ((components (get 'components)))
(if (null? components)
diff --git a/src/scm/webid-oidc/oidc-id-token.scm b/src/scm/webid-oidc/oidc-id-token.scm
new file mode 100644
index 0000000..18ac124
--- /dev/null
+++ b/src/scm/webid-oidc/oidc-id-token.scm
@@ -0,0 +1,201 @@
+(define-module (webid-oidc oidc-id-token)
+ #:use-module (webid-oidc oidc-configuration)
+ #:use-module (webid-oidc errors)
+ #:use-module (webid-oidc jws)
+ #:use-module (webid-oidc jti)
+ #:use-module ((webid-oidc stubs) #:prefix stubs:)
+ #:use-module (web uri)
+ #:use-module (web client)
+ #:use-module (ice-9 optargs)
+ #:use-module (srfi srfi-19))
+
+(define-public (the-id-token-header x)
+ (with-exception-handler
+ (lambda (error)
+ (raise-not-an-id-token-header x error))
+ (lambda ()
+ (the-jws-header x))))
+
+(define-public (id-token-header? x)
+ (false-if-exception
+ (and (the-id-token-header x) #t)))
+
+(define-public (the-id-token-payload x)
+ (with-exception-handler
+ (lambda (error)
+ (raise-not-an-id-token-payload x error))
+ (lambda ()
+ (let ((x (the-jws-payload x)))
+ (let ((webid (assq-ref x 'webid))
+ (iss (assq-ref x 'iss))
+ (sub (assq-ref x 'sub))
+ (aud (assq-ref x 'aud))
+ (nonce (assq-ref x 'nonce))
+ (iat (assq-ref x 'iat))
+ (exp (assq-ref x 'exp)))
+ (unless (and webid (string? webid) (string->uri webid))
+ (raise-incorrect-webid-field webid))
+ (unless (and iss (string? iss) (string->uri iss))
+ (raise-incorrect-iss-field iss))
+ (unless (string? sub)
+ (raise-incorrect-sub-field sub))
+ (unless (and aud (string? aud) (string->uri aud))
+ (raise-incorrect-aud-field aud))
+ (unless (string? nonce)
+ (raise-incorrect-nonce-field nonce))
+ (unless (integer? iat)
+ (raise-incorrect-iat-field iat))
+ (unless (and (integer? exp) (>= exp iat))
+ (raise-incorrect-exp-field exp))
+ x)))))
+
+(define-public (id-token-payload? x)
+ (false-if-exception
+ (and (the-id-token-header x) #t)))
+
+(define-public (the-id-token x)
+ (with-exception-handler
+ (lambda (cause)
+ (raise-not-an-id-token x cause))
+ (lambda ()
+ (cons (the-id-token-header (car x))
+ (the-id-token-payload (cdr x))))))
+
+(define-public (id-token? x)
+ (false-if-exception
+ (and (the-id-token x) #t)))
+
+(define-public (make-id-token header payload)
+ (the-id-token
+ (cons header payload)))
+
+(define-public (make-id-token-payload webid iss sub aud nonce exp iat)
+ (when (date? exp)
+ (set! exp (date->time-utc exp)))
+ (when (time? exp)
+ (set! exp (time-second exp)))
+ (when (date? iat)
+ (set! iat (date->time-utc iat)))
+ (when (time? iat)
+ (set! iat (time-second iat)))
+ (when (uri? webid)
+ (set! webid (uri->string webid)))
+ (when (uri? iss)
+ (set! iss (uri->string iss)))
+ (when (uri? aud)
+ (set! aud (uri->string aud)))
+ (the-id-token-payload
+ `((webid . ,webid)
+ (iss . ,iss)
+ (sub . ,sub)
+ (aud . ,aud)
+ (nonce . ,nonce)
+ (exp . ,exp)
+ (iat . ,iat))))
+
+(define-public (id-token-header code)
+ (car (the-id-token code)))
+
+(define-public (id-token-payload code)
+ (cdr (the-id-token code)))
+
+(define-public (id-token-alg code)
+ (when (id-token? code)
+ (set! code (id-token-header code)))
+ (jws-alg (the-id-token-header code)))
+
+(define-public (id-token-webid code)
+ (when (id-token? code)
+ (set! code (id-token-payload code)))
+ (string->uri
+ (assq-ref (the-id-token-payload code) 'webid)))
+
+(define-public (id-token-iss code)
+ (when (id-token? code)
+ (set! code (id-token-payload code)))
+ (string->uri
+ (assq-ref (the-id-token-payload code) 'iss)))
+
+(define-public (id-token-sub code)
+ (when (id-token? code)
+ (set! code (id-token-payload code)))
+ (assq-ref (the-id-token-payload code) 'sub))
+
+(define-public (id-token-aud code)
+ (when (id-token? code)
+ (set! code (id-token-payload code)))
+ (string->uri
+ (assq-ref (the-id-token-payload code) 'aud)))
+
+(define-public (id-token-nonce code)
+ (when (id-token? code)
+ (set! code (id-token-payload code)))
+ (assq-ref (the-id-token-payload code) 'nonce))
+
+(define-public (id-token-exp code)
+ (when (id-token? code)
+ (set! code (id-token-payload code)))
+ (time-utc->date
+ (make-time time-utc 0 (assq-ref
+ (the-id-token-payload code)
+ 'exp))))
+
+(define-public (id-token-iat code)
+ (when (id-token? code)
+ (set! code (id-token-payload code)))
+ (time-utc->date
+ (make-time time-utc 0 (assq-ref
+ (the-id-token-payload code)
+ 'iat))))
+
+(define*-public (id-token-decode str #:key (http-get http-get))
+ (with-exception-handler
+ (lambda (error)
+ (raise-cannot-decode-id-token str error))
+ (lambda ()
+ (jws-decode
+ str
+ (lambda (token)
+ (let ((iss (id-token-iss token)))
+ (let ((cfg
+ (with-exception-handler
+ (lambda (error)
+ (raise-cannot-fetch-issuer-configuration iss error))
+ (lambda ()
+ (get-oidc-configuration
+ (uri-host iss)
+ #:userinfo (uri-userinfo iss)
+ #:port (uri-port iss)
+ #:http-get http-get)))))
+ (with-exception-handler
+ (lambda (error)
+ (raise-cannot-fetch-jwks iss
+ (oidc-configuration-jwks-uri cfg)
+ error))
+ (lambda ()
+ (oidc-configuration-jwks cfg #:http-get http-get))))))))))
+
+(define-public (id-token-encode id-token key)
+ (with-exception-handler
+ (lambda (error)
+ (raise-cannot-encode-id-token id-token key error))
+ (lambda ()
+ (jws-encode id-token key))))
+
+(define*-public (issue-id-token
+ issuer-key
+ #:key
+ (alg #f)
+ (webid #f)
+ (iss #f)
+ (sub #f)
+ (aud #f)
+ (exp #f)
+ (iat #f))
+ (unless sub
+ (set! sub webid))
+ (id-token-encode
+ (make-id-token
+ `((alg . ,(symbol->string alg)))
+ (make-id-token-payload webid iss sub aud (stubs:random 12) exp iat))
+ issuer-key))