diff --git a/internal/oauth/oauth.go b/internal/oauth/oauth.go index c6d596761..0caf2e84b 100644 --- a/internal/oauth/oauth.go +++ b/internal/oauth/oauth.go @@ -36,8 +36,6 @@ "golang.org/x/crypto/bcrypt" ) -const methodAny = "ANY" - type API struct { manager *manage.Manager server *server.Server @@ -107,7 +105,7 @@ func (a *API) AddRoutes(s api.Server) error { s.AttachHandler(http.MethodGet, "/auth/sign_in", a.SignInGETHandler) s.AttachHandler(http.MethodPost, "/auth/sign_in", a.SignInPOSTHandler) - s.AttachHandler(http.MethodPost, "/oauth/token", a.TokenHandler) + s.AttachHandler(http.MethodPost, "/oauth/token", a.TokenPOSTHandler) s.AttachHandler(http.MethodGet, "/oauth/authorize", a.AuthorizeGETHandler) s.AttachHandler(http.MethodPost, "/oauth/authorize", a.AuthorizePOSTHandler) @@ -161,10 +159,10 @@ func (a *API) SignInPOSTHandler(c *gin.Context) { c.Redirect(http.StatusFound, "/oauth/authorize") } -// TokenHandler should be served as a POST at https://example.org/oauth/token +// TokenPOSTHandler should be served as a POST at https://example.org/oauth/token // The idea here is to serve an oauth access token to a user, which can be used for authorizing against non-public APIs. // See https://docs.joinmastodon.org/methods/apps/oauth/#obtain-a-token -func (a *API) TokenHandler(c *gin.Context) { +func (a *API) TokenPOSTHandler(c *gin.Context) { l := a.log.WithField("func", "TokenHandler") l.Trace("entered token handler, will now go to server.HandleTokenRequest") if err := a.server.HandleTokenRequest(c.Writer, c.Request); err != nil { @@ -211,8 +209,14 @@ func (a *API) AuthorizeGETHandler(c *gin.Context) { return } - l.Trace("serving authorize html") - c.HTML(http.StatusOK, "authorize.tmpl", gin.H{}) + code := &code{} + if err := c.Bind(code); err != nil || code.Code == "" { + // no code yet, serve auth html and let the user confirm + l.Trace("serving authorize html") + c.HTML(http.StatusOK, "authorize.tmpl", gin.H{}) + return + } + c.String(http.StatusOK, code.Code) } // AuthorizePOSTHandler should be served as POST at https://example.org/oauth/authorize @@ -254,6 +258,10 @@ func (a *API) AuthorizePOSTHandler(c *gin.Context) { c.JSON(http.StatusBadRequest, gin.H{"error": "session missing redirect_uri"}) return } else { + // todo: explain this little hack + if v == "urn:ietf:wg:oauth:2.0:oob" { + v = "http://localhost:8080/oauth/authorize" + } values.Add("redirect_uri", v) } diff --git a/internal/oauth/oauth_test.go b/internal/oauth/oauth_test.go index 901f99b64..0c786456a 100644 --- a/internal/oauth/oauth_test.go +++ b/internal/oauth/oauth_test.go @@ -40,7 +40,7 @@ func (suite *OauthTestSuite) SetupSuite() { suite.testUser = >smodel.User{ ID: userID, EncryptedPassword: string(encryptedPassword), - Email: "user@example.org", + Email: "user@localhost", CreatedAt: time.Now(), UpdatedAt: time.Now(), AccountID: "some-account-id-it-doesn't-matter-really-since-this-user-doesn't-actually-have-an-account!", @@ -48,7 +48,7 @@ func (suite *OauthTestSuite) SetupSuite() { suite.testClient = &oauthClient{ ID: "a-known-client-id", Secret: "some-secret", - Domain: "https://example.org", + Domain: "http://localhost:8080", UserID: userID, } @@ -122,6 +122,7 @@ func (suite *OauthTestSuite) TestAPIInitialize() { go r.Start() time.Sleep(30 * time.Second) // http://localhost:8080/oauth/authorize?client_id=a-known-client-id&response_type=code&redirect_uri=https://example.org + // http://localhost:8080/oauth/authorize?client_id=a-known-client-id&response_type=code&redirect_uri=urn:ietf:wg:oauth:2.0:oob } func TestOauthTestSuite(t *testing.T) {