refactor(handler/logoutcallback): extract to openid client

This commit is contained in:
Trong Huu Nguyen
2022-07-11 13:37:40 +02:00
parent ad3201fbfb
commit b770f22174
3 changed files with 61 additions and 21 deletions

View File

@@ -22,7 +22,7 @@ type Client interface {
Login(r *http.Request) (Login, error)
LoginCallback(r *http.Request, p provider.Provider, cookie *openid.LoginCookie) LoginCallback
Logout() (Logout, error)
LogoutCallback(r *http.Request) error
LogoutCallback(r *http.Request, cookie *openid.LogoutCookie) LogoutCallback
LogoutFrontchannel(r *http.Request) LogoutFrontchannel
AuthCodeGrant(ctx context.Context, code string, opts []oauth2.AuthCodeOption) (*oauth2.Token, error)
@@ -83,9 +83,8 @@ func (c client) Logout() (Logout, error) {
return logout, nil
}
func (c client) LogoutCallback(r *http.Request) error {
//TODO implement me
panic("implement me")
func (c client) LogoutCallback(r *http.Request, cookie *openid.LogoutCookie) LogoutCallback {
return NewLogoutCallback(r, cookie)
}
func (c client) LogoutFrontchannel(r *http.Request) LogoutFrontchannel {

View File

@@ -1,10 +1,60 @@
package client
type LogoutCallback struct {
Client
import (
"fmt"
"net/http"
"net/url"
"github.com/nais/wonderwall/pkg/openid"
)
type LogoutCallback interface {
ValidateRequest() error
}
func (in LogoutCallback) ValidateRequest() (bool, error) {
// TODO
panic("not implemented")
type logoutCallback struct {
cookie *openid.LogoutCookie
requestParams url.Values
}
func NewLogoutCallback(r *http.Request, cookie *openid.LogoutCookie) LogoutCallback {
return &logoutCallback{
requestParams: r.URL.Query(),
cookie: cookie,
}
}
func (in logoutCallback) ValidateRequest() error {
if err := in.emptyRedirectError(); err != nil {
return err
}
if err := in.stateMismatchError(); err != nil {
return err
}
return nil
}
func (in logoutCallback) emptyRedirectError() error {
if len(in.cookie.RedirectTo) == 0 {
return fmt.Errorf("empty redirect")
}
return nil
}
func (in logoutCallback) stateMismatchError() error {
expectedState := in.cookie.State
actualState := in.requestParams.Get("state")
if len(actualState) <= 0 {
return fmt.Errorf("missing state parameter in request (possible csrf)")
}
if expectedState != actualState {
return fmt.Errorf("state parameter mismatch (possible csrf): expected %s, got %s", expectedState, actualState)
}
return nil
}

View File

@@ -23,18 +23,9 @@ func (h *Handler) LogoutCallback(w http.ResponseWriter, r *http.Request) {
return
}
params := r.URL.Query()
expectedState := logoutCookie.State
actualState := params.Get("state")
if expectedState != actualState {
logger.Warn().Msgf("logout/callback: state parameter mismatch: expected %s, got %s; falling back to ingress", expectedState, actualState)
http.Redirect(w, r, h.Cfg.Wonderwall().Ingress, http.StatusTemporaryRedirect)
return
}
if len(logoutCookie.RedirectTo) == 0 {
logger.Warn().Msgf("logout/callback: empty redirect; falling back to ingress")
logoutCallback := h.Client.LogoutCallback(r, logoutCookie)
if err := logoutCallback.ValidateRequest(); err != nil {
logger.Warn().Msgf("logout/callback: %+v; falling back to ingress", err)
http.Redirect(w, r, h.Cfg.Wonderwall().Ingress, http.StatusTemporaryRedirect)
return
}