summaryrefslogtreecommitdiff
path: root/tests/client-token.scm
blob: 02f5ec7626a274b294c95dd2b273deea17c1676b (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
(use-modules (webid-oidc client)
             (webid-oidc testing)
             (webid-oidc token-endpoint)
             (webid-oidc jwk)
             (webid-oidc jti)
             (webid-oidc authorization-code)
             (webid-oidc oidc-configuration)
             (webid-oidc jws)
             (webid-oidc oidc-id-token)
             (web uri)
             (web request)
             (web response)
             (srfi srfi-19)
             (ice-9 optargs)
             (ice-9 receive)
             (ice-9 hash-table))

(with-test-environment
 "client-token"
 (lambda ()
   (define the-current-time 0)
   (define issuer-key (generate-key #:n-size 2048))
   (define issuer-configuration
     (make-oidc-configuration
      "https://issuer.client-token.scm/keys"
      "https://issuer.client-token.scm/authorize"
      "https://issuer.client-token.scm/token"))
   (define token-endpoint (make-token-endpoint
                           (string->uri "https://issuer.client-token.scm/token")
                           (string->uri "https://issuer.client-token.scm")
                           'RS256
                           issuer-key
                           3600 ;; 1 hour
                           (make-jti-list)
                           #:current-time (lambda () the-current-time)))
   (define client-key (generate-key #:n-size 2048))
   (define authorization-code
     (issue-authorization-code 'RS256  issuer-key 120
                               (string->uri "https://client-token.scm/profile/card#me")
                               (string->uri "https://app.client-token.scm/app#id")))
   (define* (http-get uri #:key (headers '()))
     (cond
      ((equal? uri (string->uri "https://issuer.client-token.scm/.well-known/openid-configuration"))
       (serve-oidc-configuration
        (time-utc->date (make-time time-utc 0 (+ the-current-time 3600)))
        issuer-configuration))
      ((equal? uri (string->uri "https://issuer.client-token.scm/keys"))
       (serve-jwks
        (time-utc->date (make-time time-utc 0 (+ the-current-time 3600)))
        (make-jwks (list issuer-key))))
      (else
       (format (current-error-port) "GET request to ~a: error.\n" (uri->string uri))
       (exit 1))))
   (define* (http-post uri #:key (body #f) (headers '()))
     (unless (equal? uri (oidc-configuration-token-endpoint issuer-configuration))
       (format (current-error-port)
               "Wrong URI for token negociation: ~a (expected ~a).\n"
               (uri->string uri)
               (uri->string
                (oidc-configuration-token-endpoint
                 issuer-configuration)))
       (exit 2))
     (unless (equal? body (format #f "grant_type=authorization_code&code=~a"
                                  authorization-code))
       (format (current-error-port)
               "Wrong body: ~s\n" body)
       (exit 3))
     (unless (equal?
              (assoc-ref headers 'content-type)
              '(application/x-www-form-urlencoded))
       (format (current-error-port)
               "Wrong content type: ~s\n" (assoc-ref headers 'content-type))
       (exit 4))
     (let ((request
            (build-request uri
                           #:method 'POST
                           #:headers headers
                           #:port (open-input-string body)))
           (request-body body))
       (token-endpoint request request-body)))
   (let ((response
          (token "https://issuer.client-token.scm"
                 client-key
                 #:authorization-code authorization-code
                 #:http-get http-get
                 #:http-post http-post
                 #:current-time (lambda () the-current-time))))
     (let ((id-token (assq-ref response 'id_token))
           (access-token (assq-ref response 'access_token))
           (token-type (assq-ref response 'token_type))
           (token-expiration (assq-ref response 'expires_in))
           (refresh-token (assq-ref response 'refresh_token)))
       (let ((id-token-dec (id-token-decode id-token #:http-get http-get))
             (access-token-dec (jws-decode access-token (lambda (jws) issuer-key))))
         (unless id-token-dec
           (format (current-error-port) "Could not decode the ID token from ~s (~s)"
                   id-token response)
           (exit 5))
         (unless access-token-dec
           (format (current-error-port) "Could not decode the access token from ~s (~s)"
                   access-token response)
           (exit 6))
         (unless refresh-token
           (format (current-error-port) "There does not seem to be a refresh token in ~s"
                   response)
           (exit 6))
         (unless (equal? (id-token-webid id-token-dec)
                         (string->uri "https://client-token.scm/profile/card#me"))
           (exit 7))
         (unless (equal? (id-token-iss id-token-dec)
                         (string->uri "https://issuer.client-token.scm"))
           (exit 8))
         (unless (equal? (id-token-aud id-token-dec)
                         (string->uri "https://app.client-token.scm/app#id"))
           (exit 9))
         ;; It’s not the job of the client to check that the access
         ;; token is correct; TODO: add a check with a resource
         ;; server.

         ;; TODO: try to negociate a refresh token.
         )))))