refactor(handler/logout): extract to openid client

This commit is contained in:
Trong Huu Nguyen
2022-07-11 13:09:10 +02:00
parent 451642caf8
commit ad3201fbfb
6 changed files with 78 additions and 63 deletions
+8 -4
View File
@@ -21,7 +21,7 @@ type Client interface {
Login(r *http.Request) (Login, error)
LoginCallback(r *http.Request, p provider.Provider, cookie *openid.LoginCookie) LoginCallback
Logout(r *http.Request) error
Logout() (Logout, error)
LogoutCallback(r *http.Request) error
LogoutFrontchannel(r *http.Request) LogoutFrontchannel
@@ -74,9 +74,13 @@ func (c client) LoginCallback(r *http.Request, p provider.Provider, cookie *open
return NewLoginCallback(c, r, p, cookie)
}
func (c client) Logout(r *http.Request) error {
//TODO implement me
panic("implement me")
func (c client) Logout() (Logout, error) {
logout, err := NewLogout(c)
if err != nil {
return nil, fmt.Errorf("logout: %w", err)
}
return logout, nil
}
func (c client) LogoutCallback(r *http.Request) error {
+1 -1
View File
@@ -56,7 +56,7 @@ func NewLogin(c Client, r *http.Request) (Login, error) {
redirect := request.CanonicalRedirectURL(r, c.config().Wonderwall().Ingress)
cookie := params.cookie(redirect)
return login{
return &login{
authCodeURL: url,
canonicalRedirect: redirect,
cookie: cookie,
+1 -1
View File
@@ -30,7 +30,7 @@ type loginCallback struct {
}
func NewLoginCallback(c Client, r *http.Request, p provider.Provider, cookie *openid.LoginCookie) LoginCallback {
return loginCallback{
return &loginCallback{
client: c,
cookie: cookie,
provider: p,
+56 -8
View File
@@ -1,17 +1,65 @@
package client
import "github.com/nais/wonderwall/pkg/openid"
import (
"fmt"
"net/url"
type Logout struct {
"github.com/nais/wonderwall/pkg/openid"
"github.com/nais/wonderwall/pkg/strings"
)
type Logout interface {
CanonicalRedirect() string
Cookie() *openid.LogoutCookie
SingleLogoutURL(idToken string) string
}
type logout struct {
Client
cookie *openid.LogoutCookie
endSessionEndpoint *url.URL
}
func (in Logout) URL() string {
// TODO
panic("not implemented")
func NewLogout(c Client) (Logout, error) {
state, err := strings.GenerateBase64(32)
if err != nil {
return nil, fmt.Errorf("generating state: %w", err)
}
cookie := &openid.LogoutCookie{
State: state,
RedirectTo: c.config().Client().GetPostLogoutRedirectURI(),
}
endSessionEndpoint, err := url.Parse(c.config().Provider().EndSessionEndpoint)
if err != nil {
return nil, fmt.Errorf("parsing end session endpoint: %w", err)
}
return &logout{
Client: c,
cookie: cookie,
endSessionEndpoint: endSessionEndpoint,
}, nil
}
func (in Logout) Cookie() openid.LogoutCookie {
// TODO
panic("not implemented")
func (in logout) CanonicalRedirect() string {
return in.cookie.RedirectTo
}
func (in logout) Cookie() *openid.LogoutCookie {
return in.cookie
}
func (in logout) SingleLogoutURL(idToken string) string {
v := in.endSessionEndpoint.Query()
v.Add("post_logout_redirect_uri", in.config().Client().GetLogoutCallbackURI())
v.Add("state", in.cookie.State)
if len(idToken) > 0 {
v.Add("id_token_hint", idToken)
}
in.endSessionEndpoint.RawQuery = v.Encode()
return in.endSessionEndpoint.String()
}
+12 -44
View File
@@ -5,14 +5,17 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"time"
"github.com/go-redis/redis/v8"
"github.com/nais/wonderwall/pkg/cookie"
"github.com/nais/wonderwall/pkg/openid"
logentry "github.com/nais/wonderwall/pkg/router/middleware"
"github.com/nais/wonderwall/pkg/strings"
)
const (
LogoutCookieLifetime = 5 * time.Minute
)
// Logout triggers self-initiated for the current user
@@ -41,53 +44,24 @@ func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) {
h.Loginstatus.ClearCookie(w, h.CookieOptions)
}
u, err := url.Parse(h.Cfg.Provider().EndSessionEndpoint)
logout, err := h.Client.Logout()
if err != nil {
h.InternalError(w, r, fmt.Errorf("logout: parsing end session endpoint: %w", err))
return
h.InternalError(w, r, err)
}
logoutCookie, err := h.logoutCookie()
if err != nil {
h.InternalError(w, r, fmt.Errorf("logout: generating logout cookie: %w", err))
return
}
err = h.setLogoutCookie(w, logoutCookie)
err = h.setLogoutCookie(w, logout.Cookie())
if err != nil {
h.InternalError(w, r, fmt.Errorf("logout: setting logout cookie: %w", err))
return
}
v := u.Query()
v.Add("post_logout_redirect_uri", h.Cfg.Client().GetLogoutCallbackURI())
v.Add("state", logoutCookie.State)
if len(idToken) > 0 {
v.Add("id_token_hint", idToken)
}
u.RawQuery = v.Encode()
fields := map[string]interface{}{
"redirect_to": logoutCookie.RedirectTo,
"redirect_to": logout.CanonicalRedirect(),
}
logger := logentry.LogEntryWithFields(r.Context(), fields)
logger.Info().Msg("logout: redirecting to identity provider")
http.Redirect(w, r, u.String(), http.StatusTemporaryRedirect)
}
func (h *Handler) logoutCookie() (*openid.LogoutCookie, error) {
state, err := strings.GenerateBase64(32)
if err != nil {
return nil, fmt.Errorf("generating state: %w", err)
}
return &openid.LogoutCookie{
State: state,
RedirectTo: h.Cfg.Client().GetPostLogoutRedirectURI(),
}, nil
http.Redirect(w, r, logout.SingleLogoutURL(idToken), http.StatusTemporaryRedirect)
}
func (h *Handler) setLogoutCookie(w http.ResponseWriter, logoutCookie *openid.LogoutCookie) error {
@@ -96,14 +70,8 @@ func (h *Handler) setLogoutCookie(w http.ResponseWriter, logoutCookie *openid.Lo
return fmt.Errorf("marshalling login cookie: %w", err)
}
opts := h.CookieOptions.
WithExpiresIn(LogoutCookieLifetime)
opts := h.CookieOptions.WithExpiresIn(LogoutCookieLifetime)
value := string(logoutCookieJson)
err = cookie.EncryptAndSet(w, cookie.Logout, value, opts, h.Crypter)
if err != nil {
return err
}
return nil
return cookie.EncryptAndSet(w, cookie.Logout, value, opts, h.Crypter)
}
-5
View File
@@ -4,17 +4,12 @@ import (
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/nais/wonderwall/pkg/cookie"
"github.com/nais/wonderwall/pkg/openid"
logentry "github.com/nais/wonderwall/pkg/router/middleware"
)
const (
LogoutCookieLifetime = 5 * time.Minute
)
// LogoutCallback handles the callback from the self-initiated logout for the current user
func (h *Handler) LogoutCallback(w http.ResponseWriter, r *http.Request) {
cookie.Clear(w, cookie.Logout, h.CookieOptions)