mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-13 17:17:43 +02:00
integration: unauthorized response Content-Type (#4956)
Modify the request 'Accept' header to behave more like a web browser, and add an assertion to verify that Pomerium serves an HTML response for the unauthorized error page.
This commit is contained in:
parent
7edd538be7
commit
f9808a73ba
2 changed files with 22 additions and 2 deletions
|
@ -15,6 +15,9 @@ func TestAuthorization(t *testing.T) {
|
||||||
ctx, clearTimeout := context.WithTimeout(context.Background(), time.Second*30)
|
ctx, clearTimeout := context.WithTimeout(context.Background(), time.Second*30)
|
||||||
defer clearTimeout()
|
defer clearTimeout()
|
||||||
|
|
||||||
|
withBrowserAcceptHeader := flows.WithRequestHeader("Accept",
|
||||||
|
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
|
||||||
|
|
||||||
accessType := []string{"direct", "api"}
|
accessType := []string{"direct", "api"}
|
||||||
for _, at := range accessType {
|
for _, at := range accessType {
|
||||||
t.Run(at, func(t *testing.T) {
|
t.Run(at, func(t *testing.T) {
|
||||||
|
@ -45,7 +48,7 @@ func TestAuthorization(t *testing.T) {
|
||||||
t.Run("allowed", func(t *testing.T) {
|
t.Run("allowed", func(t *testing.T) {
|
||||||
client := getClient(t)
|
client := getClient(t)
|
||||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"),
|
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"),
|
||||||
withAPI, flows.WithEmail("user1@dogs.test"))
|
withAPI, flows.WithEmail("user1@dogs.test"), withBrowserAcceptHeader)
|
||||||
if assert.NoError(t, err) {
|
if assert.NoError(t, err) {
|
||||||
assert.Equal(t, http.StatusOK, res.StatusCode, "expected OK for dogs.test")
|
assert.Equal(t, http.StatusOK, res.StatusCode, "expected OK for dogs.test")
|
||||||
}
|
}
|
||||||
|
@ -53,9 +56,10 @@ func TestAuthorization(t *testing.T) {
|
||||||
t.Run("not allowed", func(t *testing.T) {
|
t.Run("not allowed", func(t *testing.T) {
|
||||||
client := getClient(t)
|
client := getClient(t)
|
||||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"),
|
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-domain"),
|
||||||
withAPI, flows.WithEmail("user1@cats.test"))
|
withAPI, flows.WithEmail("user1@cats.test"), withBrowserAcceptHeader)
|
||||||
if assert.NoError(t, err) {
|
if assert.NoError(t, err) {
|
||||||
assertDeniedAccess(t, res, "expected Forbidden for cats.test, but got: %d", res.StatusCode)
|
assertDeniedAccess(t, res, "expected Forbidden for cats.test, but got: %d", res.StatusCode)
|
||||||
|
assert.Contains(t, res.Header.Get("Content-Type"), "text/html")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -28,6 +28,7 @@ type authenticateConfig struct {
|
||||||
groups []string
|
groups []string
|
||||||
tokenExpiration time.Duration
|
tokenExpiration time.Duration
|
||||||
apiPath string
|
apiPath string
|
||||||
|
requestHeaders http.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
// An AuthenticateOption is an option for authentication.
|
// An AuthenticateOption is an option for authentication.
|
||||||
|
@ -36,6 +37,7 @@ type AuthenticateOption func(cfg *authenticateConfig)
|
||||||
func getAuthenticateConfig(options ...AuthenticateOption) *authenticateConfig {
|
func getAuthenticateConfig(options ...AuthenticateOption) *authenticateConfig {
|
||||||
cfg := &authenticateConfig{
|
cfg := &authenticateConfig{
|
||||||
tokenExpiration: time.Hour * 24,
|
tokenExpiration: time.Hour * 24,
|
||||||
|
requestHeaders: http.Header{},
|
||||||
}
|
}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
if option != nil {
|
if option != nil {
|
||||||
|
@ -73,6 +75,12 @@ func WithAPI() AuthenticateOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithRequestHeader(name, value string) AuthenticateOption {
|
||||||
|
return func(cfg *authenticateConfig) {
|
||||||
|
cfg.requestHeaders.Set(name, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Authenticate submits a request to a URL, expects a redirect to authenticate and then openid and logs in.
|
// Authenticate submits a request to a URL, expects a redirect to authenticate and then openid and logs in.
|
||||||
// Finally it expects to redirect back to the original page.
|
// Finally it expects to redirect back to the original page.
|
||||||
func Authenticate(ctx context.Context, client *http.Client, url *url.URL, options ...AuthenticateOption) (*http.Response, error) {
|
func Authenticate(ctx context.Context, client *http.Client, url *url.URL, options ...AuthenticateOption) (*http.Response, error) {
|
||||||
|
@ -168,6 +176,7 @@ func Authenticate(ctx context.Context, client *http.Client, url *url.URL, option
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
addRequestHeaders(req, cfg.requestHeaders)
|
||||||
} else {
|
} else {
|
||||||
req, err = requestFromRedirectResponse(ctx, res, req)
|
req, err = requestFromRedirectResponse(ctx, res, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -238,5 +247,12 @@ func requestFromRedirectResponse(ctx context.Context, res *http.Response, req *h
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
addRequestHeaders(newreq, req.Header)
|
||||||
return newreq, nil
|
return newreq, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addRequestHeaders(req *http.Request, headers http.Header) {
|
||||||
|
for h := range headers {
|
||||||
|
req.Header[h] = headers[h]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue