This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
(ns integration-test
|
||||
(:require [babashka.http-client :as http]
|
||||
[cheshire.core :as json]
|
||||
[clojure.edn :as edn]
|
||||
[clojure.string :as str]))
|
||||
|
||||
@@ -29,6 +30,15 @@
|
||||
:headers {"Content-Type" "application/json"}
|
||||
:body body}))
|
||||
|
||||
(defn post-form* [url params]
|
||||
(http/post url {:throw false
|
||||
:client no-redirect-client
|
||||
:headers {"Content-Type" "application/x-www-form-urlencoded"}
|
||||
:form-params params}))
|
||||
|
||||
(defn json* [url]
|
||||
(json/parse-string (:body (http/get url))))
|
||||
|
||||
(defn wait-for-server [{:keys [base-url max-retries retry-delay-ms]}]
|
||||
(println (str "=== Waiting for server at " base-url " ==="))
|
||||
(loop [i 1]
|
||||
@@ -174,6 +184,56 @@
|
||||
(assert-eq "GET one" 401 (:status (get* (str base-url "/api/todos/1"))))
|
||||
(println)
|
||||
|
||||
(println "Test 16: POST /mcp without a token returns 401 pointing at the OAuth metadata")
|
||||
(let [resp (http/post (str base-url "/mcp")
|
||||
{:throw false
|
||||
:headers {"Content-Type" "application/json"
|
||||
"Accept" "application/json, text/event-stream"}
|
||||
:body "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\"}"})
|
||||
challenge (get (:headers resp) "www-authenticate" "")]
|
||||
(assert-eq "HTTP status" 401 (:status resp))
|
||||
(assert-contains "WWW-Authenticate" "Bearer resource_metadata=" challenge)
|
||||
(assert-contains "WWW-Authenticate names the metadata document" "/.well-known/oauth-protected-resource/mcp" challenge))
|
||||
(assert-eq "A bogus token is refused too" 401
|
||||
(:status (http/post (str base-url "/mcp")
|
||||
{:throw false
|
||||
:headers {"Content-Type" "application/json" "Authorization" "Bearer nope"}
|
||||
:body "{}"})))
|
||||
(println)
|
||||
|
||||
(println "Test 17: MCP OAuth discovery, registration and the authorize/token endpoints")
|
||||
(let [resource (json* (str base-url "/.well-known/oauth-protected-resource/mcp"))
|
||||
server (json* (str base-url "/.well-known/oauth-authorization-server"))]
|
||||
(assert-contains "Resource metadata names the MCP endpoint" "/mcp" (get resource "resource"))
|
||||
(assert-eq "PKCE S256 only" ["S256"] (get server "code_challenge_methods_supported"))
|
||||
(assert-contains "Registration endpoint" "/oauth/register" (get server "registration_endpoint")))
|
||||
(let [reg (http/post (str base-url "/oauth/register")
|
||||
{:throw false
|
||||
:headers {"Content-Type" "application/json"}
|
||||
:body "{\"redirect_uris\":[\"http://localhost:8123/callback\"],\"client_name\":\"integration\"}"})
|
||||
client-id (get (json/parse-string (:body reg)) "client_id")]
|
||||
(assert-eq "Registering a client" 201 (:status reg))
|
||||
(assert-eq "Registering a web redirect over plain http is refused" 400
|
||||
(:status (http/post (str base-url "/oauth/register")
|
||||
{:throw false
|
||||
:headers {"Content-Type" "application/json"}
|
||||
:body "{\"redirect_uris\":[\"http://evil.example.com/cb\"]}"})))
|
||||
(let [resp (get-no-redirect* (str base-url "/oauth/authorize?client_id=" client-id
|
||||
"&redirect_uri=http%3A%2F%2Flocalhost%3A8123%2Fcallback&response_type=code"
|
||||
"&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256"))]
|
||||
(assert-eq "Authorize while logged out sends the user to log in" 302 (:status resp))
|
||||
(assert-contains "Location" "/auth/login?return_to=" (get (:headers resp) "location" "")))
|
||||
(assert-eq "Authorize with an unregistered redirect URI is an error page, not a redirect" 400
|
||||
(:status (get-no-redirect* (str base-url "/oauth/authorize?client_id=" client-id
|
||||
"&redirect_uri=https%3A%2F%2Fevil.example.com%2Fcb&response_type=code"))))
|
||||
(assert-eq "A bad code is invalid_grant" "invalid_grant"
|
||||
(get (json/parse-string (:body (post-form* (str base-url "/oauth/token")
|
||||
{"grant_type" "authorization_code" "code" "nope" "client_id" client-id
|
||||
"redirect_uri" "http://localhost:8123/callback"
|
||||
"code_verifier" (apply str (repeat 43 "a"))})))
|
||||
"error")))
|
||||
(println)
|
||||
|
||||
(println "================================")
|
||||
(println (format " Results: %d passed, %d failed" @pass @fail))
|
||||
(println "================================")
|
||||
|
||||
Reference in New Issue
Block a user