diff --git a/internal/oidc/auth/auth_handler.go b/internal/oidc/auth/auth_handler.go index b4b9fccd..698ea7f3 100644 --- a/internal/oidc/auth/auth_handler.go +++ b/internal/oidc/auth/auth_handler.go @@ -24,6 +24,7 @@ import ( "go.pinniped.dev/internal/oidc/downstreamsession" "go.pinniped.dev/internal/oidc/login" "go.pinniped.dev/internal/oidc/provider" + "go.pinniped.dev/internal/oidc/provider/formposthtml" "go.pinniped.dev/internal/plog" "go.pinniped.dev/internal/psession" "go.pinniped.dev/pkg/oidcclient/nonce" @@ -46,7 +47,7 @@ func NewHandler( upstreamStateEncoder oidc.Encoder, cookieCodec oidc.Codec, ) http.Handler { - return securityheader.Wrap(httperr.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { + handler := httperr.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { if r.Method != http.MethodPost && r.Method != http.MethodGet { // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest // Authorization Servers MUST support the use of the HTTP GET and POST methods defined in @@ -105,7 +106,12 @@ func NewHandler( upstreamStateEncoder, cookieCodec, ) - })) + }) + + // During a response_mode=form_post auth request using the browser flow, the custom form_post html page may + // be used to post certain errors back to the CLI from this handler's response, so allow the form_post + // page's CSS and JS to run. + return securityheader.WrapWithCustomCSP(handler, formposthtml.ContentSecurityPolicy()) } func handleAuthRequestForLDAPUpstreamCLIFlow( diff --git a/internal/oidc/auth/auth_handler_test.go b/internal/oidc/auth/auth_handler_test.go index dc93c42a..11431a0b 100644 --- a/internal/oidc/auth/auth_handler_test.go +++ b/internal/oidc/auth/auth_handler_test.go @@ -521,6 +521,7 @@ func TestAuthorizationEndpoint(t *testing.T) { wantStatus int wantContentType string wantBodyString string + wantBodyRegex string wantBodyJSON string wantCSRFValueInCookieHeader string wantBodyStringWithLocationInHref bool @@ -1537,6 +1538,20 @@ func TestAuthorizationEndpoint(t *testing.T) { wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidScopeErrorQuery), wantBodyString: "", }, + { + name: "form_post page is used to send errors to client using OIDC upstream browser flow with response_mode=form_post", + idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(upstreamOIDCIdentityProviderBuilder().Build()), + generateCSRF: happyCSRFGenerator, + generatePKCE: happyPKCEGenerator, + generateNonce: happyNonceGenerator, + stateEncoder: happyStateEncoder, + cookieEncoder: happyCookieEncoder, + method: http.MethodGet, + path: modifiedHappyGetRequestPath(map[string]string{"response_mode": "form_post", "scope": "openid profile email tuna"}), + wantStatus: http.StatusOK, + wantContentType: htmlContentType, + wantBodyRegex: `