mirror of
https://github.com/pomerium/pomerium.git
synced 2025-07-20 01:58:10 +02:00
authenticate: apply branding to sign out pages (#5044)
Add support for the Enterprise branding options to the sign_out and signed_out page handlers.
This commit is contained in:
parent
40655e491a
commit
e8edb465f4
4 changed files with 67 additions and 6 deletions
|
@ -89,7 +89,7 @@ func (a *Authenticate) mountDashboard(r *mux.Router) {
|
||||||
|
|
||||||
// routes that don't need a session:
|
// routes that don't need a session:
|
||||||
sr.Path("/sign_out").Handler(httputil.HandlerFunc(a.SignOut))
|
sr.Path("/sign_out").Handler(httputil.HandlerFunc(a.SignOut))
|
||||||
sr.Path("/signed_out").Handler(handlers.SignedOut(handlers.SignedOutData{})).Methods(http.MethodGet)
|
sr.Path("/signed_out").Handler(httputil.HandlerFunc(a.signedOut)).Methods(http.MethodGet)
|
||||||
|
|
||||||
// routes that need a session:
|
// routes that need a session:
|
||||||
sr = sr.NewRoute().Subrouter()
|
sr = sr.NewRoute().Subrouter()
|
||||||
|
@ -186,7 +186,8 @@ func (a *Authenticate) SignOut(w http.ResponseWriter, r *http.Request) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
handlers.SignOutConfirm(handlers.SignOutConfirmData{
|
handlers.SignOutConfirm(handlers.SignOutConfirmData{
|
||||||
URL: urlutil.SignOutURL(r, authenticateURL, a.state.Load().sharedKey),
|
URL: urlutil.SignOutURL(r, authenticateURL, a.state.Load().sharedKey),
|
||||||
|
BrandingOptions: a.options.Load().BrandingOptions,
|
||||||
}).ServeHTTP(w, r)
|
}).ServeHTTP(w, r)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -240,6 +241,13 @@ func (a *Authenticate) signOutRedirect(w http.ResponseWriter, r *http.Request) e
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Authenticate) signedOut(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
handlers.SignedOut(handlers.SignedOutData{
|
||||||
|
BrandingOptions: a.options.Load().BrandingOptions,
|
||||||
|
}).ServeHTTP(w, r)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// reauthenticateOrFail starts the authenticate process by redirecting the
|
// reauthenticateOrFail starts the authenticate process by redirecting the
|
||||||
// user to their respective identity provider. This function also builds the
|
// user to their respective identity provider. This function also builds the
|
||||||
// 'state' parameter which is encrypted and includes authenticating data
|
// 'state' parameter which is encrypted and includes authenticating data
|
||||||
|
|
|
@ -16,9 +16,11 @@ import (
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/config"
|
"github.com/pomerium/pomerium/config"
|
||||||
"github.com/pomerium/pomerium/internal/atomicutil"
|
"github.com/pomerium/pomerium/internal/atomicutil"
|
||||||
|
@ -33,6 +35,7 @@ import (
|
||||||
"github.com/pomerium/pomerium/internal/testutil"
|
"github.com/pomerium/pomerium/internal/testutil"
|
||||||
"github.com/pomerium/pomerium/internal/urlutil"
|
"github.com/pomerium/pomerium/internal/urlutil"
|
||||||
"github.com/pomerium/pomerium/pkg/cryptutil"
|
"github.com/pomerium/pomerium/pkg/cryptutil"
|
||||||
|
configproto "github.com/pomerium/pomerium/pkg/grpc/config"
|
||||||
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -619,6 +622,49 @@ func TestAuthenticate_CORS(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSignOutBranding(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
auth := testAuthenticate()
|
||||||
|
auth.state.Load().flow.(*stubFlow).verifySignatureErr = errors.New("unsigned URL")
|
||||||
|
auth.options.Store(&config.Options{
|
||||||
|
BrandingOptions: &configproto.Settings{
|
||||||
|
PrimaryColor: proto.String("red"),
|
||||||
|
SecondaryColor: proto.String("orange"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("sign_out", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
r := httptest.NewRequest(http.MethodGet, "/.pomerium/sign_out", nil)
|
||||||
|
err := auth.SignOut(w, r)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, http.StatusOK, w.Code)
|
||||||
|
|
||||||
|
b, err := io.ReadAll(w.Body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Contains(t, string(b), `"primaryColor":"red","secondaryColor":"orange"`)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("signed_out", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
r := httptest.NewRequest(http.MethodGet, "/.pomerium/signed_out", nil)
|
||||||
|
err := auth.signedOut(w, r)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, http.StatusOK, w.Code)
|
||||||
|
|
||||||
|
b, err := io.ReadAll(w.Body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Contains(t, string(b), `"primaryColor":"red","secondaryColor":"orange"`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type mockDataBrokerServiceClient struct {
|
type mockDataBrokerServiceClient struct {
|
||||||
databroker.DataBrokerServiceClient
|
databroker.DataBrokerServiceClient
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// SignedOutData is the data for the SignedOut page.
|
// SignedOutData is the data for the SignedOut page.
|
||||||
type SignedOutData struct{}
|
type SignedOutData struct {
|
||||||
|
BrandingOptions httputil.BrandingOptions
|
||||||
|
}
|
||||||
|
|
||||||
// ToJSON converts the data into a JSON map.
|
// ToJSON converts the data into a JSON map.
|
||||||
func (data SignedOutData) ToJSON() map[string]interface{} {
|
func (data SignedOutData) ToJSON() map[string]interface{} {
|
||||||
return map[string]interface{}{}
|
m := map[string]interface{}{}
|
||||||
|
httputil.AddBrandingOptionsToMap(m, data.BrandingOptions)
|
||||||
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignedOut returns a handler that renders the signed out page.
|
// SignedOut returns a handler that renders the signed out page.
|
||||||
|
|
|
@ -9,14 +9,17 @@ import (
|
||||||
|
|
||||||
// SignOutConfirmData is the data for the SignOutConfirm page.
|
// SignOutConfirmData is the data for the SignOutConfirm page.
|
||||||
type SignOutConfirmData struct {
|
type SignOutConfirmData struct {
|
||||||
URL string
|
URL string
|
||||||
|
BrandingOptions httputil.BrandingOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON converts the data into a JSON map.
|
// ToJSON converts the data into a JSON map.
|
||||||
func (data SignOutConfirmData) ToJSON() map[string]interface{} {
|
func (data SignOutConfirmData) ToJSON() map[string]interface{} {
|
||||||
return map[string]interface{}{
|
m := map[string]interface{}{
|
||||||
"url": data.URL,
|
"url": data.URL,
|
||||||
}
|
}
|
||||||
|
httputil.AddBrandingOptionsToMap(m, data.BrandingOptions)
|
||||||
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignOutConfirm returns a handler that renders the sign out confirm page.
|
// SignOutConfirm returns a handler that renders the sign out confirm page.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue