pomerium icon indicating copy to clipboard operation
pomerium copied to clipboard

Use a user context creator URL

Open mont5piques opened this issue 2 years ago • 1 comments

Is your feature request related to a problem? Please describe.

I use often Pomerium to secure legacy applications that do not support OIDC features and in the majority of cases (php apps for exemple), these apps use a username/password forms to authenticate users.

If we use Pomerium, we need always to authenticate twice : the first time using SSO provider and the second time using these legacy forms.

Describe the solution you'd like

For one of these applications, I coded a flask webservice that does the following:

  • The service authenticate against the legacy application using an admin account
  • Given a valid authentication context (token + user claims ...):
    • The service will update the user password with a temporary generated one (very secure)
    • The service will authenticate with username / password
    • The service will return the generated cookies (Set-Cookie headers)

Now, I would like to use that service to create a user context session using Pomerium:

routes:
  - from: https://my-legacy-app-secured.domain
    to: http://my-legacy-app/
    allow_any_authenticated_user: true
    upstream_authentication:
        login_url: http://my-flask-authentication-service:8000/legacy-auth
        auth_check: *[optional]* http://my-flask-authentication-service:8000/legacy-auth-check
        method: GET
        set_authorization_header: pass_through
        pass_identity_headers: true
        resulting_cookies:
          - PHPSESSID

In this example, IF there is no pomerium session and we're forwarded to OIDC authentication, right after the authentication, an upstream_authentication is performed using a third-party service (login_url) which will generate app-specific cookies (restricted by resulting_cookies param to avoid conflicts).

If specified, auth_check verifies if app-specific session is always active. If not, restart an upstream_authentication

Describe alternatives you've considered

*Alternative 1: *

Using 2x proxifications:

routes:
  - from: https://my-legacy-app-secured.domain
    to: http://my-flask-authentication-service:8000
    allow_any_authenticated_user: true
    pass_identity_headers: true

Pomerium ==PROXY==> my-flask-authentication layer ==PROXY==> legacy-app

*Disadvantages: *

  • We need to code a reverse proxy application
  • Add an additionnal layer of proxification

*Alternative 2: * Which I'm using for now

Using a nginx based Pomerium-like altenative with some tweaks. In this configuration, we check if legacy app session is always active (using http://my-flask-authentication-service:8000/legacy-auth-check). If yes => forwarding, If not, redirect to /oidc/login which is handled by my flask service (that need to handle oidc client features).

server {

	server_name my-legacy-app-secured.domain;
	include /etc/nginx/common/default_service.conf;

	# Internal access check route
	location = /access_check {
		internal;
		proxy_pass              http://my-flask-authentication-service:8000/legacy-auth-check;
		proxy_pass_request_body off;
		proxy_set_header        Content-Length "";
		proxy_set_header        X-Original-URI $request_uri;
	}

	location /oidc/ {
		proxy_pass http://my-flask-authentication-service:8000/oidc;
		include /etc/nginx/common/default_proxy_params.conf;
	}

	location / {
		auth_request     /access_check;
		auth_request_set $auth_status $upstream_status;
		error_page 401 = /oidc/login;

		proxy_pass http://my-legacy-app/;
		include /etc/nginx/common/default_proxy_params.conf;
	}
}

*Disadvantages: *

  • Using a tricky nginx configuration
  • Need to implement an OIDC management routes (authorize, callback and so on)
  • Don't benefit from Pomerium policy rules

Explain any additional use-cases

None

Additional context

None

mont5piques avatar Aug 12 '22 09:08 mont5piques

If any more details are needed, I'll be happy to explain.

mont5piques avatar Aug 24 '22 06:08 mont5piques