diff --git a/internal/controller/oauth_controller.go b/internal/controller/oauth_controller.go index 18bed57c..1c295780 100644 --- a/internal/controller/oauth_controller.go +++ b/internal/controller/oauth_controller.go @@ -61,7 +61,7 @@ func (controller *OAuthController) oauthURLHandler(c *gin.Context) { return } - var reqParams service.OAuthURLParams + var reqParams service.OAuthCallbackParams err = c.BindQuery(&reqParams) @@ -83,7 +83,7 @@ func (controller *OAuthController) oauthURLHandler(c *gin.Context) { } } - sessionId, _, err := controller.auth.NewOAuthSession(req.Provider, reqParams) + sessionId, err := controller.auth.NewOAuthSession(req.Provider, reqParams) if err != nil { controller.log.App.Error().Err(err).Msg("Failed to create new OAuth session") @@ -272,7 +272,7 @@ func (controller *OAuthController) oauthCallbackHandler(c *gin.Context) { c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/error", controller.runtime.AppURL)) return } - c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/authorize?%s", controller.runtime.AppURL, queries.Encode())) + c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/oidc/authorize?%s", controller.runtime.AppURL, queries.Encode())) return } @@ -294,11 +294,8 @@ func (controller *OAuthController) oauthCallbackHandler(c *gin.Context) { c.Redirect(http.StatusTemporaryRedirect, controller.runtime.AppURL) } -func (controller *OAuthController) isOidcRequest(params service.OAuthURLParams) bool { - return params.Scope != "" && - params.ResponseType != "" && - params.ClientID != "" && - params.RedirectURI != "" +func (controller *OAuthController) isOidcRequest(params service.OAuthCallbackParams) bool { + return params.LoginFor == "oidc" } func (controller *OAuthController) getCookieDomain() string { diff --git a/internal/controller/oidc_controller.go b/internal/controller/oidc_controller.go index e6c3562b..969c5e8e 100644 --- a/internal/controller/oidc_controller.go +++ b/internal/controller/oidc_controller.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" "github.com/google/go-querystring/query" "github.com/tinyauthapp/tinyauth/internal/model" @@ -116,7 +117,7 @@ func (controller *OIDCController) authorize(c *gin.Context) { var req service.AuthorizeRequest - err := c.Bind(&req) + err := c.ShouldBindWith(&req, binding.Query) if err != nil { controller.authorizeError(c, authorizeErrorParams{ diff --git a/internal/service/auth_service.go b/internal/service/auth_service.go index 1034ed1e..ef3e9e08 100644 --- a/internal/service/auth_service.go +++ b/internal/service/auth_service.go @@ -30,17 +30,14 @@ var ( ErrUserNotFound = errors.New("user not found") ) -// slightly modified version of the AuthorizeRequest from the OIDC service to basically accept all -// parameters and pass them to the authorize page if needed -type OAuthURLParams struct { - Scope string `form:"scope" url:"scope"` - ResponseType string `form:"response_type" url:"response_type"` - ClientID string `form:"client_id" url:"client_id"` - RedirectURI string `form:"redirect_uri" url:"redirect_uri"` - State string `form:"state" url:"state"` - Nonce string `form:"nonce" url:"nonce"` - CodeChallenge string `form:"code_challenge" url:"code_challenge"` - CodeChallengeMethod string `form:"code_challenge_method" url:"code_challenge_method"` +// We either store params for redirecting to an app after OAuth login, +// or for redirecting back to the authorize screen to continue OIDC +type OAuthCallbackParams struct { + LoginFor string `form:"login_for" url:"login_for"` + OIDCTicket string `form:"oidc_ticket" url:"oidc_ticket"` + OIDCScope string `form:"oidc_scope" url:"oidc_scope"` + OIDCName string `form:"oidc_name" url:"oidc_name"` + RedirectURI string `form:"redirect_uri" url:"redirect_uri"` } type OAuthPendingSession struct { @@ -49,7 +46,7 @@ type OAuthPendingSession struct { Token *oauth2.Token Service *OAuthServiceImpl ExpiresAt time.Time - CallbackParams OAuthURLParams + CallbackParams OAuthCallbackParams } type LoginAttempt struct { @@ -516,17 +513,17 @@ func (auth *AuthService) LDAPAuthConfigured() bool { return auth.ldap != nil } -func (auth *AuthService) NewOAuthSession(serviceName string, params OAuthURLParams) (string, OAuthPendingSession, error) { +func (auth *AuthService) NewOAuthSession(serviceName string, params OAuthCallbackParams) (string, error) { service, ok := auth.oauthBroker.GetService(serviceName) if !ok { - return "", OAuthPendingSession{}, fmt.Errorf("oauth service not found: %s", serviceName) + return "", fmt.Errorf("oauth service not found: %s", serviceName) } sessionId, err := uuid.NewRandom() if err != nil { - return "", OAuthPendingSession{}, fmt.Errorf("failed to generate session ID: %w", err) + return "", fmt.Errorf("failed to generate session ID: %w", err) } state := service.NewRandom() @@ -542,7 +539,7 @@ func (auth *AuthService) NewOAuthSession(serviceName string, params OAuthURLPara auth.caches.oauth.Set(sessionId.String(), session, time.Minute*10) - return sessionId.String(), session, nil + return sessionId.String(), nil } func (auth *AuthService) GetOAuthURL(sessionId string) (string, error) {