From 37936a450f8c75612feb739bdecb11c682e42c0e Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Mon, 7 Nov 2022 19:44:10 +0100 Subject: [PATCH] indieauth-metadata --- cmd/owl/web/auth_test.go | 26 ++++++++++++++++++++++++++ cmd/owl/web/handler.go | 37 +++++++++++++++++++++++++++++++++++++ cmd/owl/web/server.go | 2 ++ embed/initial/base.html | 1 + user.go | 5 +++++ 5 files changed, 71 insertions(+) diff --git a/cmd/owl/web/auth_test.go b/cmd/owl/web/auth_test.go index 9ce37f9..844b598 100644 --- a/cmd/owl/web/auth_test.go +++ b/cmd/owl/web/auth_test.go @@ -399,3 +399,29 @@ func TestAccessTokenWithIncorrectCode(t *testing.T) { assertions.AssertStatus(t, rr, http.StatusUnauthorized) } + +func TestIndieauthMetadata(t *testing.T) { + repo, user := getSingleUserTestRepo() + user.ResetPassword("testpassword") + req, _ := http.NewRequest("GET", user.IndieauthMetadataUrl(), nil) + rr := httptest.NewRecorder() + router := main.SingleUserRouter(&repo) + router.ServeHTTP(rr, req) + + assertions.AssertStatus(t, rr, http.StatusOK) + // parse response as json + type responseType struct { + Issuer string `json:"issuer"` + AuthorizationEndpoint string `json:"authorization_endpoint"` + TokenEndpoint string `json:"token_endpoint"` + CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"` + ScopesSupported []string `json:"scopes_supported"` + ResponseTypesSupported []string `json:"response_types_supported"` + GrantTypesSupported []string `json:"grant_types_supported"` + } + var response responseType + json.Unmarshal(rr.Body.Bytes(), &response) + assertions.AssertEqual(t, response.Issuer, user.FullUrl()) + assertions.AssertEqual(t, response.AuthorizationEndpoint, user.AuthUrl()) + assertions.AssertEqual(t, response.TokenEndpoint, user.TokenUrl()) +} diff --git a/cmd/owl/web/handler.go b/cmd/owl/web/handler.go index 4cbf887..0bf1d22 100644 --- a/cmd/owl/web/handler.go +++ b/cmd/owl/web/handler.go @@ -60,6 +60,43 @@ func userIndexHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Requ } } +func userAuthMetadataHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request, httprouter.Params) { + return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + user, err := getUserFromRepo(repo, ps) + if err != nil { + println("Error getting user: ", err.Error()) + notFoundHandler(repo)(w, r) + return + } + + type Response struct { + Issuer string `json:"issuer"` + AuthorizationEndpoint string `json:"authorization_endpoint"` + TokenEndpoint string `json:"token_endpoint"` + CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"` + ScopesSupported []string `json:"scopes_supported"` + ResponseTypesSupported []string `json:"response_types_supported"` + GrantTypesSupported []string `json:"grant_types_supported"` + } + response := Response{ + Issuer: user.FullUrl(), + AuthorizationEndpoint: user.AuthUrl(), + TokenEndpoint: user.TokenUrl(), + CodeChallengeMethodsSupported: []string{"S256", "plain"}, + ScopesSupported: []string{"profile"}, + ResponseTypesSupported: []string{"code"}, + GrantTypesSupported: []string{"authorization_code"}, + } + jsonData, err := json.Marshal(response) + if err != nil { + println("Error marshalling json: ", err.Error()) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Internal server error")) + } + w.Write(jsonData) + } +} + func userAuthHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request, httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { user, err := getUserFromRepo(repo, ps) diff --git a/cmd/owl/web/server.go b/cmd/owl/web/server.go index 02937c1..7e75ac5 100644 --- a/cmd/owl/web/server.go +++ b/cmd/owl/web/server.go @@ -18,6 +18,7 @@ func Router(repo *owl.Repository) http.Handler { router.POST("/user/:user/auth/", userAuthProfileHandler(repo)) router.POST("/user/:user/auth/verify/", userAuthVerifyHandler(repo)) router.POST("/user/:user/auth/token/", userAuthTokenHandler(repo)) + router.GET("/user/:user/auth/indieauth-metadata", userAuthMetadataHandler(repo)) router.GET("/user/:user/media/*filepath", userMediaHandler(repo)) router.GET("/user/:user/index.xml", userRSSHandler(repo)) router.GET("/user/:user/posts/:post/", postHandler(repo)) @@ -35,6 +36,7 @@ func SingleUserRouter(repo *owl.Repository) http.Handler { router.POST("/auth/", userAuthProfileHandler(repo)) router.POST("/auth/verify/", userAuthVerifyHandler(repo)) router.POST("/auth/token/", userAuthTokenHandler(repo)) + router.GET("/auth/indieauth-metadata", userAuthMetadataHandler(repo)) router.GET("/media/*filepath", userMediaHandler(repo)) router.GET("/index.xml", userRSSHandler(repo)) router.GET("/posts/:post/", postHandler(repo)) diff --git a/embed/initial/base.html b/embed/initial/base.html index ff99bb4..78ad250 100644 --- a/embed/initial/base.html +++ b/embed/initial/base.html @@ -28,6 +28,7 @@ {{ if .User.AuthUrl }} + {{ end }} diff --git a/user.go b/user.go index ec0b2c3..6d1200a 100644 --- a/user.go +++ b/user.go @@ -78,6 +78,11 @@ func (user User) TokenUrl() string { return url } +func (user User) IndieauthMetadataUrl() string { + url, _ := url.JoinPath(user.AuthUrl(), "indieauth-metadata") + return url +} + func (user User) WebmentionUrl() string { url, _ := url.JoinPath(user.FullUrl(), "webmention/") return url