Currently, authorize service does handle unauthenticated request in
forward auth mode, and return status 401.
But proxy has not handled the response yet, and always returns 403 for
both unauthenticated and unauthorized request. That breaks session
handling in forward auth mode. That said, if user was signed out, or for
any reason, authorize service return 401 status, proxy does not redirect
user to re-signin, but always return 403.
To fix it, proxy is changed to handle envoy check response in more
details, to distinguish between 401 and 403 status.
Thanks to @simbaja for rasing the problem and come up with original fix.
Fixes#1014Fixes#858
When proxy receives forward auth request, it should forward the request
as-is to authorize for verification. Currently, it composes the check
request with actual path, then send the request to authorize service.
It makes the request works accidently, because the composed check
request will satisfy the policy un-intentionally. Example, for forward
auth request:
http://pomerium/?uri=https://httpbin.localhost.pomerium.io
the composed request will look like:
&envoy_service_auth_v2.AttributeContext_HttpRequest{
Method: "GET",
Headers: map[string]string{},
Path: "",
Host: "httpbin.localhost.pomerium.io",
Scheme: "https",
}
This check request has at least two problems.
First, it will make authorize.handleForwardAuth always returns false,
even though this is a real forward auth request. Because the "Host"
field in check request is not the forward auth host, which is "pomerium"
in this case.
Second, it will accidently matches rule like:
policy:
- from: https://httpbin.localhost.pomerium.io
to: https://httpbin
allowed_domains:
- pomerium.io
If the rule contains other conditions, like "prefix", or "regex":
policy:
- from: https://httpbin.localhost.pomerium.io
prefix: /headers
to: https://httpbin
allowed_domains:
- pomerium.io
Then the rule will never be triggered, because the "/headers" path can
be passed in request via "X-Forwarded-Uri" (traefik), instead of
directly from the path (nginx).
To fix this, we just pass the forward auth request as-is to authorize.
Fixes#873
* authorize: add support for .pomerium and unauthenticated routes
integration-tests: add test for forward auth dashboard urls
* proxy: fix ctx error test to return a 200 when authorize allows it
authenticate: unmarshal and verify state from jwt, instead of middleware
authorize: embed opa policy using statik
authorize: have IsAuthorized handle authorization for all routes
authorize: if no signing key is provided, one is generated
authorize: remove IsAdmin grpc endpoint
authorize/client: return authorize decision struct
cmd/pomerium: main logger no longer contains email and group
cryptutil: add ECDSA signing methods
dashboard: have impersonate form show up for all users, but have api gated by authz
docs: fix typo in signed jwt header
encoding/jws: remove unused es256 signer
frontend: namespace static web assets
internal/sessions: remove leeway to match authz policy
proxy: move signing functionality to authz
proxy: remove jwt attestation from proxy (authZ does now)
proxy: remove non-signed headers from headers
proxy: remove special handling of x-forwarded-host
sessions: do not verify state in middleware
sessions: remove leeway from state to match authz
sessions/{all}: store jwt directly instead of state
Signed-off-by: Bobby DeSimone <bobbydesimone@gmail.com>
- authenticate: add cors preflight check support for sign_in endpoint
- internal/httputil: indicate responses that originate from pomerium vs the app
- proxy: detect XHR requests and do not redirect on failure.
- authenticate: removed default session duration; should be maintained out of band with rpc.
CookieStore's ClearSession now properly clears the user session cookie by setting MaxAge to -1.
internal/sessions: move encoder interface to encoding package, and rename to MarshalUnmarshaler.
internal/encoding: move mock to own package
authenticate: use INFO log level for authZ error.
Signed-off-by: Bobby DeSimone <bobbydesimone@gmail.com>
These chagnes standardize how session loading is done for session
cookie, auth bearer token, and query params.
- Bearer token previously combined with session cookie.
- rearranged cookie-store to put exported methods above unexported
- added header store that implements session loader interface
- added query param store that implements session loader interface
Signed-off-by: Bobby DeSimone <bobbydesimone@gmail.com>
proxy: remove duplicate error handling in New
proxy: remove routeConfigs in favor of using gorilla/mux
proxy: add proxy specific middleware
proxy: no longer need to use middleware / handler to check if valid route. Can use build in 404 mux.
internal/middleware: add cors bypass middleware
Signed-off-by: Bobby DeSimone <bobbydesimone@gmail.com>