preliminary fixes to broken auth flow

This commit is contained in:
tsmethurst 2021-07-07 23:46:19 +02:00
commit e3ca835ff6
3 changed files with 20 additions and 25 deletions

View file

@ -26,7 +26,6 @@ import (
"github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"github.com/superseriousbusiness/gotosocial/internal/api/model" "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
@ -38,20 +37,25 @@ import (
func (m *Module) AuthorizeGETHandler(c *gin.Context) { func (m *Module) AuthorizeGETHandler(c *gin.Context) {
l := m.log.WithField("func", "AuthorizeGETHandler") l := m.log.WithField("func", "AuthorizeGETHandler")
s := sessions.Default(c) s := sessions.Default(c)
s.Options(sessions.Options{
MaxAge: 120, // give the user 2 minutes to sign in before expiring their session
})
// UserID will be set in the session by AuthorizePOSTHandler if the caller has already gone through the authentication flow // UserID will be set in the session by AuthorizePOSTHandler if the caller has already gone through the authentication flow
// If it's not set, then we don't know yet who the user is, so we need to redirect them to the sign in page. // If it's not set, then we don't know yet who the user is, so we need to redirect them to the sign in page.
userID, ok := s.Get("userid").(string) userID, ok := s.Get("userid").(string)
if !ok || userID == "" { if !ok || userID == "" {
l.Trace("userid was empty, parsing form then redirecting to sign in page") l.Trace("userid was empty, parsing form then redirecting to sign in page")
if err := parseAuthForm(c, l); err != nil { form := &model.OAuthAuthorize{}
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) if err := c.Bind(form); err != nil {
} else { l.Debugf("invalid auth form: %s", err)
c.Redirect(http.StatusFound, AuthSignInPath) return
} }
l.Debugf("parsed auth form: %+v", form)
if err := extractAuthForm(s, form); err != nil {
l.Debug(err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.Redirect(http.StatusFound, AuthSignInPath)
return return
} }
@ -178,18 +182,9 @@ func (m *Module) AuthorizePOSTHandler(c *gin.Context) {
} }
} }
// parseAuthForm parses the OAuthAuthorize form in the gin context, and stores // extractAuthForm checks the given OAuthAuthorize form, and stores
// the values in the form into the session. // the values in the form into the session.
func parseAuthForm(c *gin.Context, l *logrus.Entry) error { func extractAuthForm(s sessions.Session, form *model.OAuthAuthorize) error {
s := sessions.Default(c)
// first make sure they've filled out the authorize form with the required values
form := &model.OAuthAuthorize{}
if err := c.ShouldBind(form); err != nil {
return err
}
l.Tracef("parsed form: %+v", form)
// these fields are *required* so check 'em // these fields are *required* so check 'em
if form.ResponseType == "" || form.ClientID == "" || form.RedirectURI == "" { if form.ResponseType == "" || form.ClientID == "" || form.RedirectURI == "" {
return errors.New("missing one of: response_type, client_id or redirect_uri") return errors.New("missing one of: response_type, client_id or redirect_uri")

View file

@ -107,7 +107,7 @@ func (m *Module) ValidatePassword(email string, password string) (userid string,
// If we've made it this far the email/password is correct, so we can just return the id of the user. // If we've made it this far the email/password is correct, so we can just return the id of the user.
userid = gtsUser.ID userid = gtsUser.ID
l.Tracef("returning (%s, %s)", userid, err) l.Debugf("returning (%s, %s)", userid, err)
return return
} }

View file

@ -22,16 +22,16 @@ package model
// See here: https://docs.joinmastodon.org/methods/apps/oauth/ // See here: https://docs.joinmastodon.org/methods/apps/oauth/
type OAuthAuthorize struct { type OAuthAuthorize struct {
// Forces the user to re-login, which is necessary for authorizing with multiple accounts from the same instance. // Forces the user to re-login, which is necessary for authorizing with multiple accounts from the same instance.
ForceLogin string `form:"force_login,omitempty"` ForceLogin string `form:"force_login" json:"force_login"`
// Should be set equal to `code`. // Should be set equal to `code`.
ResponseType string `form:"response_type"` ResponseType string `form:"response_type" json:"response_type"`
// Client ID, obtained during app registration. // Client ID, obtained during app registration.
ClientID string `form:"client_id"` ClientID string `form:"client_id" json:"client_id"`
// Set a URI to redirect the user to. // Set a URI to redirect the user to.
// If this parameter is set to urn:ietf:wg:oauth:2.0:oob then the authorization code will be shown instead. // If this parameter is set to urn:ietf:wg:oauth:2.0:oob then the authorization code will be shown instead.
// Must match one of the redirect URIs declared during app registration. // Must match one of the redirect URIs declared during app registration.
RedirectURI string `form:"redirect_uri"` RedirectURI string `form:"redirect_uri" json:"redirect_uri"`
// List of requested OAuth scopes, separated by spaces (or by pluses, if using query parameters). // List of requested OAuth scopes, separated by spaces (or by pluses, if using query parameters).
// Must be a subset of scopes declared during app registration. If not provided, defaults to read. // Must be a subset of scopes declared during app registration. If not provided, defaults to read.
Scope string `form:"scope,omitempty"` Scope string `form:"scope" json:"scope"`
} }