summaryrefslogtreecommitdiff
path: root/tests/client-workflow.scm
blob: 04a44556528f048461a81588318a802174535ee0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
;; webid-oidc, implementation of the Solid specification
;; Copyright (C) 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 <https://www.gnu.org/licenses/>.

(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))

;; 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
;; account, then the refresh token gets banned.

(define (display-log simulation)
  (format (current-error-port) "Log:\n")
  (for-each
   (match-lambda
     ((request request-body response response-body)
      (format (current-error-port) "~s ~s (~s): ~s ~s\n"
              (request-method request)
              (uri->string (request-uri request))
              request-body
              (response-code response)
              (response-reason-phrase response))))
   (sim:simulation-scroll-log! simulation))
  (exit 42))

(with-test-environment
 "client-workflow"
 (lambda ()
   (let ((simulation (sim:make-simulation)))
     (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"))
     (let ((client (client:make-client
                    (string->uri "https://client@client-workflow.scm/id")
                    (jwk:generate-key #:n-size 2048)
                    (string->uri "https://client@client-workflow.scm/authorized"))))
       (parameterize ((p:current-date 0)
                      (client:authorization-process
                       (lambda* (uri #:key issuer)
                         (sim:grant-authorization simulation uri))))
         (receive (response response-body)
             (let ((handler
                    (client:request client #f
                                    (string->uri "https://server@client-workflow.scm")
                                    #:http-request (cute sim:request simulation <...>))))
               (handler (build-request (string->uri "https://server@client-workflow.scm/"))
                        #f))
           (unless (eqv? (response-code response) 200)
             ;; Only Alice can read that resource.
             (exit 3)))
         (match (sim:simulation-scroll-log! simulation)
           ;; 1. The client gets the oidc configuration of the
           ;; server.

           ;; 2. The browser gets redirected to the authorization
           ;; URI and POSTs the authorization form. The server makes
           ;; a request to the client ID, which replies first.

           ;; 3. The authorization request completes.

           ;; 4. The client exchanges the authorization code for a
           ;; refresh token.

           ;; 5. and 6. The client decodes the ID token and requests
           ;; the server keys.

           ;; 7. and 8. While the client is waiting for the final response to
           ;; complete, the server checks the access token validity by
           ;; querying the identity provider for its key.

           ;; 9. The client sends the signed request to the / URI of
           ;; the server.
           (((get-oidc-config-request _ get-oidc-config-response _)
             (get-client-id-request _ get-client-id-response _)
             (authorization-request _ authorization-response _)
             (token-request _ token-response _)
             _ _ ;; the client gets the key
             _ _ ;; the resource server gets the key
             (final-request _ final-response _))
            (unless
                (and
                 ;; 1. Get the authorization endpoint.
                 (equal? (request-uri get-oidc-config-request)
                         (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"))
                 (eqv? (response-code get-client-id-response) 200)
                 ;; 3. The authorization request completes.
                 (string-prefix?
                  "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?"
                  (uri->string (response-location authorization-response)))
                 ;; 4. Token negociation.
                 (equal? (request-uri token-request)
                         (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/"))
                 (eqv? (response-code final-response) 200))
              (exit 4)))))))))