Files
2025-04-02 00:26:21 +11:00

117 lines
3.6 KiB
Go

package plg_handler_mcp
import (
"encoding/json"
"fmt"
"net/http"
"time"
. "github.com/mickael-kerjean/filestash/server/common"
. "github.com/mickael-kerjean/filestash/server/plugin/plg_handler_mcp/utils"
)
const (
DEFAULT_TOKEN_EXPIRY = 3600
)
func (this Server) WellKnownInfoHandler(w http.ResponseWriter, r *http.Request) {
WithCors(w)
if r.Method != http.MethodGet && r.Method != http.MethodOptions {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
scheme := "https"
host := r.Host
if host == "localhost" || host == "127.0.0.1" {
scheme = "http"
}
baseURL := fmt.Sprintf("%s://%s", scheme, host)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"issuer": baseURL,
"authorization_endpoint": fmt.Sprintf("%s/mcp/authorize", baseURL),
"token_endpoint": fmt.Sprintf("%s/mcp/token", baseURL),
"registration_endpoint": fmt.Sprintf("%s/mcp/register", baseURL),
"response_types_supported": []string{"code"},
"grant_types_supported": []string{"authorization_code"},
"token_endpoint_auth_methods_supported": []string{
"none",
},
"code_challenge_methods_supported": []string{
"S256",
},
})
}
func (this Server) AuthorizeHandler(w http.ResponseWriter, r *http.Request) {
WithCors(w)
responseType := r.URL.Query().Get("response_type")
clientID := r.URL.Query().Get("client_id")
redirectURI := r.URL.Query().Get("redirect_uri")
if responseType != "code" {
http.Error(w, "response_type must be 'code'", http.StatusBadRequest)
return
} else if clientID == "" {
http.Error(w, "client_id is required", http.StatusBadRequest)
return
} else if redirectURI == "" {
http.Error(w, "redirect_uri is required", http.StatusBadRequest)
return
}
http.Redirect(w, r, fmt.Sprintf("/login?next=/api/mcp?redirect_uri=%s", redirectURI), http.StatusSeeOther)
}
func (this Server) TokenHandler(w http.ResponseWriter, r *http.Request) {
WithCors(w)
if r.Method != http.MethodPost && r.Method != http.MethodOptions {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
if err := r.ParseForm(); err != nil {
http.Error(w, "Invalid request", http.StatusBadRequest)
return
}
if grantType := r.FormValue("grant_type"); grantType != "authorization_code" {
http.Error(w, "Invalid Grant Type", http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"access_token": r.FormValue("code"),
"token_type": "Bearer",
})
}
func (this Server) RegisterHandler(w http.ResponseWriter, r *http.Request) {
WithCors(w)
if r.Method != http.MethodPost && r.Method != http.MethodOptions {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
w.WriteHeader(http.StatusCreated)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"client_id": "anonymous",
"client_secret": "anonymous",
"client_id_issued_at": time.Now().Unix(),
"client_secret_expires_at": 0,
"client_name": "Untrusted",
"redirect_uris": []string{},
"grant_types": []string{"authorization_code"},
"token_endpoint_auth_method": "client_secret_basic",
})
}
func (this Server) CallbackHandler(ctx *App, res http.ResponseWriter, req *http.Request) {
uri := req.URL.Query().Get("redirect_uri")
if uri == "" {
SendErrorResult(res, ErrNotValid)
return
}
http.Redirect(res, req, fmt.Sprintf(uri+"?code=%s", ctx.Authorization), http.StatusSeeOther)
}