diff options
Diffstat (limited to 'src/scm/webid-oidc/oidc-id-token.scm')
-rw-r--r-- | src/scm/webid-oidc/oidc-id-token.scm | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/src/scm/webid-oidc/oidc-id-token.scm b/src/scm/webid-oidc/oidc-id-token.scm new file mode 100644 index 0000000..18ac124 --- /dev/null +++ b/src/scm/webid-oidc/oidc-id-token.scm @@ -0,0 +1,201 @@ +(define-module (webid-oidc oidc-id-token) + #:use-module (webid-oidc oidc-configuration) + #:use-module (webid-oidc errors) + #:use-module (webid-oidc jws) + #:use-module (webid-oidc jti) + #:use-module ((webid-oidc stubs) #:prefix stubs:) + #:use-module (web uri) + #:use-module (web client) + #:use-module (ice-9 optargs) + #:use-module (srfi srfi-19)) + +(define-public (the-id-token-header x) + (with-exception-handler + (lambda (error) + (raise-not-an-id-token-header x error)) + (lambda () + (the-jws-header x)))) + +(define-public (id-token-header? x) + (false-if-exception + (and (the-id-token-header x) #t))) + +(define-public (the-id-token-payload x) + (with-exception-handler + (lambda (error) + (raise-not-an-id-token-payload x error)) + (lambda () + (let ((x (the-jws-payload x))) + (let ((webid (assq-ref x 'webid)) + (iss (assq-ref x 'iss)) + (sub (assq-ref x 'sub)) + (aud (assq-ref x 'aud)) + (nonce (assq-ref x 'nonce)) + (iat (assq-ref x 'iat)) + (exp (assq-ref x 'exp))) + (unless (and webid (string? webid) (string->uri webid)) + (raise-incorrect-webid-field webid)) + (unless (and iss (string? iss) (string->uri iss)) + (raise-incorrect-iss-field iss)) + (unless (string? sub) + (raise-incorrect-sub-field sub)) + (unless (and aud (string? aud) (string->uri aud)) + (raise-incorrect-aud-field aud)) + (unless (string? nonce) + (raise-incorrect-nonce-field nonce)) + (unless (integer? iat) + (raise-incorrect-iat-field iat)) + (unless (and (integer? exp) (>= exp iat)) + (raise-incorrect-exp-field exp)) + x))))) + +(define-public (id-token-payload? x) + (false-if-exception + (and (the-id-token-header x) #t))) + +(define-public (the-id-token x) + (with-exception-handler + (lambda (cause) + (raise-not-an-id-token x cause)) + (lambda () + (cons (the-id-token-header (car x)) + (the-id-token-payload (cdr x)))))) + +(define-public (id-token? x) + (false-if-exception + (and (the-id-token x) #t))) + +(define-public (make-id-token header payload) + (the-id-token + (cons header payload))) + +(define-public (make-id-token-payload webid iss sub aud nonce exp iat) + (when (date? exp) + (set! exp (date->time-utc exp))) + (when (time? exp) + (set! exp (time-second exp))) + (when (date? iat) + (set! iat (date->time-utc iat))) + (when (time? iat) + (set! iat (time-second iat))) + (when (uri? webid) + (set! webid (uri->string webid))) + (when (uri? iss) + (set! iss (uri->string iss))) + (when (uri? aud) + (set! aud (uri->string aud))) + (the-id-token-payload + `((webid . ,webid) + (iss . ,iss) + (sub . ,sub) + (aud . ,aud) + (nonce . ,nonce) + (exp . ,exp) + (iat . ,iat)))) + +(define-public (id-token-header code) + (car (the-id-token code))) + +(define-public (id-token-payload code) + (cdr (the-id-token code))) + +(define-public (id-token-alg code) + (when (id-token? code) + (set! code (id-token-header code))) + (jws-alg (the-id-token-header code))) + +(define-public (id-token-webid code) + (when (id-token? code) + (set! code (id-token-payload code))) + (string->uri + (assq-ref (the-id-token-payload code) 'webid))) + +(define-public (id-token-iss code) + (when (id-token? code) + (set! code (id-token-payload code))) + (string->uri + (assq-ref (the-id-token-payload code) 'iss))) + +(define-public (id-token-sub code) + (when (id-token? code) + (set! code (id-token-payload code))) + (assq-ref (the-id-token-payload code) 'sub)) + +(define-public (id-token-aud code) + (when (id-token? code) + (set! code (id-token-payload code))) + (string->uri + (assq-ref (the-id-token-payload code) 'aud))) + +(define-public (id-token-nonce code) + (when (id-token? code) + (set! code (id-token-payload code))) + (assq-ref (the-id-token-payload code) 'nonce)) + +(define-public (id-token-exp code) + (when (id-token? code) + (set! code (id-token-payload code))) + (time-utc->date + (make-time time-utc 0 (assq-ref + (the-id-token-payload code) + 'exp)))) + +(define-public (id-token-iat code) + (when (id-token? code) + (set! code (id-token-payload code))) + (time-utc->date + (make-time time-utc 0 (assq-ref + (the-id-token-payload code) + 'iat)))) + +(define*-public (id-token-decode str #:key (http-get http-get)) + (with-exception-handler + (lambda (error) + (raise-cannot-decode-id-token str error)) + (lambda () + (jws-decode + str + (lambda (token) + (let ((iss (id-token-iss token))) + (let ((cfg + (with-exception-handler + (lambda (error) + (raise-cannot-fetch-issuer-configuration iss error)) + (lambda () + (get-oidc-configuration + (uri-host iss) + #:userinfo (uri-userinfo iss) + #:port (uri-port iss) + #:http-get http-get))))) + (with-exception-handler + (lambda (error) + (raise-cannot-fetch-jwks iss + (oidc-configuration-jwks-uri cfg) + error)) + (lambda () + (oidc-configuration-jwks cfg #:http-get http-get)))))))))) + +(define-public (id-token-encode id-token key) + (with-exception-handler + (lambda (error) + (raise-cannot-encode-id-token id-token key error)) + (lambda () + (jws-encode id-token key)))) + +(define*-public (issue-id-token + issuer-key + #:key + (alg #f) + (webid #f) + (iss #f) + (sub #f) + (aud #f) + (exp #f) + (iat #f)) + (unless sub + (set! sub webid)) + (id-token-encode + (make-id-token + `((alg . ,(symbol->string alg))) + (make-id-token-payload webid iss sub aud (stubs:random 12) exp iat)) + issuer-key)) |