From 0d74f8c1ca9c1e9bf9a04b85f598ba7a175d1d86 Mon Sep 17 00:00:00 2001 From: Vivien Kraus Date: Tue, 21 Sep 2021 19:49:24 +0200 Subject: OIDC configuration: use GOOPS and document it --- doc/disfluid.texi | 60 ++++++ po/disfluid.pot | 155 ++++++++------- po/fr.po | 202 +++++++++++--------- src/scm/webid-oidc/access-token.scm | 1 - src/scm/webid-oidc/client.scm | 1 - src/scm/webid-oidc/client/accounts.scm | 34 ++-- src/scm/webid-oidc/client/application.scm | 1 - src/scm/webid-oidc/client/client.scm | 1 - src/scm/webid-oidc/client/gui.scm | 1 - src/scm/webid-oidc/identity-provider.scm | 11 +- src/scm/webid-oidc/jws.scm | 19 +- src/scm/webid-oidc/oidc-configuration.scm | 301 +++++++++++++++--------------- src/scm/webid-oidc/oidc-id-token.scm | 1 - src/scm/webid-oidc/parameters.scm | 7 +- src/scm/webid-oidc/resource-server.scm | 1 - tests/client-workflow.scm | 38 ++-- tests/oidc-configuration.scm | 58 +++--- tests/resource-server.scm | 47 ++--- 18 files changed, 509 insertions(+), 430 deletions(-) diff --git a/doc/disfluid.texi b/doc/disfluid.texi index 42437c2..6247bfa 100644 --- a/doc/disfluid.texi +++ b/doc/disfluid.texi @@ -61,6 +61,7 @@ is tracked in the Guix channel * Invoking disfluid:: * Running disfluid with GNU Guix:: * Managing keys:: +* OIDC discovery:: * The Json Web Token:: * Caching on server side:: * Content negociation:: @@ -458,6 +459,65 @@ If the JWKS cannot be downloaded, or is incorrect, this exception is raised. @end deftp +@node OIDC discovery +@chapter OIDC discovery +An identity provider is known by its server name. The different +endpoints can be discovered from there. + +@deftp {Class} () @var{jwks-uri} @var{authorization-endpoint} @var{token-endpoint} +The OIDC configuration for an identity provider. @var{jwks-uri}, +@var{authorization-endpoint} adn @var{token-endpoint} are all URIs. + +You can construct an OIDC configuration two different ways: +@itemize +@item +by passing @code{#:@var{jwks-uri}}, +@code{#:@var{authorization-endpoint}} and +@code{#:@var{token-endpoint}} to the constructor; +@item +by passing @code{#:@var{server}}, and optionally +@code{#:@var{http-request}} to the constructor, to query the +@var{server} for its configuration. +@end itemize +@end deftp + +@deftp {Exception type} &invalid-oidc-configuration +This exception is raised when the configuration is unusable or +incomplete. +@end deftp + +@deffn {function} make-invalid-oidc-configuration +Constructor for the @code{&invalid-oidc-configuration} exception type. +@end deffn + +@deffn {function} invalid-oidc-configuration? @var{exception} +Check whether @var{exception} was raised because of an invalid OIDC +configuration. +@end deffn + +@deffn {Generic} jwks-uri @var{oidc-configuration} +Return the JWKS uri of @var{oidc-configuration}. +@end deffn + +@deffn {Generic} jwks @var{oidc-configuration} +Query the JWKS uri of @var{oidc-configuration}. +@end deffn + +@deffn {Generic} authorization-endpoint @var{oidc-configuration} +Return the authorization endpoint of @var{oidc-configuration}. +@end deffn + +@deffn {Generic} token-endpoint @var{oidc-configuration} +Return the token endpoint of @var{oidc-configuration}. +@end deffn + +@deffn {Generic} serve @var{configuration} @var{expiration-date} +Return 2 values: the response, and response body, needed to serve +@var{configuration}. It is very much recommended to let clients cache +this value. They will not revalidate it until after +@var{expiration-date}, a SRFI-19 date. +@end deffn + @node The Json Web Token @chapter The Json Web Token diff --git a/po/disfluid.pot b/po/disfluid.pot index 7702c98..6c39980 100644 --- a/po/disfluid.pot +++ b/po/disfluid.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: disfluid SNAPSHOT\n" "Report-Msgid-Bugs-To: vivien@planete-kraus.eu\n" -"POT-Creation-Date: 2021-09-21 22:30+0200\n" +"POT-Creation-Date: 2021-09-21 22:31+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -122,34 +122,34 @@ msgid "" "webid_oidc_random_init first.\n" msgstr "" -#: src/scm/webid-oidc/access-token.scm:73 +#: src/scm/webid-oidc/access-token.scm:72 #, scheme-format msgid "invalid access token: ~a" msgstr "" -#: src/scm/webid-oidc/access-token.scm:75 +#: src/scm/webid-oidc/access-token.scm:74 msgid "invalid access token" msgstr "" -#: src/scm/webid-oidc/access-token.scm:117 +#: src/scm/webid-oidc/access-token.scm:116 #: src/scm/webid-oidc/authorization-code.scm:93 -#: src/scm/webid-oidc/oidc-id-token.scm:100 +#: src/scm/webid-oidc/oidc-id-token.scm:99 msgid "#:webid should be an URI" msgstr "" -#: src/scm/webid-oidc/access-token.scm:122 +#: src/scm/webid-oidc/access-token.scm:121 msgid "#:client-id should be an URI" msgstr "" -#: src/scm/webid-oidc/access-token.scm:127 +#: src/scm/webid-oidc/access-token.scm:126 msgid "#:cnf/jkt should be a string" msgstr "" -#: src/scm/webid-oidc/access-token.scm:132 +#: src/scm/webid-oidc/access-token.scm:131 msgid "#:aud should be exactly \"solid\"" msgstr "" -#: src/scm/webid-oidc/access-token.scm:150 +#: src/scm/webid-oidc/access-token.scm:149 msgid "" "when making an access token either its required fields (#:alg, #:webid, #:" "iss, #:aud, #:client-id, #:cnf/jkt, #:iat and #:exp) or (#:jwt-header and #:" @@ -178,7 +178,7 @@ msgstr "" #: src/scm/webid-oidc/authorization-page-unsafe.scm:52 #: src/scm/webid-oidc/hello-world.scm:40 src/scm/webid-oidc/hello-world.scm:167 #: src/scm/webid-oidc/hello-world.scm:187 -#: src/scm/webid-oidc/identity-provider.scm:139 +#: src/scm/webid-oidc/identity-provider.scm:140 #: src/scm/webid-oidc/token-endpoint.scm:113 #: src/scm/webid-oidc/token-endpoint.scm:139 #: src/scm/webid-oidc/token-endpoint.scm:166 @@ -241,7 +241,7 @@ msgid "The application you are trying to authorize behaved unexpectedly." msgstr "" #: src/scm/webid-oidc/authorization-page-unsafe.scm:126 -#: src/scm/webid-oidc/resource-server.scm:311 +#: src/scm/webid-oidc/resource-server.scm:310 msgid "reason-phrase|Found" msgstr "" @@ -435,33 +435,33 @@ msgstr "" msgid "The issuer should be a string or URI." msgstr "" -#: src/scm/webid-oidc/client/application.scm:229 +#: src/scm/webid-oidc/client/application.scm:228 #, scheme-format msgid "Add an account on ~a" msgstr "" -#: src/scm/webid-oidc/client/application.scm:244 +#: src/scm/webid-oidc/client/application.scm:243 #, scheme-format msgid "" "You already have an account for ~a issued by ~a and it is currently selected." msgstr "" -#: src/scm/webid-oidc/client/application.scm:263 +#: src/scm/webid-oidc/client/application.scm:262 #, scheme-format msgid "You already have an account for ~a issued by ~a." msgstr "" -#: src/scm/webid-oidc/client/client.scm:108 +#: src/scm/webid-oidc/client/client.scm:107 msgid "" "Client ID and redirect URIs should be URIs, and key pair should be a key " "pair.." msgstr "" -#: src/scm/webid-oidc/client/gui.scm:59 +#: src/scm/webid-oidc/client/gui.scm:58 msgid "Hello, world!\n" msgstr "" -#: src/scm/webid-oidc/client/gui.scm:64 +#: src/scm/webid-oidc/client/gui.scm:63 msgid "Hello, world!" msgstr "" @@ -829,7 +829,7 @@ msgid "The port should be a number between 0 and 65535.\n" msgstr "" #: src/scm/webid-oidc/hello-world.scm:159 -#: src/scm/webid-oidc/resource-server.scm:332 +#: src/scm/webid-oidc/resource-server.scm:331 msgid "reason-phrase|Unauthorized" msgstr "" @@ -842,7 +842,7 @@ msgid "

This page requires authentication with Solid.

" msgstr "" #: src/scm/webid-oidc/hello-world.scm:179 -#: src/scm/webid-oidc/resource-server.scm:340 +#: src/scm/webid-oidc/resource-server.scm:339 msgid "reason-phrase|Method Not Allowed" msgstr "" @@ -854,11 +854,11 @@ msgstr "" msgid "

You can only use the GET method on this resource.

" msgstr "" -#: src/scm/webid-oidc/identity-provider.scm:76 +#: src/scm/webid-oidc/identity-provider.scm:77 msgid "Warning: generating a new key pair." msgstr "" -#: src/scm/webid-oidc/identity-provider.scm:132 +#: src/scm/webid-oidc/identity-provider.scm:133 msgid "reason-phrase|Not Found" msgstr "" @@ -1007,126 +1007,117 @@ msgstr "" msgid "I cannot query the identity provider configuration" msgstr "" -#: src/scm/webid-oidc/jws.scm:505 +#: src/scm/webid-oidc/jws.scm:501 #, scheme-format msgid "I cannot query the JWKS URI of the identity provider: ~a" msgstr "" -#: src/scm/webid-oidc/jws.scm:507 +#: src/scm/webid-oidc/jws.scm:503 msgid "I cannot query the JWKS URI of the identity provider" msgstr "" -#: src/scm/webid-oidc/jws.scm:535 +#: src/scm/webid-oidc/jws.scm:528 #, scheme-format msgid "the token is signed in the future, ~a, relative to current ~a" msgstr "" -#: src/scm/webid-oidc/jws.scm:544 +#: src/scm/webid-oidc/jws.scm:537 #, scheme-format msgid "the token expired ~a, which is in the past (from ~a)" msgstr "" -#: src/scm/webid-oidc/jws.scm:567 +#: src/scm/webid-oidc/jws.scm:560 #, scheme-format msgid "cannot decode a JWS: ~a" msgstr "" -#: src/scm/webid-oidc/jws.scm:569 +#: src/scm/webid-oidc/jws.scm:562 msgid "cannot decode a JWS" msgstr "" -#: src/scm/webid-oidc/jws.scm:587 +#: src/scm/webid-oidc/jws.scm:580 #, scheme-format msgid "cannot encode a JWS: ~a" msgstr "" -#: src/scm/webid-oidc/jws.scm:589 +#: src/scm/webid-oidc/jws.scm:582 msgid "cannot encode a JWS" msgstr "" -#: src/scm/webid-oidc/jws.scm:636 +#: src/scm/webid-oidc/jws.scm:629 msgid "cannot parse a token" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:59 -#, scheme-format -msgid "the OIDC configuration is invalid: ~a" -msgstr "" - -#: src/scm/webid-oidc/oidc-configuration.scm:61 -msgid "the OIDC configuration is invalid" -msgstr "" - -#: src/scm/webid-oidc/oidc-configuration.scm:77 -#, scheme-format -msgid "the OIDC configuration does not have: ~s" -msgstr "" - -#: src/scm/webid-oidc/oidc-configuration.scm:92 -#, scheme-format -msgid "invalid JWKS URI: ~s" +#: src/scm/webid-oidc/oidc-configuration.scm:120 +msgid "#:jwks-uri should be an URI" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:99 -#, scheme-format -msgid "invalid token endpoint: ~s" +#: src/scm/webid-oidc/oidc-configuration.scm:125 +msgid "#:token-endpoint should be an URI" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:108 -#, scheme-format -msgid "invalid authorization endpoint: ~s" +#: src/scm/webid-oidc/oidc-configuration.scm:130 +msgid "#:authorization-endpoint should be an URI" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:116 -#, scheme-format -msgid "\"solid_oidc_supported\" should be set to ~s, not ~s" +#: src/scm/webid-oidc/oidc-configuration.scm:135 +msgid "" +"#:solid-oidc-supported should be exactly 'https://solidproject.org/TR/solid-" +"oidc'" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:124 -msgid "invalid JSON object" +#: src/scm/webid-oidc/oidc-configuration.scm:144 +msgid "#:server should be an URI" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:178 +#: src/scm/webid-oidc/oidc-configuration.scm:161 #, scheme-format msgid "cannot fetch the OIDC configuration: ~a" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:180 +#: src/scm/webid-oidc/oidc-configuration.scm:163 msgid "cannot fetch the OIDC configuration" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:188 +#: src/scm/webid-oidc/oidc-configuration.scm:167 #, scheme-format msgid "the server responded with ~s ~s" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:193 +#: src/scm/webid-oidc/oidc-configuration.scm:172 msgid "there is no content-type" msgstr "" -#: src/scm/webid-oidc/oidc-configuration.scm:198 +#: src/scm/webid-oidc/oidc-configuration.scm:177 #, scheme-format msgid "unexpected content-type: ~s" msgstr "" -#: src/scm/webid-oidc/oidc-id-token.scm:72 +#: src/scm/webid-oidc/oidc-configuration.scm:187 +msgid "" +"when making an OIDC configuration, either its required #:jwks-uri, #:" +"authorization-endpoint and #:token-endpoint fields or #:server (and " +"optionally #:http-request) or #:json-data should be passed" +msgstr "" + +#: src/scm/webid-oidc/oidc-id-token.scm:71 #, scheme-format msgid "invalid OIDC ID token: ~a" msgstr "" -#: src/scm/webid-oidc/oidc-id-token.scm:74 +#: src/scm/webid-oidc/oidc-id-token.scm:73 msgid "invalid OIDC id token" msgstr "" -#: src/scm/webid-oidc/oidc-id-token.scm:105 +#: src/scm/webid-oidc/oidc-id-token.scm:104 msgid "#:sub should be a string" msgstr "" -#: src/scm/webid-oidc/oidc-id-token.scm:110 +#: src/scm/webid-oidc/oidc-id-token.scm:109 msgid "#:aud should be a string" msgstr "" -#: src/scm/webid-oidc/oidc-id-token.scm:126 +#: src/scm/webid-oidc/oidc-id-token.scm:125 msgid "" "when making an ID token either its required fields (#:alg, #:webid, #:iss, #:" "sub, #:aud, #:iat and #:exp) or (#:jwt-header and #:jwt-payload) should be " @@ -1854,63 +1845,63 @@ msgstr "" msgid "the refresh token is bound to key ~s, which is not that one" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:62 +#: src/scm/webid-oidc/resource-server.scm:61 msgid "" "You need to pass #:server-uri URI where URI is the public URI of the server, " "as a (web uri)." msgstr "" -#: src/scm/webid-oidc/resource-server.scm:89 +#: src/scm/webid-oidc/resource-server.scm:88 #, scheme-format msgid "~a: authentication failure: ~a\n" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:93 +#: src/scm/webid-oidc/resource-server.scm:92 #, scheme-format msgid "~a: authentication failure\n" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:172 -#: src/scm/webid-oidc/resource-server.scm:363 +#: src/scm/webid-oidc/resource-server.scm:171 +#: src/scm/webid-oidc/resource-server.scm:362 msgid "reason-phrase|Precondition Failed" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:187 +#: src/scm/webid-oidc/resource-server.scm:186 msgid "reason-phrase|Not Modified" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:203 +#: src/scm/webid-oidc/resource-server.scm:202 msgid "The owner is not defined." msgstr "" -#: src/scm/webid-oidc/resource-server.scm:275 +#: src/scm/webid-oidc/resource-server.scm:274 msgid "reason-phrase|Created" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:300 +#: src/scm/webid-oidc/resource-server.scm:299 #, scheme-format msgid "~a: ignoring a group that cannot be fetched: ~a\n" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:304 +#: src/scm/webid-oidc/resource-server.scm:303 #, scheme-format msgid "~a: ignoring a group that cannot be fetched\n" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:328 +#: src/scm/webid-oidc/resource-server.scm:327 #: src/scm/webid-oidc/token-endpoint.scm:105 msgid "reason-phrase|Forbidden" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:349 +#: src/scm/webid-oidc/resource-server.scm:348 msgid "reason-phrase|Conflict" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:356 +#: src/scm/webid-oidc/resource-server.scm:355 msgid "reason-phrase|Unsupported Media Type" msgstr "" -#: src/scm/webid-oidc/resource-server.scm:370 +#: src/scm/webid-oidc/resource-server.scm:369 msgid "reason-phrase|Not Acceptable" msgstr "" diff --git a/po/fr.po b/po/fr.po index a13197e..8d7727d 100644 --- a/po/fr.po +++ b/po/fr.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: webid-oidc 0.0.0\n" "Report-Msgid-Bugs-To: vivien@planete-kraus.eu\n" -"POT-Creation-Date: 2021-09-21 22:30+0200\n" -"PO-Revision-Date: 2021-09-21 22:30+0200\n" +"POT-Creation-Date: 2021-09-21 22:31+0200\n" +"PO-Revision-Date: 2021-09-21 22:33+0200\n" "Last-Translator: Vivien Kraus \n" "Language-Team: French \n" "Language: fr\n" @@ -126,34 +126,34 @@ msgstr "" "Le module aléatoire n'a pas été initialisé. Veuillez appeler " "webid_oidc_random_init d'abort.\n" -#: src/scm/webid-oidc/access-token.scm:73 +#: src/scm/webid-oidc/access-token.scm:72 #, scheme-format msgid "invalid access token: ~a" msgstr "jeton d’accès invalide : ~a" -#: src/scm/webid-oidc/access-token.scm:75 +#: src/scm/webid-oidc/access-token.scm:74 msgid "invalid access token" msgstr "jeton d’accès invalide" -#: src/scm/webid-oidc/access-token.scm:117 +#: src/scm/webid-oidc/access-token.scm:116 #: src/scm/webid-oidc/authorization-code.scm:93 -#: src/scm/webid-oidc/oidc-id-token.scm:100 +#: src/scm/webid-oidc/oidc-id-token.scm:99 msgid "#:webid should be an URI" msgstr "#:webid doit être une URI" -#: src/scm/webid-oidc/access-token.scm:122 +#: src/scm/webid-oidc/access-token.scm:121 msgid "#:client-id should be an URI" msgstr "#:client-id doit être une URI" -#: src/scm/webid-oidc/access-token.scm:127 +#: src/scm/webid-oidc/access-token.scm:126 msgid "#:cnf/jkt should be a string" msgstr "#:cnf/jkt doit être une chaîne de caractères" -#: src/scm/webid-oidc/access-token.scm:132 +#: src/scm/webid-oidc/access-token.scm:131 msgid "#:aud should be exactly \"solid\"" msgstr "#:aud doit être exactement « solid »" -#: src/scm/webid-oidc/access-token.scm:150 +#: src/scm/webid-oidc/access-token.scm:149 msgid "" "when making an access token either its required fields (#:alg, #:webid, #:" "iss, #:aud, #:client-id, #:cnf/jkt, #:iat and #:exp) or (#:jwt-header and #:" @@ -187,7 +187,7 @@ msgstr "" #: src/scm/webid-oidc/authorization-page-unsafe.scm:52 #: src/scm/webid-oidc/hello-world.scm:40 src/scm/webid-oidc/hello-world.scm:167 #: src/scm/webid-oidc/hello-world.scm:187 -#: src/scm/webid-oidc/identity-provider.scm:139 +#: src/scm/webid-oidc/identity-provider.scm:140 #: src/scm/webid-oidc/token-endpoint.scm:113 #: src/scm/webid-oidc/token-endpoint.scm:139 #: src/scm/webid-oidc/token-endpoint.scm:166 @@ -251,7 +251,7 @@ msgstr "" "L’application que vous essayez d’autoriser se comporte de façon inattendue." #: src/scm/webid-oidc/authorization-page-unsafe.scm:126 -#: src/scm/webid-oidc/resource-server.scm:311 +#: src/scm/webid-oidc/resource-server.scm:310 msgid "reason-phrase|Found" msgstr "Trouvé" @@ -458,12 +458,12 @@ msgstr "Le sujet doit être une chaîne de caractères ou une URI." msgid "The issuer should be a string or URI." msgstr "L’émetteur doit être une chaîne de caractères ou une URI." -#: src/scm/webid-oidc/client/application.scm:229 +#: src/scm/webid-oidc/client/application.scm:228 #, scheme-format msgid "Add an account on ~a" msgstr "Ajouter un compte sur ~a" -#: src/scm/webid-oidc/client/application.scm:244 +#: src/scm/webid-oidc/client/application.scm:243 #, scheme-format msgid "" "You already have an account for ~a issued by ~a and it is currently selected." @@ -471,12 +471,12 @@ msgstr "" "Vous avez déjà un compte pour ~a émis par ~a et il est actuellement " "sélectionné." -#: src/scm/webid-oidc/client/application.scm:263 +#: src/scm/webid-oidc/client/application.scm:262 #, scheme-format msgid "You already have an account for ~a issued by ~a." msgstr "Vous avez déjà un compte pour ~a émis par ~a." -#: src/scm/webid-oidc/client/client.scm:108 +#: src/scm/webid-oidc/client/client.scm:107 msgid "" "Client ID and redirect URIs should be URIs, and key pair should be a key " "pair.." @@ -484,11 +484,11 @@ msgstr "" "L’ID de client et l’URI de redirection doivent être des URIs, et la paire de " "clés doit être une paire de clés." -#: src/scm/webid-oidc/client/gui.scm:59 +#: src/scm/webid-oidc/client/gui.scm:58 msgid "Hello, world!\n" msgstr "Bonjour, le monde !\n" -#: src/scm/webid-oidc/client/gui.scm:64 +#: src/scm/webid-oidc/client/gui.scm:63 msgid "Hello, world!" msgstr "Bonjour, le monde !" @@ -906,7 +906,7 @@ msgid "The port should be a number between 0 and 65535.\n" msgstr "Le port doit être un nombre entre 0 et 65535.\n" #: src/scm/webid-oidc/hello-world.scm:159 -#: src/scm/webid-oidc/resource-server.scm:332 +#: src/scm/webid-oidc/resource-server.scm:331 msgid "reason-phrase|Unauthorized" msgstr "Non Autorisé" @@ -919,7 +919,7 @@ msgid "

This page requires authentication with Solid.

" msgstr "

Cette page requiert une authentification avec Solid.

" #: src/scm/webid-oidc/hello-world.scm:179 -#: src/scm/webid-oidc/resource-server.scm:340 +#: src/scm/webid-oidc/resource-server.scm:339 msgid "reason-phrase|Method Not Allowed" msgstr "Méthode Non Autorisée" @@ -933,11 +933,11 @@ msgstr "" "

Vous pouvez uniquement utiliser la méthode GET pour cette " "ressource.

" -#: src/scm/webid-oidc/identity-provider.scm:76 +#: src/scm/webid-oidc/identity-provider.scm:77 msgid "Warning: generating a new key pair." msgstr "Attention : génération d'une nouvelle paire de clé." -#: src/scm/webid-oidc/identity-provider.scm:132 +#: src/scm/webid-oidc/identity-provider.scm:133 msgid "reason-phrase|Not Found" msgstr "Non Trouvé" @@ -1104,127 +1104,123 @@ msgstr "" msgid "I cannot query the identity provider configuration" msgstr "je ne peux pas requêter la configuration du fournisseur d’identité" -#: src/scm/webid-oidc/jws.scm:505 +#: src/scm/webid-oidc/jws.scm:501 #, scheme-format msgid "I cannot query the JWKS URI of the identity provider: ~a" msgstr "je ne peux pas requêter l’URI de JWKS du fournisseur d’identité : ~a" -#: src/scm/webid-oidc/jws.scm:507 +#: src/scm/webid-oidc/jws.scm:503 msgid "I cannot query the JWKS URI of the identity provider" msgstr "impossible de requêter l’URI de JWKS du fournisseur d’identité" -#: src/scm/webid-oidc/jws.scm:535 +#: src/scm/webid-oidc/jws.scm:528 #, scheme-format msgid "the token is signed in the future, ~a, relative to current ~a" msgstr "" "le jeton est signé dans le futur, ~a, par rapport à la date courante, ~a" -#: src/scm/webid-oidc/jws.scm:544 +#: src/scm/webid-oidc/jws.scm:537 #, scheme-format msgid "the token expired ~a, which is in the past (from ~a)" msgstr "le jeton a expiré le ~a, qui est dans le passé (depuis ~a)" -#: src/scm/webid-oidc/jws.scm:567 +#: src/scm/webid-oidc/jws.scm:560 #, scheme-format msgid "cannot decode a JWS: ~a" msgstr "impossible de décoder un JWS : ~a" -#: src/scm/webid-oidc/jws.scm:569 +#: src/scm/webid-oidc/jws.scm:562 msgid "cannot decode a JWS" msgstr "impossible de décoder un JWS" -#: src/scm/webid-oidc/jws.scm:587 +#: src/scm/webid-oidc/jws.scm:580 #, scheme-format msgid "cannot encode a JWS: ~a" msgstr "impossible d’encoder un JWS : ~a" -#: src/scm/webid-oidc/jws.scm:589 +#: src/scm/webid-oidc/jws.scm:582 msgid "cannot encode a JWS" msgstr "impossible d’encoder un JWS" -#: src/scm/webid-oidc/jws.scm:636 +#: src/scm/webid-oidc/jws.scm:629 msgid "cannot parse a token" msgstr "impossible d’analyser le jeton" -#: src/scm/webid-oidc/oidc-configuration.scm:59 -#, scheme-format -msgid "the OIDC configuration is invalid: ~a" -msgstr "la configuration OIDC est invalide : ~a" - -#: src/scm/webid-oidc/oidc-configuration.scm:61 -msgid "the OIDC configuration is invalid" -msgstr "la configuration OIDC est invalide" - -#: src/scm/webid-oidc/oidc-configuration.scm:77 -#, scheme-format -msgid "the OIDC configuration does not have: ~s" -msgstr "il manque ~s à la configuration OIDC" +#: src/scm/webid-oidc/oidc-configuration.scm:120 +msgid "#:jwks-uri should be an URI" +msgstr "#:jwks-uri doit être une URI" -#: src/scm/webid-oidc/oidc-configuration.scm:92 -#, scheme-format -msgid "invalid JWKS URI: ~s" -msgstr "URI de JWKS invalide : ~s" - -#: src/scm/webid-oidc/oidc-configuration.scm:99 -#, scheme-format -msgid "invalid token endpoint: ~s" -msgstr "terminal de jeton invalide : ~s" +#: src/scm/webid-oidc/oidc-configuration.scm:125 +msgid "#:token-endpoint should be an URI" +msgstr "#:token-endpoint doit être une URI" -#: src/scm/webid-oidc/oidc-configuration.scm:108 -#, scheme-format -msgid "invalid authorization endpoint: ~s" -msgstr "terminal d’autorisation invalide : ~s" +#: src/scm/webid-oidc/oidc-configuration.scm:130 +msgid "#:authorization-endpoint should be an URI" +msgstr "#:authorization-endpoint doit être une URI" -#: src/scm/webid-oidc/oidc-configuration.scm:116 -#, scheme-format -msgid "\"solid_oidc_supported\" should be set to ~s, not ~s" -msgstr "« solid_oidc_supported » doit valoir ~s, pas ~s" +#: src/scm/webid-oidc/oidc-configuration.scm:135 +msgid "" +"#:solid-oidc-supported should be exactly 'https://solidproject.org/TR/solid-" +"oidc'" +msgstr "" +"#:solid-oidc-supported doit être exactement « https://solidproject.org/TR/" +"solid-oidc »" -#: src/scm/webid-oidc/oidc-configuration.scm:124 -msgid "invalid JSON object" -msgstr "objet JSON invalide" +#: src/scm/webid-oidc/oidc-configuration.scm:144 +msgid "#:server should be an URI" +msgstr "#:server doit être une URI" -#: src/scm/webid-oidc/oidc-configuration.scm:178 +#: src/scm/webid-oidc/oidc-configuration.scm:161 #, scheme-format msgid "cannot fetch the OIDC configuration: ~a" msgstr "impossible de télécharger la configuration OIDC : ~a" -#: src/scm/webid-oidc/oidc-configuration.scm:180 +#: src/scm/webid-oidc/oidc-configuration.scm:163 msgid "cannot fetch the OIDC configuration" msgstr "impossible de télécharger la configuration OIDC" -#: src/scm/webid-oidc/oidc-configuration.scm:188 +#: src/scm/webid-oidc/oidc-configuration.scm:167 #, scheme-format msgid "the server responded with ~s ~s" msgstr "le serveur a répondu ~s ~s" -#: src/scm/webid-oidc/oidc-configuration.scm:193 +#: src/scm/webid-oidc/oidc-configuration.scm:172 msgid "there is no content-type" msgstr "il n’y a pas de type de contenu" -#: src/scm/webid-oidc/oidc-configuration.scm:198 +#: src/scm/webid-oidc/oidc-configuration.scm:177 #, scheme-format msgid "unexpected content-type: ~s" msgstr "type de contenu inattendu : ~s" -#: src/scm/webid-oidc/oidc-id-token.scm:72 +#: src/scm/webid-oidc/oidc-configuration.scm:187 +msgid "" +"when making an OIDC configuration, either its required #:jwks-uri, #:" +"authorization-endpoint and #:token-endpoint fields or #:server (and " +"optionally #:http-request) or #:json-data should be passed" +msgstr "" +"pour construire une configuration OIDC, il faut soit définir les paramètres " +"requis #:jwks-uri, #:authorization-endpoint et #:token-endpoint, soit #:" +"server (et potentiellement #:http-request), soit #:json-data" + +#: src/scm/webid-oidc/oidc-id-token.scm:71 #, scheme-format msgid "invalid OIDC ID token: ~a" msgstr "jeton d’identité OIDC invalide : ~a" -#: src/scm/webid-oidc/oidc-id-token.scm:74 +#: src/scm/webid-oidc/oidc-id-token.scm:73 msgid "invalid OIDC id token" msgstr "jeton d’identité OIDC invalide" -#: src/scm/webid-oidc/oidc-id-token.scm:105 +#: src/scm/webid-oidc/oidc-id-token.scm:104 msgid "#:sub should be a string" msgstr "#:sub doit être une chaîne de caractères" -#: src/scm/webid-oidc/oidc-id-token.scm:110 +#: src/scm/webid-oidc/oidc-id-token.scm:109 msgid "#:aud should be a string" msgstr "#:aud doit être une chaîne de caractères" -#: src/scm/webid-oidc/oidc-id-token.scm:126 +#: src/scm/webid-oidc/oidc-id-token.scm:125 msgid "" "when making an ID token either its required fields (#:alg, #:webid, #:iss, #:" "sub, #:aud, #:iat and #:exp) or (#:jwt-header and #:jwt-payload) should be " @@ -2198,7 +2194,7 @@ msgid "the refresh token is bound to key ~s, which is not that one" msgstr "" "le jeton de rafraîchissement est lié à la clé ~s, ce n’est pas celle utilisée" -#: src/scm/webid-oidc/resource-server.scm:62 +#: src/scm/webid-oidc/resource-server.scm:61 msgid "" "You need to pass #:server-uri URI where URI is the public URI of the server, " "as a (web uri)." @@ -2206,57 +2202,57 @@ msgstr "" "Vous devez passer #:server-uri URI où URI est l’URI publique du serveur, " "comme dans (web uri)." -#: src/scm/webid-oidc/resource-server.scm:89 +#: src/scm/webid-oidc/resource-server.scm:88 #, scheme-format msgid "~a: authentication failure: ~a\n" msgstr "~a : échec d’authentificationn : ~a\n" -#: src/scm/webid-oidc/resource-server.scm:93 +#: src/scm/webid-oidc/resource-server.scm:92 #, scheme-format msgid "~a: authentication failure\n" msgstr "~a : échec d’authentification\n" -#: src/scm/webid-oidc/resource-server.scm:172 -#: src/scm/webid-oidc/resource-server.scm:363 +#: src/scm/webid-oidc/resource-server.scm:171 +#: src/scm/webid-oidc/resource-server.scm:362 msgid "reason-phrase|Precondition Failed" msgstr "Échec de Précondition" -#: src/scm/webid-oidc/resource-server.scm:187 +#: src/scm/webid-oidc/resource-server.scm:186 msgid "reason-phrase|Not Modified" msgstr "Non Modifié" -#: src/scm/webid-oidc/resource-server.scm:203 +#: src/scm/webid-oidc/resource-server.scm:202 msgid "The owner is not defined." msgstr "Le propriétaire n’est pas défini." -#: src/scm/webid-oidc/resource-server.scm:275 +#: src/scm/webid-oidc/resource-server.scm:274 msgid "reason-phrase|Created" msgstr "Créé" -#: src/scm/webid-oidc/resource-server.scm:300 +#: src/scm/webid-oidc/resource-server.scm:299 #, scheme-format msgid "~a: ignoring a group that cannot be fetched: ~a\n" msgstr "~a : j’ignore un groupe qui n’a pas pu être téléchargé : ~a\n" -#: src/scm/webid-oidc/resource-server.scm:304 +#: src/scm/webid-oidc/resource-server.scm:303 #, scheme-format msgid "~a: ignoring a group that cannot be fetched\n" msgstr "~a : j’ignore un groupe qui ne peut pas être téléchargé\n" -#: src/scm/webid-oidc/resource-server.scm:328 +#: src/scm/webid-oidc/resource-server.scm:327 #: src/scm/webid-oidc/token-endpoint.scm:105 msgid "reason-phrase|Forbidden" msgstr "Interdit" -#: src/scm/webid-oidc/resource-server.scm:349 +#: src/scm/webid-oidc/resource-server.scm:348 msgid "reason-phrase|Conflict" msgstr "Conflit" -#: src/scm/webid-oidc/resource-server.scm:356 +#: src/scm/webid-oidc/resource-server.scm:355 msgid "reason-phrase|Unsupported Media Type" msgstr "Type de Média Non Supporté" -#: src/scm/webid-oidc/resource-server.scm:370 +#: src/scm/webid-oidc/resource-server.scm:369 msgid "reason-phrase|Not Acceptable" msgstr "Inacceptable" @@ -2388,6 +2384,36 @@ msgstr "" "

Vous voulez utiliser

~s
comme type d’offre, mais ce n’est pas " "supporté.

" +#, scheme-format +#~ msgid "the OIDC configuration is invalid: ~a" +#~ msgstr "la configuration OIDC est invalide : ~a" + +#~ msgid "the OIDC configuration is invalid" +#~ msgstr "la configuration OIDC est invalide" + +#, scheme-format +#~ msgid "the OIDC configuration does not have: ~s" +#~ msgstr "il manque ~s à la configuration OIDC" + +#, scheme-format +#~ msgid "invalid JWKS URI: ~s" +#~ msgstr "URI de JWKS invalide : ~s" + +#, scheme-format +#~ msgid "invalid token endpoint: ~s" +#~ msgstr "terminal de jeton invalide : ~s" + +#, scheme-format +#~ msgid "invalid authorization endpoint: ~s" +#~ msgstr "terminal d’autorisation invalide : ~s" + +#, scheme-format +#~ msgid "\"solid_oidc_supported\" should be set to ~s, not ~s" +#~ msgstr "« solid_oidc_supported » doit valoir ~s, pas ~s" + +#~ msgid "invalid JSON object" +#~ msgstr "objet JSON invalide" + #, scheme-format #~ msgid "this is not an access token, because it is not even a JWS: ~a" #~ msgstr "" diff --git a/src/scm/webid-oidc/access-token.scm b/src/scm/webid-oidc/access-token.scm index 7c23126..0960069 100644 --- a/src/scm/webid-oidc/access-token.scm +++ b/src/scm/webid-oidc/access-token.scm @@ -18,7 +18,6 @@ #:use-module (webid-oidc jws) #:use-module (webid-oidc errors) #:use-module (webid-oidc jwk) - #:use-module (webid-oidc oidc-configuration) #:use-module (webid-oidc web-i18n) #:use-module ((webid-oidc stubs) #:prefix stubs:) #:use-module ((webid-oidc parameters) #:prefix p:) diff --git a/src/scm/webid-oidc/client.scm b/src/scm/webid-oidc/client.scm index 006c86a..2c16fb1 100644 --- a/src/scm/webid-oidc/client.scm +++ b/src/scm/webid-oidc/client.scm @@ -17,7 +17,6 @@ (define-module (webid-oidc client) #:use-module (webid-oidc errors) #:use-module (webid-oidc provider-confirmation) - #:use-module (webid-oidc oidc-configuration) #:use-module (webid-oidc oidc-id-token) #:use-module (webid-oidc dpop-proof) #:use-module (webid-oidc jwk) diff --git a/src/scm/webid-oidc/client/accounts.scm b/src/scm/webid-oidc/client/accounts.scm index 3591b52..7e14000 100644 --- a/src/scm/webid-oidc/client/accounts.scm +++ b/src/scm/webid-oidc/client/accounts.scm @@ -31,7 +31,7 @@ #:use-module ((webid-oidc parameters) #:prefix p:) #:use-module ((webid-oidc stubs) #:prefix stubs:) #:use-module ((webid-oidc oidc-id-token) #:prefix id:) - #:use-module ((webid-oidc oidc-configuration) #:prefix cfg:) + #:use-module (webid-oidc oidc-configuration) #:use-module ((webid-oidc jwk) #:prefix jwk:) #:use-module (webid-oidc dpop-proof) #:use-module ((webid-oidc client client) #:prefix client:) @@ -41,6 +41,10 @@ #:use-module (rnrs bytevectors) #:use-module (oop goops) #:declarative? #t + #:re-export + ( + (p:anonymous-http-request . anonymous-http-request) + ) #:export ( @@ -58,7 +62,6 @@ authorization-process authorization-state - anonymous-http-request &authorization-code-required make-authorization-code-required @@ -129,15 +132,12 @@ (define authorization-state (make-parameter #f)) -(define anonymous-http-request - (make-parameter http-request)) - (define (http-request->http-get http-request) (lambda* (uri . all-args) (apply http-request uri #:method 'GET all-args))) (define (http-get-implementation) - (http-request->http-get (anonymous-http-request))) + (http-request->http-get (p:anonymous-http-request))) (define-class () (subject #:init-keyword #:subject #:getter subject) @@ -157,13 +157,16 @@ (define-method (->sexp (account )) `(begin - (use-modules (oop goops) (webid-oidc client accounts) (webid-oidc jwk)) + (use-modules (oop goops) (webid-oidc client accounts) (webid-oidc jwk) (webid-oidc jws) (webid-oidc oidc-id-token)) (make #:subject ,(uri->string (subject account)) #:issuer ,(uri->string (issuer account)) ,@(let ((id-token (id-token account))) (if id-token - `(#:id-token (quote ,id-token)) + (receive (header payload) (token->jwk id-token) + `(#:id-token (make + #:jws-header (quote ,header) + #:jws-payload (quote ,payload)))) '())) ,@(let ((access-token (access-token account))) (if access-token @@ -217,14 +220,11 @@ (let ((client (client:client))) (receive (authorization-endpoint token-endpoint) (let ((configuration - (cfg:get-oidc-configuration - (uri-host issuer) - #:userinfo (uri-userinfo issuer) - #:port (uri-port issuer) - #:http-get (http-get-implementation)))) + (make + #:server issuer))) (values - (cfg:oidc-configuration-authorization-endpoint configuration) - (cfg:oidc-configuration-token-endpoint configuration))) + (authorization-endpoint configuration) + (token-endpoint configuration))) (receive (grant-type grant) (if refresh-token (values "refresh_token" refresh-token) @@ -261,7 +261,7 @@ #:htm 'POST #:htu token-endpoint))) (receive (response response-body) - ((anonymous-http-request) token-endpoint + ((p:anonymous-http-request) token-endpoint #:method 'POST #:body (string-join @@ -372,7 +372,7 @@ (lambda () (set! id-token (decode id-token - #:http-request (anonymous-http-request))))) + #:http-request (p:anonymous-http-request))))) ;; We are not interested in the ID token ;; signature anymore, because it won’t be ;; transmitted to other parties and we know that diff --git a/src/scm/webid-oidc/client/application.scm b/src/scm/webid-oidc/client/application.scm index 74fcefe..5839195 100644 --- a/src/scm/webid-oidc/client/application.scm +++ b/src/scm/webid-oidc/client/application.scm @@ -31,7 +31,6 @@ #:use-module ((webid-oidc parameters) #:prefix p:) #:use-module ((webid-oidc stubs) #:prefix stubs:) #:use-module ((webid-oidc oidc-id-token) #:prefix id:) - #:use-module ((webid-oidc oidc-configuration) #:prefix cfg:) #:use-module ((webid-oidc jwk) #:prefix jwk:) #:use-module ((webid-oidc dpop-proof) #:prefix dpop:) #:use-module ((webid-oidc client client) #:prefix client:) diff --git a/src/scm/webid-oidc/client/client.scm b/src/scm/webid-oidc/client/client.scm index 5da701b..01f8da1 100644 --- a/src/scm/webid-oidc/client/client.scm +++ b/src/scm/webid-oidc/client/client.scm @@ -17,7 +17,6 @@ (define-module (webid-oidc client client) #:use-module (webid-oidc errors) #:use-module (webid-oidc provider-confirmation) - #:use-module (webid-oidc oidc-configuration) #:use-module (webid-oidc oidc-id-token) #:use-module (webid-oidc dpop-proof) #:use-module (webid-oidc web-i18n) diff --git a/src/scm/webid-oidc/client/gui.scm b/src/scm/webid-oidc/client/gui.scm index 3bfaf6a..c0d0767 100644 --- a/src/scm/webid-oidc/client/gui.scm +++ b/src/scm/webid-oidc/client/gui.scm @@ -31,7 +31,6 @@ #:use-module ((webid-oidc parameters) #:prefix p:) #:use-module ((webid-oidc stubs) #:prefix stubs:) #:use-module ((webid-oidc oidc-id-token) #:prefix id:) - #:use-module ((webid-oidc oidc-configuration) #:prefix cfg:) #:use-module ((webid-oidc jwk) #:prefix jwk:) #:use-module ((webid-oidc dpop-proof) #:prefix dpop:) #:use-module ((webid-oidc client client) #:prefix client:) diff --git a/src/scm/webid-oidc/identity-provider.scm b/src/scm/webid-oidc/identity-provider.scm index 7973917..46de33c 100644 --- a/src/scm/webid-oidc/identity-provider.scm +++ b/src/scm/webid-oidc/identity-provider.scm @@ -42,6 +42,7 @@ #:use-module (srfi srfi-19) #:use-module (rnrs bytevectors) #:use-module (oop goops) + #:duplicates (merge-generics) #:declarative? #t #:export ( @@ -86,10 +87,10 @@ (token-endpoint (make-token-endpoint token-endpoint-uri issuer key 3600)) (openid-configuration - `((jwks_uri . ,(uri->string jwks-uri)) - (authorization_endpoint . ,(uri->string authorization-endpoint-uri)) - (token_endpoint . ,(uri->string token-endpoint-uri)) - (solid_oidc_supported . "https://solidproject.org/TR/solid-oidc"))) + (make + #:jwks-uri jwks-uri + #:authorization-endpoint authorization-endpoint-uri + #:token-endpoint token-endpoint-uri)) (openid-configuration-uri (build-uri 'https #:host (uri-host issuer) @@ -103,7 +104,7 @@ (exp-sec (+ current-sec 3600)) (exp (time-utc->date (make-time time-utc 0 exp-sec)))) - (serve-oidc-configuration exp openid-configuration))) + (serve openid-configuration exp))) ((same-uri? uri jwks-uri) (let* ((current-sec (time-second (date->time-utc current-time))) (exp-sec (+ current-sec 3600)) diff --git a/src/scm/webid-oidc/jws.scm b/src/scm/webid-oidc/jws.scm index 22dabdd..bfb941f 100644 --- a/src/scm/webid-oidc/jws.scm +++ b/src/scm/webid-oidc/jws.scm @@ -472,7 +472,7 @@ (define-method (lookup-keys (token ) args) (let-keywords args #f - ((http-request http-request)) + ((http-request (p:anonymous-http-request))) (let ((iss (iss token))) (let ((cfg (with-exception-handler @@ -488,13 +488,9 @@ (make-exception-with-message final-message) error)))) (lambda () - (get-oidc-configuration - (uri-host iss) - #:userinfo (uri-userinfo iss) - #:port (uri-port iss) - #:http-get - (lambda* (uri . args) - (apply http-request uri #:method 'GET args))))))) + (make + #:server iss + #:http-request http-request))))) (with-exception-handler (lambda (error) (raise-exception @@ -509,11 +505,8 @@ (append (keys (next-method)) (keys - (oidc-configuration-jwks - cfg - #:http-get - (lambda* (uri . args) - (apply http-request uri #:method 'GET args))))))))))) + (parameterize ((p:anonymous-http-request http-request)) + (jwks cfg)))))))))) (define verify (make diff --git a/src/scm/webid-oidc/oidc-configuration.scm b/src/scm/webid-oidc/oidc-configuration.scm index 2233d95..0a776d1 100644 --- a/src/scm/webid-oidc/oidc-configuration.scm +++ b/src/scm/webid-oidc/oidc-configuration.scm @@ -19,6 +19,7 @@ #:use-module (webid-oidc errors) #:use-module (webid-oidc web-i18n) #:use-module ((webid-oidc stubs) #:prefix stubs:) + #:use-module ((webid-oidc parameters) #:prefix p:) #:use-module (web uri) #:use-module (web client) #:use-module (web response) @@ -28,6 +29,7 @@ #:use-module (ice-9 optargs) #:use-module (ice-9 exceptions) #:use-module (ice-9 match) + #:use-module (oop goops) #:declarative? #t #:export ( @@ -35,14 +37,14 @@ make-invalid-oidc-configuratioon invalid-oidc-configuration? - the-oidc-configuration - oidc-configuration? - oidc-configuration-jwks-uri - oidc-configuration-authorization-endpoint - oidc-configuration-token-endpoint - oidc-configuration-jwks - serve-oidc-configuration - get-oidc-configuration + + jwks-uri + authorization-endpoint + token-endpoint + jwks + serve + + ->json-data )) (define-exception-type @@ -51,152 +53,149 @@ make-invalid-oidc-configuration invalid-oidc-configuration?) -(define (the-oidc-configuration x) - (with-exception-handler - (lambda (error) - (let ((final-message - (if (exception-with-message? error) - (format #f (G_ "the OIDC configuration is invalid: ~a") - (exception-message error)) - (format #f (G_ "the OIDC configuration is invalid"))))) - (raise-exception - (make-exception - (make-invalid-oidc-configuration) - (make-exception-with-message final-message) - error)))) - (lambda () - (let examine ((data x) - (jwks-uri #f) - (token-endpoint #f) - (authorization-endpoint #f) - (solid-oidc-supported #f) - (other-fields '())) - (match data - (() - (unless (and jwks-uri token-endpoint authorization-endpoint solid-oidc-supported) - (fail (format #f (G_ "the OIDC configuration does not have: ~s") - `(,@(if jwks-uri '() '("jwks_uri")) - ,@(if token-endpoint '() '("token_endpoint")) - ,@(if authorization-endpoint '() '("authorization_endpoint")) - ,@(if solid-oidc-supported '() '("solid_oidc_supported")))))) - `((jwks_uri . ,(uri->string jwks-uri)) - (token_endpoint . ,(uri->string token-endpoint)) - (authorization_endpoint . ,(uri->string authorization-endpoint)) - (solid_oidc_supported . "https://solidproject.org/TR/solid-oidc") - ,@(reverse other-fields))) - ((('jwks_uri . (? string->uri (? string? given-jwks-uri))) data ...) - (examine data (or jwks-uri (string->uri given-jwks-uri)) - token-endpoint authorization-endpoint - solid-oidc-supported other-fields)) - ((('jwks_uri . invalid) data ...) - (fail (format #f (G_ "invalid JWKS URI: ~s") - invalid))) - ((('token_endpoint . (? string->uri (? string? given-token-endpoint))) data ...) - (examine data jwks-uri - (or token-endpoint (string->uri given-token-endpoint)) - authorization-endpoint solid-oidc-supported other-fields)) - ((('token_endpoint . invalid) data ...) - (fail (format #f (G_ "invalid token endpoint: ~s") - invalid))) - ((('authorization_endpoint - . (? string->uri (? string? given-authorization-endpoint))) - data ...) - (examine data jwks-uri token-endpoint - (or authorization-endpoint (string->uri given-authorization-endpoint)) - solid-oidc-supported other-fields)) - ((('authorization_endpoint . invalid) data ...) - (fail (format #f (G_ "invalid authorization endpoint: ~s") - invalid))) - ((('solid_oidc_supported . "https://solidproject.org/TR/solid-oidc") - data ...) - (examine data jwks-uri token-endpoint authorization-endpoint - (or solid-oidc-supported #t) - other-fields)) - ((('solid_oidc_supported . incorrect) data ...) - (fail (format #f (G_ "\"solid_oidc_supported\" should be set to ~s, not ~s") - "https://solidproject.org/TR/solid-oidc" - incorrect))) - ((((? symbol? key) . value) data ...) - (examine data jwks-uri token-endpoint authorization-endpoint - solid-oidc-supported - `((,key . ,value) ,@other-fields))) - (else - (fail (format #f (G_ "invalid JSON object"))))))))) - -(define (oidc-configuration? obj) - (false-if-exception - (the-oidc-configuration obj))) - -(define (uri-field what) - (lambda (x) - (let ((str (assq-ref (the-oidc-configuration x) what))) - (string->uri str)))) - -(define oidc-configuration-jwks-uri - (uri-field 'jwks_uri)) - -(define oidc-configuration-authorization-endpoint - (uri-field 'authorization_endpoint)) +(define-class () + (jwks-uri #:init-keyword #:jwks-uri #:accessor jwks-uri) + (authorization-endpoint #:init-keyword #:authorization-endpoint #:accessor authorization-endpoint) + (token-endpoint #:init-keyword #:token-endpoint #:accessor token-endpoint)) -(define oidc-configuration-token-endpoint - (uri-field 'token_endpoint)) +(define-method (initialize (cfg ) initargs) + (next-method) + (let-keywords + initargs #t + ((jwks-uri #f) + (authorization-endpoint #f) + (token-endpoint #f) + (solid-oidc-supported "https://solidproject.org/TR/solid-oidc") + (json-data #f) + (server #f) + (http-request (p:anonymous-http-request))) + (let do-initialize ((jwks-uri jwks-uri) + (authorization-endpoint authorization-endpoint) + (token-endpoint token-endpoint) + (solid-oidc-supported solid-oidc-supported) + (json-data json-data) + (server server)) + (cond + ((string? jwks-uri) + (do-initialize (string->uri jwks-uri) + authorization-endpoint + token-endpoint + solid-oidc-supported + json-data + server)) + ((string? authorization-endpoint) + (do-initialize jwks-uri + (string->uri authorization-endpoint) + token-endpoint + solid-oidc-supported + json-data + server)) + ((string? token-endpoint) + (do-initialize jwks-uri + authorization-endpoint + (string->uri token-endpoint) + solid-oidc-supported + json-data + server)) + ((string? server) + ;; Either it is an URI, or it is a host name + (do-initialize jwks-uri + authorization-endpoint + token-endpoint + solid-oidc-supported + json-data + (or (false-if-exception (string->uri server)) + (false-if-exception + (build-uri 'https #:host server))))) + (json-data + (do-initialize (assq-ref json-data 'jwks_uri) + (assq-ref json-data 'authorization_endpoint) + (assq-ref json-data 'token_endpoint) + (assq-ref json-data 'solid_oidc_supported) + #f #f)) + ((and jwks-uri authorization-endpoint token-endpoint solid-oidc-supported) + (begin + (unless (uri? jwks-uri) + (scm-error 'wrong-type-arg "make" + (G_ "#:jwks-uri should be an URI") + '() + (list jwks-uri))) + (unless (uri? token-endpoint) + (scm-error 'wrong-type-arg "make" + (G_ "#:token-endpoint should be an URI") + '() + (list token-endpoint))) + (unless (uri? authorization-endpoint) + (scm-error 'wrong-type-arg "make" + (G_ "#:authorization-endpoint should be an URI") + '() + (list authorization-endpoint))) + (unless (equal? solid-oidc-supported "https://solidproject.org/TR/solid-oidc") + (scm-error 'wrong-type-arg "make" + (G_ "#:solid-oidc-supported should be exactly 'https://solidproject.org/TR/solid-oidc'") + '() + (list solid-oidc-supported))) + (slot-set! cfg 'jwks-uri jwks-uri) + (slot-set! cfg 'token-endpoint token-endpoint) + (slot-set! cfg 'authorization-endpoint authorization-endpoint))) + (server + (unless (uri? server) + (scm-error 'wrong-type-arg "make" + (G_ "#:server should be an URI") + '() + (list server))) + (let ((discovery-uri + (build-uri (uri-scheme server) + #:userinfo (uri-userinfo server) + #:host (uri-host server) + #:port (uri-port server) + #:path "/.well-known/openid-configuration"))) + (receive (response response-body) (http-request discovery-uri) + (with-exception-handler + (lambda (error) + (raise-exception + (make-exception + (make-invalid-oidc-configuration) + (make-exception-with-message + (if (exception-with-message? error) + (format #f (G_ "cannot fetch the OIDC configuration: ~a") + (exception-message error)) + (format #f (G_ "cannot fetch the OIDC configuration")))) + error))) + (lambda () + (unless (eqv? (response-code response) 200) + (fail (format #f (G_ "the server responded with ~s ~s") + (response-code response) + (response-reason-phrase response)))) + (let ((content-type (response-content-type response))) + (unless content-type + (fail (format #f (G_ "there is no content-type")))) + (unless (and (eq? (car content-type) 'application/json) + (or (equal? (assoc-ref (cdr content-type) 'charset) + "utf-8") + (not (assoc-ref (cdr content-type) 'charset)))) + (fail (format #f (G_ "unexpected content-type: ~s") + content-type))) + (unless (string? response-body) + (set! response-body (utf8->string response-body))) + (do-initialize #f #f #f #f (stubs:json-string->scm response-body) #f))))))) + (else + (raise-exception + (make-exception + (make-invalid-oidc-configuratin) + (make-exception-with-message + (G_ "when making an OIDC configuration, either its required #:jwks-uri, #:authorization-endpoint and #:token-endpoint fields or #:server (and optionally #:http-request) or #:json-data should be passed"))))))))) -(define* (oidc-configuration-jwks cfg #:key (http-get http-get)) - (let ((http-request-for-get-jwks - (lambda* (uri #:key (method 'GET)) - (http-get uri)))) - (get-jwks (oidc-configuration-jwks-uri cfg) - #:http-request http-request-for-get-jwks))) +(define-method (->json-data (cfg )) + `((jwks_uri . ,(uri->string (jwks-uri cfg))) + (authorization_endpoint . ,(uri->string (authorization-endpoint cfg))) + (token_endpoint . ,(uri->string (token-endpoint cfg))) + (solid_oidc_supported . "https://solidproject.org/TR/solid-oidc"))) -(define (serve-oidc-configuration expiration-date cfg) +(define-method (serve (cfg ) expiration-date) (values (build-response #:headers `((content-type . (application/json)) (expires . ,expiration-date))) - (stubs:scm->json-string cfg))) + (stubs:scm->json-string (->json-data cfg)))) -(define* (get-oidc-configuration host - #:key - (userinfo #f) - (port #f) - (http-get http-get)) - (when (and (string? host) - (false-if-exception - (string->uri host))) - ;; host is something like "https://example.com" - (set! host (string->uri host))) - (when (uri? host) - (set! host (uri-host host))) - (let ((uri (build-uri 'https - #:userinfo userinfo - #:host host - #:port port - #:path "/.well-known/openid-configuration"))) - (receive (response response-body) (http-get uri) - (with-exception-handler - (lambda (error) - (let ((final-message - (if (exception-with-message? error) - (format #f (G_ "cannot fetch the OIDC configuration: ~a") - (exception-message error)) - (format #f (G_ "cannot fetch the OIDC configuration"))))) - (raise-exception - (make-exception - (make-invalid-oidc-configuration) - (make-exception-with-message final-message) - error)))) - (lambda () - (unless (eqv? (response-code response) 200) - (fail (format #f (G_ "the server responded with ~s ~s") - (response-code response) - (response-reason-phrase response)))) - (let ((content-type (response-content-type response))) - (unless content-type - (fail (format #f (G_ "there is no content-type")))) - (unless (and (eq? (car content-type) 'application/json) - (or (equal? (assoc-ref (cdr content-type) 'charset) - "utf-8") - (not (assoc-ref (cdr content-type) 'charset)))) - (fail (format #f (G_ "unexpected content-type: ~s") - content-type))) - (unless (string? response-body) - (set! response-body (utf8->string response-body))) - (the-oidc-configuration (stubs:json-string->scm response-body)))))))) +(define-method (jwks (cfg )) + (get-jwks (jwks-uri cfg) #:http-request (p:anonymous-http-request))) diff --git a/src/scm/webid-oidc/oidc-id-token.scm b/src/scm/webid-oidc/oidc-id-token.scm index 1d96a47..a33351b 100644 --- a/src/scm/webid-oidc/oidc-id-token.scm +++ b/src/scm/webid-oidc/oidc-id-token.scm @@ -15,7 +15,6 @@ ;; along with this program. If not, see . (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 jwk) diff --git a/src/scm/webid-oidc/parameters.scm b/src/scm/webid-oidc/parameters.scm index 603a2cd..7d10798 100644 --- a/src/scm/webid-oidc/parameters.scm +++ b/src/scm/webid-oidc/parameters.scm @@ -16,8 +16,8 @@ (define-module (webid-oidc parameters) #:use-module (srfi srfi-19) - #:use-module (webid-oidc jti) - #:export (data-home cache-home current-date) + #:use-module (web client) + #:export (data-home cache-home current-date anonymous-http-request) #:declarative? #t) (define data-home @@ -49,3 +49,6 @@ (when (time? date) (set! date (time-utc->date date))) date))))) + +(define anonymous-http-request + (make-parameter http-request)) diff --git a/src/scm/webid-oidc/resource-server.scm b/src/scm/webid-oidc/resource-server.scm index 99291b0..bae9db9 100644 --- a/src/scm/webid-oidc/resource-server.scm +++ b/src/scm/webid-oidc/resource-server.scm @@ -16,7 +16,6 @@ (define-module (webid-oidc resource-server) #:use-module (webid-oidc errors) - #:use-module (webid-oidc oidc-configuration) #:use-module (webid-oidc provider-confirmation) #:use-module (webid-oidc jwk) #:use-module (webid-oidc dpop-proof) diff --git a/tests/client-workflow.scm b/tests/client-workflow.scm index b0c0c2f..50514d8 100644 --- a/tests/client-workflow.scm +++ b/tests/client-workflow.scm @@ -14,24 +14,26 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see . -(use-modules ((webid-oidc client) #:prefix client:) - ((webid-oidc client accounts) #:prefix client:) - ((webid-oidc jwk) #:prefix jwk:) - (webid-oidc testing) - ((webid-oidc stubs) #:prefix stubs:) - ((webid-oidc refresh-token) #:prefix refresh:) - ((webid-oidc simulation) #:prefix sim:) - ((webid-oidc parameters) #:prefix p:) - (web uri) - (web request) - (web response) - (srfi srfi-19) - (srfi srfi-26) - (ice-9 optargs) - (ice-9 receive) - (ice-9 hash-table) - (ice-9 match) - (oop goops)) +(define-module (tests client-workflow) + #:use-module ((webid-oidc client) #:prefix client:) + #:use-module ((webid-oidc client accounts) #:prefix client:) + #:use-module ((webid-oidc jwk) #:prefix jwk:) + #:use-module (webid-oidc testing) + #:use-module ((webid-oidc stubs) #:prefix stubs:) + #:use-module ((webid-oidc refresh-token) #:prefix refresh:) + #:use-module ((webid-oidc simulation) #:prefix sim:) + #:use-module ((webid-oidc parameters) #:prefix p:) + #:use-module (web uri) + #:use-module (web request) + #:use-module (web response) + #:use-module (srfi srfi-19) + #:use-module (srfi srfi-26) + #:use-module (ice-9 optargs) + #:use-module (ice-9 receive) + #:use-module (ice-9 hash-table) + #:use-module (ice-9 match) + #:use-module (oop goops) + #:duplicates (merge-generics)) ;; In this example, a user firsts requests an account, then logs in ;; with a refresh token, then logs out, but we can still revive per diff --git a/tests/oidc-configuration.scm b/tests/oidc-configuration.scm index 7f76280..736c3f8 100644 --- a/tests/oidc-configuration.scm +++ b/tests/oidc-configuration.scm @@ -14,16 +14,19 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see . -(use-modules (webid-oidc oidc-configuration) - (webid-oidc jwk) - (webid-oidc cache) - (webid-oidc testing) - ((webid-oidc stubs) #:prefix stubs:) - (web uri) - (web response) - (srfi srfi-19) - (ice-9 receive) - (oop goops)) +(define-module (tests oidc-configuration) + #:use-module (webid-oidc oidc-configuration) + #:use-module (webid-oidc jwk) + #:use-module (webid-oidc cache) + #:use-module (webid-oidc testing) + #:use-module ((webid-oidc stubs) #:prefix stubs:) + #:use-module ((webid-oidc parameters) #:prefix p:) + #:use-module (web uri) + #:use-module (web response) + #:use-module (srfi srfi-19) + #:use-module (ice-9 receive) + #:use-module (oop goops) + #:duplicates (merge-generics)) (with-test-environment "oidc-configuration" @@ -120,26 +123,31 @@ (define cache-http-get (with-cache #:http-get respond)) - (define cfg (get-oidc-configuration - "example.com" - #:http-get cache-http-get)) - (define jwks (oidc-configuration-jwks - cfg - #:http-get cache-http-get)) - (unless (oidc-configuration? cfg) + (define cfg + (make + #:server "example.com" + #:http-request cache-http-get)) + (define my-jwks + (parameterize ((p:anonymous-http-request cache-http-get)) + (jwks cfg))) + (unless (is-a? cfg ) (exit 3)) - (unless (is-a? jwks ) + (unless (is-a? my-jwks ) (exit 4)) - (let ((my-oidc `((jwks_uri . "https://example.com/keys") - (authorization_endpoint . "https://example.com/authorize") - (token_endpoint . "https://example.com/token") - (solid_oidc_supported . "https://solidproject.org/TR/solid-oidc")))) + (let ((my-oidc + (make + #:jwks-uri "https://example.com/keys" + #:authorization-endpoint "https://example.com/authorize" + #:token-endpoint "https://example.com/token" + #:solid-oidc-supported "https://solidproject.org/TR/solid-oidc"))) (receive (response response-body) - (serve-oidc-configuration (time-utc->date (make-time time-utc 0 3600)) - my-oidc) + (serve my-oidc (time-utc->date (make-time time-utc 0 3600))) (unless (eqv? (car (response-content-type response)) 'application/json) (exit 5)) - (let ((parsed (the-oidc-configuration (stubs:json-string->scm response-body)))) + (let ((parsed + (->json-data + (make + #:json-data (stubs:json-string->scm response-body))))) (unless (equal? (assq-ref parsed 'jwks_uri) "https://example.com/keys") (exit 7)) diff --git a/tests/resource-server.scm b/tests/resource-server.scm index a8032b1..89df999 100644 --- a/tests/resource-server.scm +++ b/tests/resource-server.scm @@ -14,23 +14,25 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see . -(use-modules (webid-oidc provider-confirmation) - (webid-oidc jti) - (webid-oidc jwk) - (webid-oidc jws) - (webid-oidc oidc-configuration) - (webid-oidc access-token) - (webid-oidc dpop-proof) - (webid-oidc resource-server) - (webid-oidc testing) - ((webid-oidc parameters) #:prefix p:) - (web uri) - (web request) - (srfi srfi-19) - (web response) - (ice-9 optargs) - (ice-9 receive) - (oop goops)) +(define-module (tests resource-server) + #:use-module (webid-oidc provider-confirmation) + #:use-module (webid-oidc jti) + #:use-module (webid-oidc jwk) + #:use-module (webid-oidc jws) + #:use-module (webid-oidc oidc-configuration) + #:use-module (webid-oidc access-token) + #:use-module (webid-oidc dpop-proof) + #:use-module (webid-oidc resource-server) + #:use-module (webid-oidc testing) + #:use-module ((webid-oidc parameters) #:prefix p:) + #:use-module (web uri) + #:use-module (web request) + #:use-module (srfi srfi-19) + #:use-module (web response) + #:use-module (ice-9 optargs) + #:use-module (ice-9 receive) + #:use-module (oop goops) + #:duplicates (merge-generics)) (with-test-environment "resource-server" @@ -40,10 +42,11 @@ (define jwks (make #:keys (list idp-key))) (define jwks-uri (string->uri "https://identity.provider/keys")) (define oidc-config - `((jwks_uri . ,(uri->string jwks-uri)) - (authorization_endpoint . "https://identity.provider/authorize") - (token_endpoint . "https://identity.provider/token") - (solid_oidc_supported . "https://solidproject.org/TR/solid-oidc"))) + (make + #:jwks-uri jwks-uri + #:authorization-endpoint "https://identity.provider/authorize" + #:token-endpoint "https://identity.provider/token" + #:solid-oidc-supported "https://solidproject.org/TR/solid-oidc")) (define oidc-config-uri (string->uri "https://identity.provider/.well-known/openid-configuration")) @@ -51,7 +54,7 @@ (define* (http-get uri #:key (headers '())) (define exp (time-utc->date (make-time time-utc 0 3600))) (cond ((equal? uri oidc-config-uri) - (serve-oidc-configuration exp oidc-config)) + (serve oidc-config exp)) ((equal? uri jwks-uri) (serve jwks exp)) (else (exit 1)))) -- cgit v1.2.3