diff options
author | Vivien Kraus <vivien@planete-kraus.eu> | 2021-10-17 14:52:14 +0200 |
---|---|---|
committer | Vivien Kraus <vivien@planete-kraus.eu> | 2021-10-21 09:45:14 +0200 |
commit | 1dc4802d231bf4083d387a6db0765730075cc752 (patch) | |
tree | 1dde8889f49ebeb7652d89bd1af8428480532201 /tests | |
parent | 7debf052567f50d2c2510d80405069e53b0971bf (diff) |
Use the endpoint API
Diffstat (limited to 'tests')
-rw-r--r-- | tests/authorization-endpoint-get-form.scm | 49 | ||||
-rw-r--r-- | tests/authorization-endpoint-no-args.scm | 58 | ||||
-rw-r--r-- | tests/authorization-endpoint-submit-form.scm | 66 | ||||
-rw-r--r-- | tests/client-manifest-not-modified.scm | 59 | ||||
-rw-r--r-- | tests/client-workflow.scm | 117 | ||||
-rw-r--r-- | tests/resource-server.scm | 24 | ||||
-rw-r--r-- | tests/token-endpoint-issue.scm | 182 | ||||
-rw-r--r-- | tests/token-endpoint-refresh.scm | 195 |
8 files changed, 444 insertions, 306 deletions
diff --git a/tests/authorization-endpoint-get-form.scm b/tests/authorization-endpoint-get-form.scm index 25b7128..a3cbf2b 100644 --- a/tests/authorization-endpoint-get-form.scm +++ b/tests/authorization-endpoint-get-form.scm @@ -1,4 +1,4 @@ -;; webid-oidc, implementation of the Solid specification +;; disfluid, implementation of the Solid specification ;; Copyright (C) 2020, 2021 Vivien Kraus ;; This program is free software: you can redistribute it and/or modify @@ -14,17 +14,22 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see <https://www.gnu.org/licenses/>. -(use-modules (webid-oidc authorization-endpoint) - (webid-oidc jwk) - (webid-oidc testing) - ((webid-oidc parameters) #:prefix p:) - (web uri) - (web request) - (web response) - (srfi srfi-19) - (web response) - (ice-9 optargs) - (ice-9 receive)) +(define-module (tests authorization-endpoint-get-form) + #:use-module (webid-oidc jwk) + #:use-module (webid-oidc testing) + #: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 (web response) + #:use-module (ice-9 optargs) + #:use-module (ice-9 receive) + #:use-module (webid-oidc server endpoint) + #:use-module (webid-oidc server endpoint identity-provider) + #:use-module (oop goops) + #:duplicates (merge-generics) + #:declarative? #t) (with-test-environment "authorization-endpoint-get-form" @@ -32,16 +37,18 @@ (define subject (string->uri "https://authorization-endpoint-get-form.scm/profile/card#me")) (define password "p4ssw0rd") (define endpoint - (make-authorization-endpoint - subject password "key-file.jwk")) - (receive (response response-body) + (make <authorization-endpoint> + #:subject subject + #:encrypted-password (crypt password "$6$some.salt.data") + #:key-file "key-file.jwk")) + (receive (response response-body response-meta) (parameterize ((p:current-date 0)) - (endpoint - (build-request (string->uri - (format #f "https://authorization-endpoint-get-form.scm/authorize?client_id=~a&redirect_uri=~a" - (uri-encode "https://authorization-endpoint-get-form.scm/client/card#app") - (uri-encode "https://authorization-endpoint-get-form.scm/client/redirect")))) - "")) + (handle endpoint + (build-request (string->uri + (format #f "https://authorization-endpoint-get-form.scm/authorize?client_id=~a&redirect_uri=~a" + (uri-encode "https://authorization-endpoint-get-form.scm/client/card#app") + (uri-encode "https://authorization-endpoint-get-form.scm/client/redirect")))) + "")) (unless (eq? (response-code response) 200) (exit 3)) (unless (response-content-type response) diff --git a/tests/authorization-endpoint-no-args.scm b/tests/authorization-endpoint-no-args.scm index 7976d9d..0cc2fab 100644 --- a/tests/authorization-endpoint-no-args.scm +++ b/tests/authorization-endpoint-no-args.scm @@ -1,4 +1,4 @@ -;; webid-oidc, implementation of the Solid specification +;; disfluid, implementation of the Solid specification ;; Copyright (C) 2020, 2021 Vivien Kraus ;; This program is free software: you can redistribute it and/or modify @@ -14,17 +14,22 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see <https://www.gnu.org/licenses/>. -(use-modules (webid-oidc authorization-endpoint) - (webid-oidc jwk) - (webid-oidc testing) - ((webid-oidc parameters) #:prefix p:) - (web uri) - (web request) - (web response) - (srfi srfi-19) - (web response) - (ice-9 optargs) - (ice-9 receive)) +(define-module (tests authorization-endpoint-no-args) + #:use-module (webid-oidc jwk) + #:use-module (webid-oidc testing) + #: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 (web response) + #:use-module (ice-9 optargs) + #:use-module (ice-9 receive) + #:use-module (webid-oidc server endpoint) + #:use-module (webid-oidc server endpoint identity-provider) + #:use-module (oop goops) + #:duplicates (merge-generics) + #:declarative? #t) (with-test-environment "authorization-endpoint-no-args" @@ -32,12 +37,25 @@ (define subject (string->uri "https://authorization-endpoint-get-form.scm/profile/card#me")) (define password "p4ssw0rd") (define endpoint - (make-authorization-endpoint subject password "./key-file.jwk")) - (receive (response response-body) + (make <authorization-endpoint> + #:subject subject + #:encrypted-password (crypt password "$6$some.salt.data") + #:key-file "key-file.jwk")) + (with-exception-handler + (lambda (exn) + (unless (and (web-exception? exn) + (eqv? (web-exception-code exn) 400)) + (raise-exception + (make-exception + (make-exception-with-message + "I was expected a 400 response.") + exn)))) + (lambda () (parameterize ((p:current-date 0)) - (endpoint - (build-request (string->uri - "https://authorization-endpoint-get-form.scm/authorize")) - "")) - (unless (eq? (response-code response) 400) - (exit 3))))) + (handle endpoint + (build-request (string->uri + "https://authorization-endpoint-get-form.scm/authorize")) + "") + (exit 3))) + #:unwind? #t + #:unwind-for-type &web-exception))) diff --git a/tests/authorization-endpoint-submit-form.scm b/tests/authorization-endpoint-submit-form.scm index 78216a9..de5c76c 100644 --- a/tests/authorization-endpoint-submit-form.scm +++ b/tests/authorization-endpoint-submit-form.scm @@ -15,13 +15,15 @@ ;; along with this program. If not, see <https://www.gnu.org/licenses/>. (define-module (tests authorization-endpoint-submit-form) - #:use-module (webid-oidc authorization-endpoint) #:use-module (webid-oidc authorization-code) + #:use-module (webid-oidc server endpoint) + #:use-module (webid-oidc server endpoint identity-provider) #:use-module (webid-oidc client-manifest) #:use-module (webid-oidc jwk) #:use-module (webid-oidc cache) #:use-module (webid-oidc jti) #:use-module (webid-oidc testing) + #:use-module (webid-oidc errors) #:use-module ((webid-oidc parameters) #:prefix p:) #:use-module ((webid-oidc stubs) #:prefix stubs:) #:use-module (web uri) @@ -31,6 +33,7 @@ #:use-module (web response) #:use-module (ice-9 optargs) #:use-module (ice-9 receive) + #:use-module (ice-9 exceptions) #:use-module (oop goops) #:declarative? #t #:duplicates (merge-generics)) @@ -54,8 +57,10 @@ (define the-response (car served)) (define the-response-body (cdr served)) (define endpoint - (make-authorization-endpoint - subject encrypted-password "key-file.jwk")) + (make <authorization-endpoint> + #:subject subject + #:encrypted-password encrypted-password + #:key-file "key-file.jwk")) (parameterize ((p:anonymous-http-request (lambda* (uri #:key (headers '()) #:allow-other-keys) (unless (equal? uri what-uri-to-expect) @@ -63,30 +68,43 @@ (values the-response the-response-body)))) (use-cache (lambda () - (receive (response response-body) + (with-exception-handler + (lambda (exn) + (unless (and (web-exception? exn) + (eqv? (web-exception-code exn) 401)) + (raise-exception + (make-exception + (make-exception-with-message + (if (web-exception? exn) + (format #f "the error code should be 401, not ~a" + (web-exception-code exn)) + (format #f "there should be a web error"))) + exn)))) + (lambda () ;; The password is fake! (parameterize ((p:current-date 0)) - (endpoint - (build-request (string->uri - (format #f "https://authorization-endpoint-submit-form.scm/authorize?client_id=~a&redirect_uri=~a" - (uri-encode (uri->string client)) - (uri-encode (uri->string redirect)))) - #:headers '((content-type application/x-www-form-urlencoded)) - #:method 'POST - #:port #t) - "password=fake")) - (when (eq? (response-code response) 302) - (exit 3))) - (receive (response response-body) + (handle endpoint + (build-request (string->uri + (format #f "https://authorization-endpoint-submit-form.scm/authorize?client_id=~a&redirect_uri=~a" + (uri-encode (uri->string client)) + (uri-encode (uri->string redirect)))) + #:headers '((content-type application/x-www-form-urlencoded)) + #:method 'POST + #:port #t) + "password=fake") + (exit 3))) + #:unwind? #t + #:unwind-for-type &web-exception) + (receive (response response-body response-meta) (parameterize ((p:current-date 0)) - (endpoint - (build-request (string->uri - (format #f "https://authorization-endpoint-submit-form.scm/authorize?client_id=~a&redirect_uri=~a" - (uri-encode (uri->string client)) - (uri-encode (uri->string redirect)))) - #:headers '((content-type application/x-www-form-urlencoded)) - #:method 'POST - #:port #t) + (handle endpoint + (build-request (string->uri + (format #f "https://authorization-endpoint-submit-form.scm/authorize?client_id=~a&redirect_uri=~a" + (uri-encode (uri->string client)) + (uri-encode (uri->string redirect)))) + #:headers '((content-type application/x-www-form-urlencoded)) + #:method 'POST + #:port #t) "password=p4ssw0rd")) (unless (eq? (response-code response) 302) (exit 4)) diff --git a/tests/client-manifest-not-modified.scm b/tests/client-manifest-not-modified.scm index 26f4852..9026c87 100644 --- a/tests/client-manifest-not-modified.scm +++ b/tests/client-manifest-not-modified.scm @@ -1,4 +1,4 @@ -;; webid-oidc, implementation of the Solid specification +;; disfluid, implementation of the Solid specification ;; Copyright (C) 2020, 2021 Vivien Kraus ;; This program is free software: you can redistribute it and/or modify @@ -14,31 +14,40 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see <https://www.gnu.org/licenses/>. -(use-modules (webid-oidc client) - (webid-oidc testing) - (webid-oidc errors) - (web uri) - (srfi srfi-19) - (web request) - (web response) - (ice-9 optargs) - (ice-9 receive)) +(define-module (tests client-manifest-not-modified) + #:use-module (webid-oidc server endpoint) + #:use-module (webid-oidc server endpoint client) + #:use-module (webid-oidc client) + #:use-module (webid-oidc testing) + #:use-module (webid-oidc errors) + #:use-module (web uri) + #:use-module (srfi srfi-19) + #:use-module (web request) + #:use-module (web response) + #:use-module (ice-9 optargs) + #:use-module (ice-9 receive) + #:use-module (oop goops) + #:declarative? #t + #:duplicates (merge-generics)) (with-test-environment "client-manifest-not-modified" (lambda () - (let ((handler (serve-application - (string->uri "https://example.com/manifest") - (string->uri "https://example.com/authorized")))) - (receive (response response-body) - (handler (build-request (string->uri "https://example.com/manifest")) - "") - (let ((etag (response-etag response))) - (unless etag - (exit 1)) - (receive (second-response second-response-body) - (handler (build-request (string->uri "https://example.com/manifest") - #:headers `((if-none-match . (,etag)))) - "") - (unless (eqv? (response-code second-response) 304) - (exit 2)))))))) + (define endpoint + (make <client-id> + #:client-id (string->uri "https://example.com/manifest") + #:redirect-uris (list (string->uri "https://example.com/authorized")))) + (receive (response response-body response-meta) + (handle endpoint + (build-request (string->uri "https://example.com/manifest")) + #f) + (let ((etag (response-etag response))) + (unless etag + (exit 1)) + (receive (second-response second-response-body second-response-meta) + (handle endpoint + (build-request (string->uri "https://example.com/manifest") + #:headers `((if-none-match . (,etag)))) + #f) + (unless (eqv? (response-code second-response) 304) + (exit 2))))))) diff --git a/tests/client-workflow.scm b/tests/client-workflow.scm index ed1c1b4..63d505a 100644 --- a/tests/client-workflow.scm +++ b/tests/client-workflow.scm @@ -19,9 +19,15 @@ #:use-module ((webid-oidc client accounts) #:prefix client:) #:use-module ((webid-oidc jwk) #:prefix jwk:) #:use-module (webid-oidc testing) + #:use-module (webid-oidc oidc-configuration) + #:use-module (webid-oidc server endpoint) + #:use-module (webid-oidc server endpoint resource-server) + #:use-module (webid-oidc server endpoint identity-provider) + #:use-module (webid-oidc server endpoint client) + #:use-module (webid-oidc server endpoint authentication) #: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 simulation) #:use-module ((webid-oidc parameters) #:prefix p:) #:use-module (web uri) #:use-module (web request) @@ -33,6 +39,7 @@ #:use-module (ice-9 hash-table) #:use-module (ice-9 match) #:use-module (oop goops) + #:declarative? #t #:duplicates (merge-generics)) ;; In this example, a user firsts requests an account, then logs in @@ -59,39 +66,75 @@ (with-test-environment "client-workflow" (lambda () - (let ((simulation (sim:make-simulation)) + (let ((simulation + (make <simulation> + #:endpoint + (make <router> + #:routed + (list + (make <identity-provider> + #:host "server.client-workflow.scm" + #:oidc-discovery + (make <oidc-discovery> + #:path "/.well-known/openid-configuration" + #:configuration + (make <oidc-configuration> + #:jwks-uri "https://server.client-workflow.scm/keys" + #:authorization-endpoint "https://server.client-workflow.scm/authorize" + #:token-endpoint "https://server.client-workflow.scm/token")) + #:authorization-endpoint + (make <authorization-endpoint> + #:path "/authorize" + #:subject "https://server.client-workflow.scm/alice#me" + #:encrypted-password (crypt "password" "$6$password") + #:key-file "key-file.jwk") + #:token-endpoint + (make <token-endpoint> + #:path "/token" + #:issuer "https://server.client-workflow.scm" + #:key-file "key-file.jwk") + #:jwks-endpoint + (make <jwks-endpoint> + #:path "/keys" + #:key-file "key-file.jwk") + #:default + (make <authenticator> + #:backend + (make <resource-server> + #:server-name "https://server.client-workflow.scm" + #:owner "https://server.client-workflow.scm/alice#me") + #:server-uri "https://server.client-workflow.scm")) + (make <client-id> + #:host "client.client-workflow.scm" + #:client-id "https://client.client-workflow.scm/id" + #:redirect-uris '("https://client.client-workflow.scm/authorized") + #:client-name "Client workflow test" + #:client-uri "https://client.client-workflow.scm/about" + #:grant-types '(authorization_code refresh_token) + #:response-types '(code)))))) (account #f)) - (sim:add-server! simulation - (string->uri "https://server@client-workflow.scm") - (string->uri "https://server@client-workflow.scm/alice#me")) - (sim:add-client! simulation - (string->uri "https://client@client-workflow.scm") - (string->uri "https://client@client-workflow.scm/id") - (string->uri "https://client@client-workflow.scm/authorized") - "Client workflow test" - (string->uri "https://client@client-workflow.scm/about")) (parameterize ((client:client (make <client:client> - #:client-id "https://client@client-workflow.scm/id" + #:client-id "https://client.client-workflow.scm/id" #:redirect-uri - (string->uri "https://client@client-workflow.scm/authorized"))) + (string->uri "https://client.client-workflow.scm/authorized"))) (p:anonymous-http-request - (cute sim:request simulation <...>))) + (cute (@ (webid-oidc simulation) request) simulation <...>))) (parameterize ((p:current-date 0) (client:authorization-process (lambda* (uri #:key reason) - (sim:grant-authorization simulation uri)))) + (grant-authorization simulation uri)))) (receive (new-account response response-body) (begin (set! account - (make <client:account> #:issuer "https://server@client-workflow.scm")) + (make <client:account> #:issuer "https://server.client-workflow.scm")) (client:request account - (string->uri "https://server@client-workflow.scm/"))) + (string->uri "https://server.client-workflow.scm/"))) (set! account new-account) (unless (eqv? (response-code response) 200) ;; Only Alice can read that resource. (exit 3))) - (match (sim:simulation-scroll-log! simulation) + (match (scroll-log! simulation) ;; 1. The client gets the oidc configuration of the ;; server. @@ -124,39 +167,39 @@ (and ;; 1. Get the authorization endpoint. (equal? (request-uri get-oidc-config-request) - (string->uri "https://server@client-workflow.scm/.well-known/openid-configuration")) + (string->uri "https://server.client-workflow.scm/.well-known/openid-configuration")) (eqv? (response-code get-oidc-config-response) 200) ;; 2. The server checks the client ID. (equal? (request-uri get-client-id-request) - (string->uri "https://client@client-workflow.scm/id")) + (string->uri "https://client.client-workflow.scm/id")) (eqv? (response-code get-client-id-response) 200) ;; 3. The authorization request completes. (string-prefix? - "https://server@client-workflow.scm/authorize?" + "https://server.client-workflow.scm/authorize?" (uri->string (request-uri authorization-request))) (eq? (request-method authorization-request) 'POST) (eqv? (response-code authorization-response) 302) (string-prefix? - "https://client@client-workflow.scm/authorized?" + "https://client.client-workflow.scm/authorized?" (uri->string (response-location authorization-response))) ;; 4. Token negociation. (equal? (request-uri token-request) - (string->uri "https://server@client-workflow.scm/token")) + (string->uri "https://server.client-workflow.scm/token")) (eqv? (response-code token-response) 200) ;; 5. The final request. (equal? (request-uri final-request) - (string->uri "https://server@client-workflow.scm/")) + (string->uri "https://server.client-workflow.scm/")) (eqv? (response-code final-response) 200)) (exit 4))))) ;; 1 hour later, the access token should have expired. (parameterize ((p:current-date 3600)) (receive (new-account response response-body) - (client:request account (string->uri "https://server@client-workflow.scm/")) + (client:request account (string->uri "https://server.client-workflow.scm/")) (set! account new-account) (unless (eqv? (response-code response) 200) ;; Only Alice can read that resource. (exit 5))) - (match (sim:simulation-scroll-log! simulation) + (match (scroll-log! simulation) ;; 1. and 2. The client starts sending the request, the server ;; querries the identity provider and keys. @@ -187,39 +230,39 @@ ;; 3. The client realizes that the access token is ;; expired. (equal? (request-uri naively-try-request) - (string->uri "https://server@client-workflow.scm/")) + (string->uri "https://server.client-workflow.scm/")) (eqv? (response-code naively-try-response) 401) (eqv? (time-second (date->time-utc (response-date naively-try-response))) 3600) ;; 4. The client discovers the token endpoint. (equal? (request-uri get-token-endpoint-request) - (string->uri "https://server@client-workflow.scm/.well-known/openid-configuration")) + (string->uri "https://server.client-workflow.scm/.well-known/openid-configuration")) (eqv? (response-code get-token-endpoint-response) 200) ;; 5. Refresh the access token. (equal? (request-uri refresh-request) - (string->uri "https://server@client-workflow.scm/token")) + (string->uri "https://server.client-workflow.scm/token")) (eqv? (response-code refresh-response) 200) ;; 10. Send again. (equal? (request-uri with-new-refresh-token-request) - (string->uri "https://server@client-workflow.scm/")) + (string->uri "https://server.client-workflow.scm/")) (eqv? (response-code with-new-refresh-token-response) 200)) (exit 6))))) ;; Wait another hour, and we’ll need to update the refresh ;; token again, but this time it’s not there anymore. (parameterize ((p:current-date 7200)) (refresh:remove-refresh-token - (string->uri "https://server@client-workflow.scm/alice#me") - (string->uri "https://client@client-workflow.scm/id")) + (string->uri "https://server.client-workflow.scm/alice#me") + (string->uri "https://client.client-workflow.scm/id")) (with-exception-handler (lambda (error) (unless (client:refresh-token-expired? error) (exit 7))) (lambda () - (client:request account (string->uri "https://server@client-workflow.scm/")) + (client:request account (string->uri "https://server.client-workflow.scm/")) (exit 8)) #:unwind? #t #:unwind-for-type client:&refresh-token-expired) - (match (sim:simulation-scroll-log! simulation) + (match (scroll-log! simulation) ;; 1. and 2. The client starts sending the request, the server ;; querries the identity provider and keys. @@ -239,15 +282,15 @@ ;; 3. The client realizes that the access token is ;; expired. (equal? (request-uri naively-try-request) - (string->uri "https://server@client-workflow.scm/")) + (string->uri "https://server.client-workflow.scm/")) (eqv? (response-code naively-try-response) 401) (eqv? (time-second (date->time-utc (response-date naively-try-response))) 7200) ;; 4. The client discovers the token endpoint. (equal? (request-uri get-token-endpoint-request) - (string->uri "https://server@client-workflow.scm/.well-known/openid-configuration")) + (string->uri "https://server.client-workflow.scm/.well-known/openid-configuration")) (eqv? (response-code get-token-endpoint-response) 200) ;; 5. The client tries to refresh. (equal? (request-uri refresh-request) - (string->uri "https://server@client-workflow.scm/token")) + (string->uri "https://server.client-workflow.scm/token")) (eqv? (response-code refresh-response) 403)))))))) diff --git a/tests/resource-server.scm b/tests/resource-server.scm index 767088d..94f2816 100644 --- a/tests/resource-server.scm +++ b/tests/resource-server.scm @@ -16,13 +16,14 @@ (define-module (tests resource-server) #:use-module (webid-oidc provider-confirmation) + #:use-module (webid-oidc server endpoint) + #:use-module (webid-oidc server endpoint authentication) #: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) @@ -30,10 +31,18 @@ #:use-module (srfi srfi-19) #:use-module (web response) #:use-module (ice-9 optargs) + #:use-module (ice-9 control) #:use-module (ice-9 receive) #:use-module (oop goops) #:duplicates (merge-generics)) +(define-class <backend> (<endpoint>)) + +(define return (make-parameter values)) + +(define-method (handle (backend <backend>) request request-body) + ((return) (assq-ref (request-meta request) 'user))) + (with-test-environment "resource-server" (lambda () @@ -91,12 +100,15 @@ DPoP: ~a\r\n\r\n" read-request)) (define rq-body "") (define authenticator - (make-authenticator - #:server-uri server-uri)) + (make <authenticator> + #:backend (make <backend>) + #:server-uri server-uri)) (define parsed - (parameterize ((p:current-date 20) - (p:anonymous-http-request http-get)) - (authenticator rq rq-body))) + (let/ec ret + (parameterize ((p:current-date 20) + (p:anonymous-http-request http-get) + (return ret)) + (handle authenticator rq rq-body)))) (unless (uri? parsed) (exit 2)) (unless (equal? parsed subject) diff --git a/tests/token-endpoint-issue.scm b/tests/token-endpoint-issue.scm index f986e8e..757e650 100644 --- a/tests/token-endpoint-issue.scm +++ b/tests/token-endpoint-issue.scm @@ -14,23 +14,29 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see <https://www.gnu.org/licenses/>. -(use-modules (webid-oidc token-endpoint) - (webid-oidc authorization-code) - (webid-oidc dpop-proof) - (webid-oidc access-token) - (webid-oidc jwk) - (webid-oidc jws) - (webid-oidc jti) - (webid-oidc testing) - ((webid-oidc stubs) #:prefix stubs:) - ((webid-oidc parameters) #:prefix p:) - (web uri) - (web request) - (web response) - (srfi srfi-19) - (web response) - (ice-9 optargs) - (ice-9 receive)) +(define-module (tests token-endpoint-refresh) + #:use-module (webid-oidc server endpoint) + #:use-module (webid-oidc server endpoint identity-provider) + #:use-module (webid-oidc authorization-code) + #:use-module (webid-oidc refresh-token) + #:use-module (webid-oidc dpop-proof) + #:use-module (webid-oidc jwk) + #:use-module (webid-oidc access-token) + #:use-module (webid-oidc jws) + #:use-module (webid-oidc jti) + #: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 request) + #:use-module (web response) + #: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) + #:declarative? #t) (with-test-environment "token-endpoint-issue" @@ -46,18 +52,27 @@ (define subject (string->uri "https://token-endpoint-issue.scm/profile/card#me")) (define client (string->uri "https://token-endpoint-issue.scm/client/card#app")) (define issuer (string->uri "https://issuer.token-endpoint-issue.scm")) + (define endpoint + (make <token-endpoint> + #:issuer "https://issuer.token-endpoint-issue.scm" + #:key-file "key-file.jwk")) (define authz (parameterize ((p:current-date 0)) (issue <authorization-code> key #:webid subject #:client-id client))) - (define endpoint - (make-token-endpoint - (string->uri "https://token-endpoint-issue.scm/token") - issuer "key-file.jwk")) - (receive (response response-body . _) - ;; The code is fake! + (with-exception-handler + (lambda (exn) + (unless (and (web-exception? exn) + (eqv? (web-exception-code exn) 400)) + (raise-exception + (make-exception + (make-exception-with-message + (format #f "the error code should be 400")) + exn)))) + (lambda () + ;; The refresh token is fake! (let ((dpop (parameterize ((p:current-date 0)) (issue <dpop-proof> @@ -67,69 +82,70 @@ #:htu (string->uri "https://token-endpoint-issue.scm/token"))))) (parameterize ((p:current-date 0)) - (endpoint - (build-request (string->uri - "http://localhost:8080/token") - #:headers `((content-type application/x-www-form-urlencoded) - (dpop . ,dpop)) - #:method 'POST - #:port #t) - "grant_type=authorization_code&code=fake"))) - (unless (eq? (response-code response) 400) + (handle endpoint + (build-request (string->uri + "http://localhost:8080/token") + #:headers `((content-type application/x-www-form-urlencoded) + (dpop . ,dpop)) + #:method 'POST + #:port #t) + "grant_type=authorization_code&code=fake"))) (exit 3)) - (receive (response response-body . _) - (let ((dpop - (parameterize ((p:current-date 10)) - (issue <dpop-proof> - client-key - #:jwk (public-key client-key) - #:htm 'POST - #:htu (string->uri - "https://token-endpoint-issue.scm/token"))))) - (parameterize ((p:current-date 10)) - (endpoint - (build-request (string->uri - "http://localhost:8080/token") - #:headers `((content-type application/x-www-form-urlencoded) - (dpop . ,dpop)) - #:method 'POST - #:port #t) - (string-append "grant_type=authorization_code&code=" authz)))) - (unless (eq? (response-code response) 200) - (exit 4)) - (unless (eq? (car (response-content-type response)) 'application/json) - (exit 5)) - (let ((response (stubs:json-string->scm response-body))) - (let ((access-token-enc (assq-ref response 'access_token)) - (refresh-token-enc (assq-ref response 'refresh_token))) - (unless access-token-enc - (exit 6)) - (unless refresh-token-enc - (exit 7)) - (let ((access-token - (parameterize ((p:current-date 20) - (p:anonymous-http-request - (lambda* (uri . args) - (cond - ((equal? uri (string->uri "https://issuer.token-endpoint-issue.scm/.well-known/openid-configuration")) - (values (build-response #:headers '((content-type application/json))) - "{ + #:unwind? #t + #:unwind-for-type &web-exception) + (receive (response response-body . _) + (let ((dpop + (parameterize ((p:current-date 10)) + (issue <dpop-proof> + client-key + #:jwk (public-key client-key) + #:htm 'POST + #:htu (string->uri + "https://token-endpoint-issue.scm/token"))))) + (parameterize ((p:current-date 10)) + (handle endpoint + (build-request (string->uri + "http://localhost:8080/token") + #:headers `((content-type application/x-www-form-urlencoded) + (dpop . ,dpop)) + #:method 'POST + #:port #t) + (string-append "grant_type=authorization_code&code=" authz)))) + (unless (eq? (response-code response) 200) + (exit 4)) + (unless (eq? (car (response-content-type response)) 'application/json) + (exit 5)) + (let ((response (stubs:json-string->scm response-body))) + (let ((access-token-enc (assq-ref response 'access_token)) + (refresh-token-enc (assq-ref response 'refresh_token))) + (unless access-token-enc + (exit 6)) + (unless refresh-token-enc + (exit 7)) + (let ((access-token + (parameterize ((p:current-date 20) + (p:anonymous-http-request + (lambda* (uri . args) + (cond + ((equal? uri (string->uri "https://issuer.token-endpoint-issue.scm/.well-known/openid-configuration")) + (values (build-response #:headers '((content-type application/json))) + "{ \"jwks_uri\": \"https://token-endpoint-issue.scm/keys\", \"token_endpoint\": \"https://token-endpoint-issue.scm/token\", \"authorization_endpoint\": \"https://token-endpoint-issue.scm/authorize\", \"solid_oidc_supported\": \"https://solidproject.org/TR/solid-oidc\" }")) - ((equal? uri (string->uri "https://token-endpoint-issue.scm/keys")) - (values (build-response #:headers '((content-type application/json))) - (stubs:scm->json-string `((keys . ,(list->vector (list (key->jwk key)))))))) - (else - (format (current-error-port) "Unknown URI: ~s\n" (uri->string uri)) - (exit 11)))))) - (decode <access-token> access-token-enc)))) - (unless access-token - (exit 8)) - (let ((access-token-cnf/jkt (cnf/jkt access-token))) - (unless access-token-cnf/jkt - (exit 9)) - (unless (string=? access-token-cnf/jkt (jkt client-key)) - (exit 10)))))))))) + ((equal? uri (string->uri "https://token-endpoint-issue.scm/keys")) + (values (build-response #:headers '((content-type application/json))) + (stubs:scm->json-string `((keys . ,(list->vector (list (key->jwk key)))))))) + (else + (format (current-error-port) "Unknown URI: ~s\n" (uri->string uri)) + (exit 11)))))) + (decode <access-token> access-token-enc)))) + (unless access-token + (exit 8)) + (let ((access-token-cnf/jkt (cnf/jkt access-token))) + (unless access-token-cnf/jkt + (exit 9)) + (unless (string=? access-token-cnf/jkt (jkt client-key)) + (exit 10))))))))) diff --git a/tests/token-endpoint-refresh.scm b/tests/token-endpoint-refresh.scm index 91effe0..d338f2f 100644 --- a/tests/token-endpoint-refresh.scm +++ b/tests/token-endpoint-refresh.scm @@ -14,24 +14,29 @@ ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see <https://www.gnu.org/licenses/>. -(use-modules (webid-oidc token-endpoint) - (webid-oidc authorization-code) - (webid-oidc refresh-token) - (webid-oidc dpop-proof) - (webid-oidc jwk) - (webid-oidc access-token) - (webid-oidc jws) - (webid-oidc jti) - (webid-oidc testing) - ((webid-oidc stubs) #:prefix stubs:) - ((webid-oidc parameters) #:prefix p:) - (web uri) - (web request) - (web response) - (srfi srfi-19) - (web response) - (ice-9 optargs) - (ice-9 receive)) +(define-module (tests token-endpoint-refresh) + #:use-module (webid-oidc server endpoint) + #:use-module (webid-oidc server endpoint identity-provider) + #:use-module (webid-oidc authorization-code) + #:use-module (webid-oidc refresh-token) + #:use-module (webid-oidc dpop-proof) + #:use-module (webid-oidc jwk) + #:use-module (webid-oidc access-token) + #:use-module (webid-oidc jws) + #:use-module (webid-oidc jti) + #: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 request) + #:use-module (web response) + #: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) + #:declarative? #t) (with-test-environment "token-endpoint-refresh" @@ -44,16 +49,25 @@ port #:pretty #t))) (define client-key (generate-key #:n-size 2048)) - (define subject (string->uri "https://token-endpoint-issue.scm/profile/card#me")) - (define client (string->uri "https://token-endpoint-issue.scm/client/card#app")) - (define issuer (string->uri "https://issuer.token-endpoint-issue.scm")) + (define subject (string->uri "https://token-endpoint-refresh.scm/profile/card#me")) + (define client (string->uri "https://token-endpoint-refresh.scm/client/card#app")) + (define issuer (string->uri "https://issuer.token-endpoint-refresh.scm")) (define refresh-code (issue-refresh-token subject client (jkt client-key))) (define endpoint - (make-token-endpoint - (string->uri "https://token-endpoint-issue.scm/token") - issuer "key-file.jwk")) - (receive (response response-body . _) + (make <token-endpoint> + #:issuer "https://issuer.token-endpoint-refresh.scm" + #:key-file "key-file.jwk")) + (with-exception-handler + (lambda (exn) + (unless (and (web-exception? exn) + (eqv? (web-exception-code exn) 400)) + (raise-exception + (make-exception + (make-exception-with-message + (format #f "the error code should be 400")) + exn)))) + (lambda () ;; The refresh token is fake! (let ((dpop (parameterize ((p:current-date 0)) @@ -62,72 +76,73 @@ #:jwk (public-key client-key) #:htm 'POST #:htu (string->uri - "https://token-endpoint-issue.scm/token"))))) + "https://token-endpoint-refresh.scm/token"))))) (parameterize ((p:current-date 0)) - (endpoint - (build-request (string->uri - "http://localhost:8080/token") - #:headers `((content-type application/x-www-form-urlencoded) - (dpop . ,dpop)) - #:method 'POST - #:port #t) - "refresh_token=fake"))) - (unless (eq? (response-code response) 400) + (handle endpoint + (build-request (string->uri + "http://localhost:8080/token") + #:headers `((content-type application/x-www-form-urlencoded) + (dpop . ,dpop)) + #:method 'POST + #:port #t) + "refresh_token=fake"))) (exit 3)) - (receive (response response-body) - (let ((dpop - (parameterize ((p:current-date 10)) - (issue <dpop-proof> - client-key - #:jwk (public-key client-key) - #:htm 'POST - #:htu (string->uri - "https://token-endpoint-issue.scm/token"))))) - (parameterize ((p:current-date 10)) - (endpoint - (build-request (string->uri - "http://localhost:8080/token") - #:headers `((content-type application/x-www-form-urlencoded) - (dpop . ,dpop)) - #:method 'POST - #:port #t) - (string-append "grant_type=refresh_token&refresh_token=" refresh-code)))) - (unless (eq? (response-code response) 200) - (exit 4)) - (unless (eq? (car (response-content-type response)) 'application/json) - (exit 5)) - (let ((response (stubs:json-string->scm response-body))) - (let ((access-token-enc (assq-ref response 'access_token)) - (refresh-token-enc (assq-ref response 'refresh_token))) - (unless access-token-enc - (exit 6)) - (unless refresh-token-enc - (exit 7)) - (let ((access-token - (parameterize ((p:current-date 20) - (p:anonymous-http-request - (lambda* (uri . args) - (cond - ((equal? uri (string->uri "https://issuer.token-endpoint-issue.scm/.well-known/openid-configuration")) - (values (build-response #:headers '((content-type application/json))) - "{ - \"jwks_uri\": \"https://token-endpoint-issue.scm/keys\", - \"token_endpoint\": \"https://token-endpoint-issue.scm/token\", - \"authorization_endpoint\": \"https://token-endpoint-issue.scm/authorize\", + #:unwind? #t + #:unwind-for-type &web-exception) + (receive (response response-body response-meta) + (let ((dpop + (parameterize ((p:current-date 10)) + (issue <dpop-proof> + client-key + #:jwk (public-key client-key) + #:htm 'POST + #:htu (string->uri + "https://token-endpoint-refresh.scm/token"))))) + (parameterize ((p:current-date 10)) + (handle endpoint + (build-request (string->uri + "http://localhost:8080/token") + #:headers `((content-type application/x-www-form-urlencoded) + (dpop . ,dpop)) + #:method 'POST + #:port #t) + (string-append "grant_type=refresh_token&refresh_token=" refresh-code)))) + (unless (eq? (response-code response) 200) + (exit 4)) + (unless (eq? (car (response-content-type response)) 'application/json) + (exit 5)) + (let ((response (stubs:json-string->scm response-body))) + (let ((access-token-enc (assq-ref response 'access_token)) + (refresh-token-enc (assq-ref response 'refresh_token))) + (unless access-token-enc + (exit 6)) + (unless refresh-token-enc + (exit 7)) + (let ((access-token + (parameterize ((p:current-date 20) + (p:anonymous-http-request + (lambda* (uri . args) + (cond + ((equal? uri (string->uri "https://issuer.token-endpoint-refresh.scm/.well-known/openid-configuration")) + (values (build-response #:headers '((content-type application/json))) + "{ + \"jwks_uri\": \"https://token-endpoint-refresh.scm/keys\", + \"token_endpoint\": \"https://token-endpoint-refresh.scm/token\", + \"authorization_endpoint\": \"https://token-endpoint-refresh.scm/authorize\", \"solid_oidc_supported\": \"https://solidproject.org/TR/solid-oidc\" }")) - ((equal? uri (string->uri "https://token-endpoint-issue.scm/keys")) - (values (build-response #:headers '((content-type application/json))) - (stubs:scm->json-string `((keys . ,(list->vector (list (key->jwk key)))))))) - (else - (exit 8)))))) - (decode <access-token> access-token-enc)))) - (unless access-token - (exit 9)) - (let ((access-token-cnf/jkt (cnf/jkt access-token))) - (unless access-token-cnf/jkt - (exit 10)) - (unless (string=? access-token-cnf/jkt (jkt client-key)) - (exit 11)))) - (unless (string=? refresh-token-enc refresh-code) - (exit 12)))))))) + ((equal? uri (string->uri "https://token-endpoint-refresh.scm/keys")) + (values (build-response #:headers '((content-type application/json))) + (stubs:scm->json-string `((keys . ,(list->vector (list (key->jwk key)))))))) + (else + (exit 8)))))) + (decode <access-token> access-token-enc)))) + (unless access-token + (exit 9)) + (let ((access-token-cnf/jkt (cnf/jkt access-token))) + (unless access-token-cnf/jkt + (exit 10)) + (unless (string=? access-token-cnf/jkt (jkt client-key)) + (exit 11)))) + (unless (string=? refresh-token-enc refresh-code) + (exit 12))))))) |