summaryrefslogtreecommitdiff
path: root/src/scm/webid-oidc/authorization-code.scm
blob: 7abf68b3086a31af25295007b7fa8b2bd775494f (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
;; disfluid, 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 <https://www.gnu.org/licenses/>.

(define-module (webid-oidc authorization-code)
  #:use-module (webid-oidc errors)
  #:use-module ((webid-oidc stubs) #:prefix stubs:)
  #:use-module (webid-oidc jws)
  #:use-module (webid-oidc jwk)
  #:use-module (webid-oidc jti)
  #:use-module (webid-oidc serializable)
  #:use-module ((webid-oidc parameters) #:prefix p:)
  #:use-module (web uri)
  #:use-module (srfi srfi-19)
  #:use-module (webid-oidc web-i18n)
  #:use-module (ice-9 match)
  #:use-module (ice-9 exceptions)
  #:use-module (ice-9 receive)
  #:use-module (ice-9 optargs)
  #:use-module (oop goops)
  #:declarative? #t
  #:re-export
  (
   alg iat exp nonce
   token->jwt
   decode
   encode
   issue
   )
  #:export
  (

   &invalid-authorization-code
   make-invalid-authorization-code
   invalid-authorization-code?

   <authorization-code> webid client-id
   ))

(define-exception-type
  &invalid-authorization-code
  &external-error
  make-invalid-authorization-code
  invalid-authorization-code?)

(define-class <authorization-code> (<single-use-token>)
  (webid #:init-keyword #:webid #:accessor webid #:->sxml uri->string)
  (client-id #:init-keyword #:client-id #:accessor client-id #:->sxml uri->string)
  #:module-name '(webid-oidc authorization-code))

(define-method (initialize (token <authorization-code>) initargs)
  (with-exception-handler
      (lambda (error)
        (raise-exception
         (make-exception
          (make-invalid-authorization-code)
          (make-exception-with-message
           (if (exception-with-message? error)
               (format #f (G_ "invalid authorization code: ~a")
                       (exception-message error))
               (G_ "invalid authorization code")))
          error)))
    (lambda ()
      (next-method)
      (let-keywords
       initargs #t
       ((webid #f)
        (client-id #f)
        (jwt-header #f)
        (jwt-payload #f))
       (let do-initialize ((webid webid)
                           (client-id client-id)
                           (jwt-header jwt-header)
                           (jwt-payload jwt-payload))
         (cond
          ((string? webid)
           (do-initialize (string->uri webid) client-id jwt-header jwt-payload))
          ((string? client-id)
           (do-initialize webid (string->uri client-id) jwt-header jwt-payload))
          ((and webid client-id)
           (unless (uri? webid)
             (scm-error 'wrong-type-arg "make"
                        (G_ "#:webid should be an URI")
                        '()
                        (list webid)))
           (unless (uri? client-id)
             (scm-error 'wrong-type-arg "make"
                        (G_ "#:client-id should be a string")
                        '()
                        (list client-id)))
           (slot-set! token 'webid webid)
           (slot-set! token 'client-id client-id))
          ((and jwt-header jwt-payload)
           (do-initialize (assq-ref jwt-payload 'webid)
                          (assq-ref jwt-payload 'client_id)
                          #f #f))
          (else
           (raise-exception
            (make-exception
             (make-invalid-jws)
             (make-exception-with-message
              (G_ "when making an authorization code either its required fields (#:webid and #:client-id) or (#:jwt-header and #:jwt-payload) should be passed")))))))))))

(define-method (token->jwt (token <authorization-code>))
  (receive (base-header base-payload)
      (next-method)
    (values
     base-header
     `((webid . ,(uri->string (webid token)))
       (client_id . ,(uri->string (client-id token)))
       ,@base-payload))))

(define-method (lookup-keys (token <authorization-code>) args)
  (let-keywords
   args #f
   ((issuer-key #f))
   issuer-key))