;; 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 .
(define-module (tests authorization-endpoint-submit-form)
#:use-module (webid-oidc authorization-code)
#:use-module (webid-oidc server endpoint)
#:use-module (webid-oidc server endpoint identity-provider)
#:use-module (webid-oidc client-manifest)
#:use-module (webid-oidc jwk)
#:use-module (webid-oidc cache)
#:use-module (webid-oidc jti)
#:use-module (webid-oidc testing)
#:use-module (webid-oidc errors)
#:use-module ((webid-oidc parameters) #:prefix p:)
#:use-module ((webid-oidc stubs) #:prefix stubs:)
#:use-module (web uri)
#:use-module (web request)
#:use-module (web response)
#:use-module (srfi srfi-19)
#:use-module (web response)
#:use-module (ice-9 optargs)
#:use-module (ice-9 receive)
#:use-module (ice-9 exceptions)
#:use-module (oop goops)
#:declarative? #t
#:duplicates (merge-generics))
(with-test-environment
"authorization-endpoint-submit-form"
(lambda ()
(define subject (string->uri "https://authorization-endpoint-submit-form.scm/profile/card#me"))
(define client (string->uri "https://authorization-endpoint-submit-form.scm/client/card#app"))
(define redirect (string->uri "https://authorization-endpoint-submit-form.scm/client/redirect"))
(define password "p4ssw0rd")
(define encrypted-password (crypt password "$6$this.is.the.salt"))
(define what-uri-to-expect client)
(define served
(receive (response response-body)
(serve (make
#:client-id client
#:redirect-uris (list redirect))
(time-utc->date (make-time time-utc 0 3600)))
(cons response response-body)))
(define the-response (car served))
(define the-response-body (cdr served))
(define endpoint
(make
#:subject subject
#:encrypted-password encrypted-password
#:key-file (string-append (p:data-home) "/key-file.jwk")))
(parameterize ((p:anonymous-http-request
(lambda* (uri #:key (headers '()) #:allow-other-keys)
(unless (equal? uri what-uri-to-expect)
(exit 2))
(values the-response the-response-body))))
(use-cache
(lambda ()
(with-exception-handler
(lambda (exn)
(unless (and (web-exception? exn)
(eqv? (web-exception-code exn) 401))
(raise-exception
(make-exception
(make-exception-with-message
(if (web-exception? exn)
(format #f "the error code should be 401, not ~a"
(web-exception-code exn))
(format #f "there should be a web error")))
exn))))
(lambda ()
;; The password is fake!
(parameterize ((p:current-date 0))
(handle endpoint
(build-request (string->uri
(format #f "https://authorization-endpoint-submit-form.scm/authorize?client_id=~a&redirect_uri=~a"
(uri-encode (uri->string client))
(uri-encode (uri->string redirect))))
#:headers '((content-type application/x-www-form-urlencoded))
#:method 'POST
#:port #t)
"password=fake")
(exit 3)))
#:unwind? #t
#:unwind-for-type &web-exception)
(receive (response response-body response-meta)
(parameterize ((p:current-date 0))
(handle endpoint
(build-request (string->uri
(format #f "https://authorization-endpoint-submit-form.scm/authorize?client_id=~a&redirect_uri=~a"
(uri-encode (uri->string client))
(uri-encode (uri->string redirect))))
#:headers '((content-type application/x-www-form-urlencoded))
#:method 'POST
#:port #t)
"password=p4ssw0rd"))
(unless (eq? (response-code response) 302)
(exit 4))
(let ((loc (response-location response)))
(unless (uri? loc)
(exit 5))
(let ((loc-scheme (uri-scheme loc))
(loc-host (uri-host loc))
(loc-path (uri-path loc))
(loc-query (uri-query loc)))
(unless (eq? loc-scheme 'https)
(exit 6))
(unless (string=? loc-host "authorization-endpoint-submit-form.scm")
(exit 7))
(unless (string=? loc-path "/client/redirect")
(exit 8))
(let* ((kv (string-split loc-query #\&))
(args (map (lambda (x)
(map uri-decode (string-split x #\=)))
kv)))
(unless (assoc-ref args "code")
(exit 9))
(let ((parsed
(parameterize ((p:current-date 60))
(decode
(car (assoc-ref args "code"))
#:issuer-key
(call-with-input-file (string-append (p:data-home) "/key-file.jwk")
(lambda (port)
(jwk->key (stubs:json->scm port))))))))
(unless parsed
(exit 10))))))))))))