;; webid-oidc, implementation of the Solid specification ;; Copyright (C) 2020, 2021 Vivien Kraus ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Affero General Public License as ;; published by the Free Software Foundation, either version 3 of the ;; License, or (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU Affero General Public License for more details. ;; 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) (webid-oidc testing) ((webid-oidc stubs) #:prefix stubs:) (web uri) (web response) (srfi srfi-19) (ice-9 optargs) (ice-9 receive) (ice-9 hash-table)) ;; We need to test different things. ;; 1. It works when passed a host ;; 2. It works when passed a webid with foreign identity providers ;; 3. It works when passed a webid without foreign identity providers (with-test-environment "client-authorization" (lambda () (define* (http-get uri #:key (headers '())) (cond ;; 1. We pass a host name ((equal? uri (string->uri "https://case-1.client-authorization.scm/.well-known/openid-configuration")) (values (build-response #:headers `((content-type application/json))) (stubs:scm->json-string `((jwks_uri . "https://case-1.client-authorization.scm/keys") (authorization_endpoint . "https://case-1.client-authorization.scm/authorize") (token_endpoint . "https://case-1.client-authorization.scm/token"))))) ;; It’s not a webid ((equal? uri (string->uri "https://case-1.client-authorization.scm")) (values (build-response #:code 404 #:reason-phrase "Not Found") #f)) ;; 2. We first dereference the webid ((equal? uri (string->uri "https://case-2.client-authorization.scm/profile/card#me")) (values (build-response #:headers `((content-type text/turtle))) "<#me> , .")) ;; and we get the config of all IPs ((equal? uri (string->uri "https://case-2.client-authorization.scm/.well-known/openid-configuration")) (values (build-response #:headers `((content-type application/json))) (stubs:scm->json-string `((jwks_uri . "https://case-2.client-authorization.scm/keys") (authorization_endpoint . "https://case-2.client-authorization.scm/authorize") (token_endpoint . "https://case-2.client-authorization.scm/token"))))) ((equal? uri (string->uri "https://one.identity.provider/.well-known/openid-configuration")) (values (build-response #:headers `((content-type application/json))) (stubs:scm->json-string `((jwks_uri . "https://one.identity.provider/keys") (authorization_endpoint . "https://one.identity.provider/authorize") (token_endpoint . "https://one.identity.provider/token"))))) ((equal? uri (string->uri "https://another.identity.provider/.well-known/openid-configuration")) (values (build-response #:headers `((content-type application/json))) (stubs:scm->json-string `((jwks_uri . "https://another.identity.provider/keys") (authorization_endpoint . "https://another.identity.provider/authorize") (token_endpoint . "https://another.identity.provider/token"))))) ;; 3. The webid has no IPs. ((equal? uri (string->uri "https://case-3.client-authorization.scm/profile/card#me")) (values (build-response #:headers `((content-type text/turtle))) "")) ;; so we query the host of the webid. ((equal? uri (string->uri "https://case-3.client-authorization.scm/.well-known/openid-configuration")) (values (build-response #:headers `((content-type application/json))) (stubs:scm->json-string `((jwks_uri . "https://case-3.client-authorization.scm/keys") (authorization_endpoint . "https://case-3.client-authorization.scm/authorize") (token_endpoint . "https://case-3.client-authorization.scm/token"))))) (else (format (current-error-port) "Unexpected GET query of URI ~a.\n" (uri->string uri)) (exit 1)))) (let ((case-1 (authorize "case-1.client-authorization.scm" #:client-id "https://app.client-authorization.scm" #:redirect-uri "https://app.client-authorization.scm/redirected" #:state "integrity&check" #:http-get http-get)) (case-2 (authorize "https://case-2.client-authorization.scm/profile/card#me" #:client-id "https://app.client-authorization.scm" #:redirect-uri "https://app.client-authorization.scm/redirected" #:state "integrity&check" #:http-get http-get)) (case-3 (authorize "https://case-3.client-authorization.scm/profile/card#me" #:client-id "https://app.client-authorization.scm" #:redirect-uri "https://app.client-authorization.scm/redirected" #:state "integrity&check" #:http-get http-get)) (expected-1 `(("https://case-1.client-authorization.scm" . ,(string->uri "https://case-1.client-authorization.scm/authorize?client_id=https%3A%2F%2Fapp.client-authorization.scm&redirect_uri=https%3A%2F%2Fapp.client-authorization.scm%2Fredirected&state=integrity%26check")))) (expected-2 `(("https://case-2.client-authorization.scm" . ,(string->uri "https://case-2.client-authorization.scm/authorize?client_id=https%3A%2F%2Fapp.client-authorization.scm&redirect_uri=https%3A%2F%2Fapp.client-authorization.scm%2Fredirected&state=integrity%26check")) ("https://one.identity.provider" . ,(string->uri "https://one.identity.provider/authorize?client_id=https%3A%2F%2Fapp.client-authorization.scm&redirect_uri=https%3A%2F%2Fapp.client-authorization.scm%2Fredirected&state=integrity%26check")) ("https://another.identity.provider" . ,(string->uri "https://another.identity.provider/authorize?client_id=https%3A%2F%2Fapp.client-authorization.scm&redirect_uri=https%3A%2F%2Fapp.client-authorization.scm%2Fredirected&state=integrity%26check")))) (expected-3 `(("https://case-3.client-authorization.scm" . ,(string->uri "https://case-3.client-authorization.scm/authorize?client_id=https%3A%2F%2Fapp.client-authorization.scm&redirect_uri=https%3A%2F%2Fapp.client-authorization.scm%2Fredirected&state=integrity%26check"))))) (unless (equal? case-1 expected-1) (format (current-error-port) "Case 1 failed:\n~s\n~s\n\n" case-1 expected-1) (exit 2)) (unless (equal? (hash-map->list cons (alist->hash-table case-2)) (hash-map->list cons (alist->hash-table expected-2))) (format (current-error-port) "Case 2 failed:\n~s\n~s\n\n" case-2 expected-2) (exit 3)) (unless (equal? case-3 expected-3) (format (current-error-port) "Case 3 failed:\n~s\n~s\n\n" case-3 expected-3) (exit 4)))))