From 4eb8c28d9db50126faaf9b97a8a60cf0b5b37260 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Wed, 27 Mar 2024 15:40:18 -0400 Subject: [PATCH 01/12] WIP; Basic openid_connect setup; much more to do --- Gemfile | 1 + Gemfile.lock | 47 +++++++++++++++++++++++++ app/helpers/application_helper.rb | 9 +++-- app/models/concerns/omniauth_support.rb | 4 ++- app/models/user.rb | 2 ++ config/initializers/devise.rb | 15 ++++++++ config/routes.rb | 3 ++ 7 files changed, 75 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index 9be0c7eb29d..d240b1fc4ef 100644 --- a/Gemfile +++ b/Gemfile @@ -88,6 +88,7 @@ gem 'doorkeeper' gem 'omniauth', '~> 2.1' gem 'omniauth-oauth2', '~> 1.7.3' +gem 'omniauth_openid_connect' gem 'omniauth-rails_csrf_protection', '~> 1.0.1' gem 'faraday', '~> 2.2' gem 'oauth2' diff --git a/Gemfile.lock b/Gemfile.lock index f1507db7f9f..b2ddf460651 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -143,6 +143,7 @@ GEM activerecord (>= 5.0, < 6.2) addressable (2.8.5) public_suffix (>= 2.0.2, < 6.0) + aes_key_wrap (1.1.0) airbrussh (1.4.1) sshkit (>= 1.6.1, != 1.7.0) ajax_modal_rails (1.0.12) @@ -154,6 +155,7 @@ GEM ast (2.4.2) attr_encrypted (3.1.0) encryptor (~> 3.0.0) + attr_required (1.0.2) attribute_normalizer (1.2.0) authtrail (0.4.3) activerecord (>= 5.2) @@ -255,6 +257,7 @@ GEM benchmark-malloc (0.2.0) benchmark-perf (0.6.0) benchmark-trend (0.4.0) + bindata (2.5.0) bindex (0.8.1) bootsnap (1.9.1) msgpack (~> 1.0) @@ -411,6 +414,8 @@ GEM dry-initializer (3.1.1) ed25519 (1.3.0) email_check (1.0.1) + email_validator (2.2.4) + activemodel encryptor (3.0.0) erubi (1.12.0) erubis (2.7.0) @@ -426,6 +431,8 @@ GEM base64 faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) + faraday-follow_redirects (0.3.0) + faraday (>= 1, < 3) faraday-multipart (1.0.4) multipart-post (~> 2) faraday-net_http (2.1.0) @@ -512,6 +519,13 @@ GEM jsbundling-rails (1.2.1) railties (>= 6.0.0) json (2.6.3) + json-jwt (1.16.6) + activesupport (>= 4.2) + aes_key_wrap + base64 + bindata + faraday (~> 2.0) + faraday-follow_redirects json_schemer (2.0.0) hana (~> 1.3) regexp_parser (~> 2.0) @@ -629,6 +643,22 @@ GEM omniauth-rails_csrf_protection (1.0.1) actionpack (>= 4.2) omniauth (~> 2.0) + omniauth_openid_connect (0.7.1) + omniauth (>= 1.9, < 3) + openid_connect (~> 2.2) + openid_connect (2.3.0) + activemodel + attr_required (>= 1.0.0) + email_validator + faraday (~> 2.0) + faraday-follow_redirects + json-jwt (>= 1.16) + mail + rack-oauth2 (~> 2.2) + swd (~> 2.0) + tzinfo + validate_url + webfinger (~> 2.0) options (2.3.2) order_as_specified (1.7) activerecord (>= 5.0.0) @@ -675,6 +705,13 @@ GEM rack (>= 2.0.0) rack-mini-profiler (2.3.3) rack (>= 1.2.0) + rack-oauth2 (2.2.1) + activesupport + attr_required + faraday (~> 2.0) + faraday-follow_redirects + json-jwt (>= 1.11.0) + rack (>= 2.1.0) rack-protection (3.0.5) rack rack-test (2.1.0) @@ -891,6 +928,11 @@ GEM stackprof (0.2.17) strong_migrations (1.4.4) activerecord (>= 5.2) + swd (2.0.3) + activesupport (>= 3) + attr_required (>= 0.0.5) + faraday (~> 2.0) + faraday-follow_redirects sync (0.5.0) temple (0.8.2) term-ansicolor (1.7.1) @@ -934,6 +976,10 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) + webfinger (2.1.3) + activesupport + faraday (~> 2.0) + faraday-follow_redirects webmock (3.14.0) addressable (>= 2.8.0) crack (>= 0.3.2) @@ -1113,6 +1159,7 @@ DEPENDENCIES omniauth (~> 2.1) omniauth-oauth2 (~> 1.7.3) omniauth-rails_csrf_protection (~> 1.0.1) + omniauth_openid_connect order_as_specified overcommit pagy diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 19568978611..b11ec5fc8be 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -398,11 +398,10 @@ def hmis_admin_visible? end def omni_auth_providers - if ENV['OKTA_DOMAIN'].present? - [['Okta', '/users/auth/okta']] - else - [] - end + providers = [] + providers << ['Okta', '/users/auth/okta'] if ENV['OKTA_DOMAIN'].present? + providers << [ENV['IDP_HUMAN_NAME'], user_openid_connect_omniauth_authorize_path] if ENV['IDP_NAME'].present? + providers end def foreground_color(bg_color) diff --git a/app/models/concerns/omniauth_support.rb b/app/models/concerns/omniauth_support.rb index 2ebec11584b..f57da4e2c41 100644 --- a/app/models/concerns/omniauth_support.rb +++ b/app/models/concerns/omniauth_support.rb @@ -32,7 +32,9 @@ def find_or_build_for_oauth(email:) # Does this user use an external identity provider. #provider says which one. # All other methods should return safe values if this is false. def external_idp? - ENV['OKTA_DOMAIN'].present? && OauthIdentity.for_user(self).any? + okta = ENV['OKTA_DOMAIN'].present? && OauthIdentity.for_user(self).any? + openid_connect = ENV['IDP_NAME'].present? + okta || openid_connect end # Remove the IDP present, reseting the password and diff --git a/app/models/user.rb b/app/models/user.rb index 6e319b88799..c4266408569 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -15,6 +15,8 @@ class User < ApplicationRecord USER_PROJECT_ID_PREFIX = "#{USER_PERMISSION_PREFIX}_project_ids".freeze EXPIRY_MINUTES = 5 + devise :omniauthable, omniauth_providers: [:openid_connect] + has_many :user_group_members, dependent: :destroy, inverse_of: :user has_many :user_groups, through: :user_group_members has_many :access_controls, through: :user_groups diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 36ba8438e54..779e3ef7e5d 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -8,6 +8,21 @@ manager.default_strategies(scope: :user).unshift :two_factor_backupable manager.failure_app = CustomAuthFailure end + config.omniauth :openid_connect, { + name: ENV['IDP_NAME'], + scope: [:openid, :email, :profile, :address], + response_type: :code, + uid_field: 'email', + client_options: { + port: ENV['IDP_PORT'], + scheme: ENV['IDP_SCHEME'], + host: ENV['IDP_HOST'], + identifier: ENV['IDP_CLIENT_ID'], + secret: ENV['IDP_SECRET_KEY'], + redirect_uri: ENV['IDP_REDIRECT_URI'], + token_endpoint: ENV['IDP_TOKEN_ENDPOINT'] + }, + } # The secret key used by Devise. Devise uses this key to generate # random tokens. Changing this key will render invalid all existing diff --git a/config/routes.rb b/config/routes.rb index 9dbbab378d4..384410cedbb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,6 +27,9 @@ def matches?(request) if ENV['OKTA_DOMAIN'].present? get "/users/auth/okta/callback" => "users/omniauth_callbacks#okta" if ENV['OKTA_CLIENT_ID'] end + if ENV['OKTA_DOMAIN'].present? + get "/users/auth/okta/callback" => "users/omniauth_callbacks#okta" if ENV['IDP_NAME'].present? + end end namespace :users do From ab3537b565354dfda7830a0ab95b77b4bbbc0688 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Tue, 14 May 2024 15:16:21 -0400 Subject: [PATCH 02/12] WIP; connecting to dex, needs official certificate --- config/initializers/devise.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 779e3ef7e5d..862ede1056d 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -20,7 +20,12 @@ identifier: ENV['IDP_CLIENT_ID'], secret: ENV['IDP_SECRET_KEY'], redirect_uri: ENV['IDP_REDIRECT_URI'], - token_endpoint: ENV['IDP_TOKEN_ENDPOINT'] + token_endpoint: ENV['IDP_TOKEN_ENDPOINT'], + # FIXME: Development only + ssl: { + verify: false, + verify_mode: 0 + }, }, } From c7a8c2a625a40bb7183963d54c73b888734279f6 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Tue, 14 May 2024 18:58:23 -0400 Subject: [PATCH 03/12] WIP; don't verify SSL cert in development --- config/initializers/devise.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 862ede1056d..1f6824b634e 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -8,6 +8,12 @@ manager.default_strategies(scope: :user).unshift :two_factor_backupable manager.failure_app = CustomAuthFailure end + + # This needs to be silenced because it may have already been set + silence_warnings do + OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE if Rails.env.development? + end + config.omniauth :openid_connect, { name: ENV['IDP_NAME'], scope: [:openid, :email, :profile, :address], @@ -23,8 +29,7 @@ token_endpoint: ENV['IDP_TOKEN_ENDPOINT'], # FIXME: Development only ssl: { - verify: false, - verify_mode: 0 + verify: ! Rails.env.development?, }, }, } From b7dc0883bb96316fbb39929168f8fbeb24d83226 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Wed, 15 May 2024 16:02:00 -0400 Subject: [PATCH 04/12] Some oauth-proxy infrastructure --- .gitignore | 1 + dev/auth/dex.yaml | 33 ++++++++++++++++++++++++++++++++ dev/auth/oauth2-proxy.cfg | 18 ++++++++++++++++++ docker/docker-compose.yml | 40 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 dev/auth/dex.yaml create mode 100644 dev/auth/oauth2-proxy.cfg diff --git a/.gitignore b/.gitignore index 398e3de366a..edb0e10e774 100644 --- a/.gitignore +++ b/.gitignore @@ -68,6 +68,7 @@ untracked docker-compose.dev.yml yarn-error.log /dev/minio/* +/dev/auth/certs/* # docker deployment docker/deploy/REVISION diff --git a/dev/auth/dex.yaml b/dev/auth/dex.yaml new file mode 100644 index 00000000000..6683f3a6e03 --- /dev/null +++ b/dev/auth/dex.yaml @@ -0,0 +1,33 @@ +# https://github.com/oauth2-proxy/oauth2-proxy/blob/master/contrib/local-environment/dex.yaml +# This configuration is intended to be used with the docker-compose testing +# environment. +# This should configure Dex to run on port 4190 and provides a static login +issuer: http://dex.dev.test:4190/dex +storage: + type: etcd + config: + endpoints: + - http://etcd:2379 + namespace: dex/ +web: + http: 0.0.0.0:4190 +oauth2: + skipApprovalScreen: true +expiry: + signingKeys: "4h" + idTokens: "1h" +staticClients: +- id: oauth2-proxy + redirectURIs: + # These redirect URIs point to the `--redirect-url` for OAuth2 proxy. + - 'http://oauth2-proxy.dev.test:4180/oauth2/callback' # For basic proxy example. + # - 'http://oauth2-proxy.oauth2-proxy.localhost/oauth2/callback' # For nginx and traefik example. + name: 'OAuth2 Proxy' + secret: b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK +enablePasswordDB: true +staticPasswords: +- email: "admin@example.com" + # bcrypt hash of the string "password" + hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" + username: "admin" + userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" diff --git a/dev/auth/oauth2-proxy.cfg b/dev/auth/oauth2-proxy.cfg new file mode 100644 index 00000000000..c8afb011297 --- /dev/null +++ b/dev/auth/oauth2-proxy.cfg @@ -0,0 +1,18 @@ +http_address="0.0.0.0:4180" +cookie_secret="OQINaROshtE9TcZkNAm-5Zs2Pv3xaWytBmc5W7sPX7w=" +email_domains="example.com" +cookie_secure="false" +upstreams="http://hmis-warehouse.dev.test" +cookie_domains=[".dev.test", "oauth2-proxy.dev.test"] # Required so cookie can be read on all subdomains. +whitelist_domains=[".dev.test", "oauth2-proxy.dev.test", "hmis-warehouse.dev.test"] # Required to allow redirection back to original requested target. +# tls_cert_file="/etc/certs/dev.test.crt" +# tls_key_file="/etc/certs/dev.test.key" + +# dex provider +client_secret="b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK" +client_id="oauth2-proxy" +redirect_url="http://oauth2-proxy.dev.test:4180/oauth2/callback" + +oidc_issuer_url="http://dex.dev.test:4190/dex" +provider="oidc" +provider_display_name="Dex" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index b50c117f1ab..76406226de4 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -262,6 +262,46 @@ services: - 9000:9000 - 9001:9001 # enable for UI access command: server --certs-dir /certs /data + # Access http://oauth2-proxy.dev.test:4180 to initiate a login cycle + oauth2-proxy: + container_name: oauth2-proxy + image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 + command: --config /oauth2-proxy.cfg + hostname: oauth2-proxy.dev.test + volumes: + - "./dev/auth/oauth2-proxy.cfg:/oauth2-proxy.cfg" + - "./dev/auth/certs/dev.test.crt:/etc/certs/dev.test.crt" + - "./dev/auth/certs/dev.test.key:/etc/certs/dev.test.key" + restart: unless-stopped + ports: + - 4180:4180/tcp + depends_on: + - dex + dex: + container_name: dex + image: ghcr.io/dexidp/dex:v2.39.0 + command: dex serve /dex.yaml + hostname: dex + volumes: + - "./dev/auth/dex.yaml:/dex.yaml" + - "./dev/auth/certs/dev.test.crt:/etc/certs/dev.test.crt" + - "./dev/auth/certs/dev.test.key:/etc/certs/dev.test.key" + restart: unless-stopped + ports: + - 4190:4190/tcp + networks: + default: + aliases: + - dex.dev.test + depends_on: + - etcd + etcd: + container_name: etcd + image: gcr.io/etcd-development/etcd:v3.5.13 + entrypoint: /usr/local/bin/etcd + command: + - --listen-client-urls=http://0.0.0.0:2379 + - --advertise-client-urls=http://etcd:2379 volumes: bundle_alpine: From 72c212cdb0d353a893c66d96481910ffd54d4703 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Fri, 17 May 2024 12:03:38 -0400 Subject: [PATCH 05/12] Functional with TLS --- dev/auth/dex.yaml | 16 +++++++++++++--- dev/auth/oauth2-proxy.cfg | 20 ++++++++++++-------- docker/docker-compose.yml | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/dev/auth/dex.yaml b/dev/auth/dex.yaml index 6683f3a6e03..3f94f015a1e 100644 --- a/dev/auth/dex.yaml +++ b/dev/auth/dex.yaml @@ -2,7 +2,7 @@ # This configuration is intended to be used with the docker-compose testing # environment. # This should configure Dex to run on port 4190 and provides a static login -issuer: http://dex.dev.test:4190/dex +issuer: https://dex.dev.test:4190/dex storage: type: etcd config: @@ -10,7 +10,17 @@ storage: - http://etcd:2379 namespace: dex/ web: - http: 0.0.0.0:4190 + # http: 0.0.0.0:4190 + https: 0.0.0.0:4190 + tlsCert: /etc/certs/dev.test.crt + tlsKey: /etc/certs/dev.test.key + tlsClientCA: /etc/certs/root-ca.pem + # headers: + # X-Frame-Options: "DENY" + # X-Content-Type-Options: "nosniff" + # X-XSS-Protection: "1; mode=block" + # Content-Security-Policy: "default-src 'self'" + # Strict-Transport-Security: "max-age=31536000; includeSubDomains" oauth2: skipApprovalScreen: true expiry: @@ -20,7 +30,7 @@ staticClients: - id: oauth2-proxy redirectURIs: # These redirect URIs point to the `--redirect-url` for OAuth2 proxy. - - 'http://oauth2-proxy.dev.test:4180/oauth2/callback' # For basic proxy example. + - 'https://oauth2-proxy.dev.test:4180/oauth2/callback' # For basic proxy example. # - 'http://oauth2-proxy.oauth2-proxy.localhost/oauth2/callback' # For nginx and traefik example. name: 'OAuth2 Proxy' secret: b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK diff --git a/dev/auth/oauth2-proxy.cfg b/dev/auth/oauth2-proxy.cfg index c8afb011297..e06fd283b8b 100644 --- a/dev/auth/oauth2-proxy.cfg +++ b/dev/auth/oauth2-proxy.cfg @@ -1,18 +1,22 @@ http_address="0.0.0.0:4180" cookie_secret="OQINaROshtE9TcZkNAm-5Zs2Pv3xaWytBmc5W7sPX7w=" -email_domains="example.com" -cookie_secure="false" -upstreams="http://hmis-warehouse.dev.test" -cookie_domains=[".dev.test", "oauth2-proxy.dev.test"] # Required so cookie can be read on all subdomains. +email_domains="*" +cookie_secure="true" +force_https="true" +https_address="oauth2-proxy.dev.test:4180" +# upstreams=["http://httpbin.localtest.me"] +upstreams=["http://hmis-warehouse.dev.test:3000"] +cookie_domains=[".dev.test", "oauth2-proxy.dev.test", "hmis-warehouse.dev.test"] # Required so cookie can be read on all subdomains. whitelist_domains=[".dev.test", "oauth2-proxy.dev.test", "hmis-warehouse.dev.test"] # Required to allow redirection back to original requested target. -# tls_cert_file="/etc/certs/dev.test.crt" -# tls_key_file="/etc/certs/dev.test.key" +tls_cert_file="/etc/certs/dev.test.crt" +tls_key_file="/etc/certs/dev.test.key" +provider_ca_files="/etc/certs/root-ca.pem" # dex provider client_secret="b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK" client_id="oauth2-proxy" -redirect_url="http://oauth2-proxy.dev.test:4180/oauth2/callback" +redirect_url="https://oauth2-proxy.dev.test:4180/oauth2/callback" -oidc_issuer_url="http://dex.dev.test:4190/dex" +oidc_issuer_url="https://dex.dev.test:4190/dex" provider="oidc" provider_display_name="Dex" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 76406226de4..384754f0245 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -151,6 +151,11 @@ services: condition: service_started yarn: condition: service_started + hostname: hmis-warehouse.dev.test + networks: + default: + aliases: + - hmis-warehouse.dev.test # To transition from a previous major version to pg13, run ./docker/pg13/upgrade.db db_previous: @@ -263,6 +268,12 @@ services: - 9001:9001 # enable for UI access command: server --certs-dir /certs /data # Access http://oauth2-proxy.dev.test:4180 to initiate a login cycle + # some useful notes about setting up SSL certs + # mkcert -install + # mkcert dev.test "*.dev.test" localhost 127.0.0.1 ::1 + # mkcert -CACERT + # copy the certs and CA cert to dev/auth/certs/ + oauth2-proxy: container_name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 @@ -272,6 +283,7 @@ services: - "./dev/auth/oauth2-proxy.cfg:/oauth2-proxy.cfg" - "./dev/auth/certs/dev.test.crt:/etc/certs/dev.test.crt" - "./dev/auth/certs/dev.test.key:/etc/certs/dev.test.key" + - "./dev/auth/certs/ca/rootCA.pem:/etc/certs/root-ca.pem" restart: unless-stopped ports: - 4180:4180/tcp @@ -279,6 +291,7 @@ services: - dex dex: container_name: dex + # image: dexidp/dex:latest-alpine image: ghcr.io/dexidp/dex:v2.39.0 command: dex serve /dex.yaml hostname: dex @@ -286,6 +299,7 @@ services: - "./dev/auth/dex.yaml:/dex.yaml" - "./dev/auth/certs/dev.test.crt:/etc/certs/dev.test.crt" - "./dev/auth/certs/dev.test.key:/etc/certs/dev.test.key" + - "./dev/auth/certs/ca/rootCA.pem:/etc/certs/root-ca.pem" restart: unless-stopped ports: - 4190:4190/tcp From 2f4d6d25bb04415282c7f4b629b30bddd6d1e46d Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Fri, 17 May 2024 13:44:28 -0400 Subject: [PATCH 06/12] Spike; oauth2-proxy with dex login functional. Needs to handle many more features. --- app/controllers/application_controller.rb | 30 ++++++++++++ dev/auth/dex.yaml | 23 ++++++---- dev/auth/oauth2-proxy.cfg | 27 +++++++---- docker/docker-compose.yml | 56 +++++++++++++---------- 4 files changed, 94 insertions(+), 42 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4c67f46565d..a4e5b107104 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -40,6 +40,36 @@ class ApplicationController < ActionController::Base prepend_before_action :skip_timeout + # if we have a jwt, use it, + # sign-in user (programmatically) + # if not, call devise authenticate_user! + def authenticate_user! + if valid_jwt? + login_jwt_user + else + super + end + end + + private def valid_jwt? + return false unless ENV['JWT_SECRET'] + + # TODO: how do we validate the JWT? + return true + # decoded = JWT.decode(cookies[:_oauth2_proxy], ENV['JWT_SECRET'])[0] + # raise decoded.inspect + end + + private def login_jwt_user + email = request.headers['HTTP_X_FORWARDED_USER'] + return unless email + + user = User.find_by(email: email.downcase) + return unless user + + sign_in(user) + end + private def resource_name :user end diff --git a/dev/auth/dex.yaml b/dev/auth/dex.yaml index 3f94f015a1e..4be4ca985e3 100644 --- a/dev/auth/dex.yaml +++ b/dev/auth/dex.yaml @@ -2,7 +2,7 @@ # This configuration is intended to be used with the docker-compose testing # environment. # This should configure Dex to run on port 4190 and provides a static login -issuer: https://dex.dev.test:4190/dex +issuer: http://dex.dev.test:4190/dex storage: type: etcd config: @@ -10,11 +10,11 @@ storage: - http://etcd:2379 namespace: dex/ web: - # http: 0.0.0.0:4190 - https: 0.0.0.0:4190 - tlsCert: /etc/certs/dev.test.crt - tlsKey: /etc/certs/dev.test.key - tlsClientCA: /etc/certs/root-ca.pem + http: 0.0.0.0:4190 + # https: 0.0.0.0:4190 + # tlsCert: /etc/certs/dev.test.crt + # tlsKey: /etc/certs/dev.test.key + # tlsClientCA: /etc/certs/root-ca.pem # headers: # X-Frame-Options: "DENY" # X-Content-Type-Options: "nosniff" @@ -27,12 +27,12 @@ expiry: signingKeys: "4h" idTokens: "1h" staticClients: -- id: oauth2-proxy +- id: hmis-warehouse redirectURIs: # These redirect URIs point to the `--redirect-url` for OAuth2 proxy. - - 'https://oauth2-proxy.dev.test:4180/oauth2/callback' # For basic proxy example. + - 'http://hmis-warehouse.dev.test/oauth2/callback' # For basic proxy example. # - 'http://oauth2-proxy.oauth2-proxy.localhost/oauth2/callback' # For nginx and traefik example. - name: 'OAuth2 Proxy' + name: 'HMIS Warehouse' secret: b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK enablePasswordDB: true staticPasswords: @@ -41,3 +41,8 @@ staticPasswords: hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" username: "admin" userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" +- email: "noreply@example.com" + # bcrypt hash of the string "password" + hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" + username: "admin-user" + userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" diff --git a/dev/auth/oauth2-proxy.cfg b/dev/auth/oauth2-proxy.cfg index e06fd283b8b..676a287f38c 100644 --- a/dev/auth/oauth2-proxy.cfg +++ b/dev/auth/oauth2-proxy.cfg @@ -1,22 +1,29 @@ http_address="0.0.0.0:4180" cookie_secret="OQINaROshtE9TcZkNAm-5Zs2Pv3xaWytBmc5W7sPX7w=" email_domains="*" -cookie_secure="true" -force_https="true" -https_address="oauth2-proxy.dev.test:4180" +# cookie_secure="true" +# force_https="true" +# https_address="oauth2-proxy.dev.test:4180" # upstreams=["http://httpbin.localtest.me"] -upstreams=["http://hmis-warehouse.dev.test:3000"] +upstreams=["http://warehouse.dev.test:3000"] cookie_domains=[".dev.test", "oauth2-proxy.dev.test", "hmis-warehouse.dev.test"] # Required so cookie can be read on all subdomains. whitelist_domains=[".dev.test", "oauth2-proxy.dev.test", "hmis-warehouse.dev.test"] # Required to allow redirection back to original requested target. -tls_cert_file="/etc/certs/dev.test.crt" -tls_key_file="/etc/certs/dev.test.key" -provider_ca_files="/etc/certs/root-ca.pem" +pass_access_token="true" +set_xauthrequest="true" +prefer_email_to_user="true" +pass_user_headers="true" +# tls_cert_file="/etc/certs/dev.test.crt" +# tls_key_file="/etc/certs/dev.test.key" +# provider_ca_files="/etc/certs/root-ca.pem" # dex provider client_secret="b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK" -client_id="oauth2-proxy" -redirect_url="https://oauth2-proxy.dev.test:4180/oauth2/callback" +client_id="hmis-warehouse" +redirect_url="http://hmis-warehouse.dev.test/oauth2/callback" -oidc_issuer_url="https://dex.dev.test:4190/dex" +oidc_issuer_url="http://dex.dev.test:4190/dex" provider="oidc" provider_display_name="Dex" + +# These paths don't require authentication +skip_auth_routes=["public_agencies", "public_files/*"] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 384754f0245..590377eca88 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -122,16 +122,16 @@ services: stdin_open: true tty: true command: bin/rails server -b 0.0.0.0 - labels: - - traefik.enable=${TRAEFIK_ENABLED:-false} - - traefik.http.routers.op.entrypoints=web - - traefik.http.routers.op.rule=Host(`${FQDN:-hmis-warehouse.dev.test}`) - - traefik.http.services.op_https.loadbalancer.server.port=3000 - - traefik.http.routers.op_https.rule=Host(`${FQDN:-hmis-warehouse.dev.test}`) - - traefik.http.routers.op_https.tls=true - - traefik.http.routers.op_https.entrypoints=web-secure - - traefik.http.middlewares.op_https.redirectscheme.scheme=https - - traefik.http.routers.op.middlewares=op_https + # labels: + # - traefik.enable=${TRAEFIK_ENABLED:-false} + # - traefik.http.routers.op.entrypoints=web + # - traefik.http.routers.op.rule=Host(`${FQDN:-hmis-warehouse.dev.test}`) + # - traefik.http.services.op_https.loadbalancer.server.port=3000 + # - traefik.http.routers.op_https.rule=Host(`${FQDN:-hmis-warehouse.dev.test}`) + # - traefik.http.routers.op_https.tls=true + # - traefik.http.routers.op_https.entrypoints=web-secure + # - traefik.http.middlewares.op_https.redirectscheme.scheme=https + # - traefik.http.routers.op.middlewares=op_https ports: - "3000" - "9394" @@ -151,11 +151,11 @@ services: condition: service_started yarn: condition: service_started - hostname: hmis-warehouse.dev.test - networks: - default: - aliases: - - hmis-warehouse.dev.test + hostname: warehouse.dev.test + # networks: + # default: + # aliases: + # - hmis-warehouse.dev.test # To transition from a previous major version to pg13, run ./docker/pg13/upgrade.db db_previous: @@ -273,22 +273,32 @@ services: # mkcert dev.test "*.dev.test" localhost 127.0.0.1 ::1 # mkcert -CACERT # copy the certs and CA cert to dev/auth/certs/ - oauth2-proxy: container_name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 command: --config /oauth2-proxy.cfg - hostname: oauth2-proxy.dev.test + hostname: hmis-warehouse.dev.test volumes: - "./dev/auth/oauth2-proxy.cfg:/oauth2-proxy.cfg" - - "./dev/auth/certs/dev.test.crt:/etc/certs/dev.test.crt" - - "./dev/auth/certs/dev.test.key:/etc/certs/dev.test.key" - - "./dev/auth/certs/ca/rootCA.pem:/etc/certs/root-ca.pem" + # - "./dev/auth/certs/dev.test.crt:/etc/certs/dev.test.crt" + # - "./dev/auth/certs/dev.test.key:/etc/certs/dev.test.key" + # - "./dev/auth/certs/ca/rootCA.pem:/etc/certs/root-ca.pem" + labels: + - traefik.enable=${TRAEFIK_ENABLED:-false} + - traefik.http.routers.op.entrypoints=web + - traefik.http.routers.op.rule=Host(`${FQDN:-hmis-warehouse.dev.test}`) + - traefik.http.services.op_https.loadbalancer.server.port=4180 + - traefik.http.routers.op_https.rule=Host(`${FQDN:-hmis-warehouse.dev.test}`) + - traefik.http.routers.op_https.tls=true + - traefik.http.routers.op_https.entrypoints=web-secure + - traefik.http.middlewares.op_https.redirectscheme.scheme=https + - traefik.http.routers.op.middlewares=op_https restart: unless-stopped ports: - 4180:4180/tcp depends_on: - dex + - web dex: container_name: dex # image: dexidp/dex:latest-alpine @@ -297,9 +307,9 @@ services: hostname: dex volumes: - "./dev/auth/dex.yaml:/dex.yaml" - - "./dev/auth/certs/dev.test.crt:/etc/certs/dev.test.crt" - - "./dev/auth/certs/dev.test.key:/etc/certs/dev.test.key" - - "./dev/auth/certs/ca/rootCA.pem:/etc/certs/root-ca.pem" + # - "./dev/auth/certs/dev.test.crt:/etc/certs/dev.test.crt" + # - "./dev/auth/certs/dev.test.key:/etc/certs/dev.test.key" + # - "./dev/auth/certs/ca/rootCA.pem:/etc/certs/root-ca.pem" restart: unless-stopped ports: - 4190:4190/tcp From c687072fae2d12206b94e9cbb2009bd2d0066410 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Fri, 17 May 2024 14:12:31 -0400 Subject: [PATCH 07/12] Logout working --- app/controllers/users/sessions_controller.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index 359f0a796c2..dc16be951a7 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -23,7 +23,12 @@ def create def destroy request.env['last_user'] = current_user - super + if request.headers['HTTP_X_FORWARDED_USER'] + sign_out(current_user) + redirect_to '/oauth2/sign_out' + else + super + end end def keepalive From ee5af78d5df209d4b5781073011fdfa989f223fb Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Fri, 24 May 2024 14:22:12 -0400 Subject: [PATCH 08/12] Switch dex port --- dev/auth/dex.yaml | 11 +++++++---- dev/auth/oauth2-proxy.cfg | 2 +- docker/docker-compose.yml | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/dev/auth/dex.yaml b/dev/auth/dex.yaml index 4be4ca985e3..494c9ba2069 100644 --- a/dev/auth/dex.yaml +++ b/dev/auth/dex.yaml @@ -1,8 +1,8 @@ # https://github.com/oauth2-proxy/oauth2-proxy/blob/master/contrib/local-environment/dex.yaml # This configuration is intended to be used with the docker-compose testing # environment. -# This should configure Dex to run on port 4190 and provides a static login -issuer: http://dex.dev.test:4190/dex +# This should configure Dex to run on port 4443 and provides a static login +issuer: http://dex.dev.test:4443/dex storage: type: etcd config: @@ -10,8 +10,8 @@ storage: - http://etcd:2379 namespace: dex/ web: - http: 0.0.0.0:4190 - # https: 0.0.0.0:4190 + http: 0.0.0.0:4443 + # https: 0.0.0.0:4443 # tlsCert: /etc/certs/dev.test.crt # tlsKey: /etc/certs/dev.test.key # tlsClientCA: /etc/certs/root-ca.pem @@ -43,6 +43,9 @@ staticPasswords: userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" - email: "noreply@example.com" # bcrypt hash of the string "password" + # bash $(echo password | htpasswd -BinC 10 admin | cut -d: -f2) + # hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" + # bash $(echo 'fix-this-password-55-*' | htpasswd -BinC 10 admin | cut -d: -f2) hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" username: "admin-user" userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" diff --git a/dev/auth/oauth2-proxy.cfg b/dev/auth/oauth2-proxy.cfg index 676a287f38c..4c8377e14fb 100644 --- a/dev/auth/oauth2-proxy.cfg +++ b/dev/auth/oauth2-proxy.cfg @@ -21,7 +21,7 @@ client_secret="b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK" client_id="hmis-warehouse" redirect_url="http://hmis-warehouse.dev.test/oauth2/callback" -oidc_issuer_url="http://dex.dev.test:4190/dex" +oidc_issuer_url="http://dex.dev.test:4443/dex" provider="oidc" provider_display_name="Dex" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 590377eca88..bdce82ea5ae 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -312,7 +312,7 @@ services: # - "./dev/auth/certs/ca/rootCA.pem:/etc/certs/root-ca.pem" restart: unless-stopped ports: - - 4190:4190/tcp + - 4443:4443/tcp networks: default: aliases: From cec9239e0f1ce3e2e6970bde6293c6de237a1557 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Mon, 27 May 2024 12:17:52 -0400 Subject: [PATCH 09/12] Unpack and verify the JWT payload --- app/controllers/application_controller.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a4e5b107104..8b1b99f12a7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -53,11 +53,18 @@ def authenticate_user! private def valid_jwt? return false unless ENV['JWT_SECRET'] + return false unless jwt_payload['email_verified'] == true + return false unless jwt_payload['email'] == request.headers['HTTP_X_FORWARDED_USER'] + return false unless jwt_payload['exp'] > Time.now.to_i - # TODO: how do we validate the JWT? - return true - # decoded = JWT.decode(cookies[:_oauth2_proxy], ENV['JWT_SECRET'])[0] - # raise decoded.inspect + # TODO: any additional checks we should do here? Also, I'd rather invert this logic and return true + # if everything looks good, but false if we can't positively verify + + true + end + + private def jwt_payload + @jwt_payload ||= JWT.decode(request.headers['HTTP_X_FORWARDED_ACCESS_TOKEN'], ENV['JWT_SECRET'], false, algorithm: 'RS256').first end private def login_jwt_user From 0116a26c39d1eddcef8b9f99eef7164be82ce41b Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Mon, 27 May 2024 14:50:12 -0400 Subject: [PATCH 10/12] Removing non oauth2-proxy config and code --- app/helpers/application_helper.rb | 9 +++++---- app/models/concerns/omniauth_support.rb | 4 +--- app/models/user.rb | 2 -- config/initializers/devise.rb | 25 ------------------------- config/routes.rb | 3 --- docker/docker-compose.yml | 14 -------------- 6 files changed, 6 insertions(+), 51 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a443841e285..f13acc302cc 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -398,10 +398,11 @@ def hmis_admin_visible? end def omni_auth_providers - providers = [] - providers << ['Okta', '/users/auth/okta'] if ENV['OKTA_DOMAIN'].present? - providers << [ENV['IDP_HUMAN_NAME'], user_openid_connect_omniauth_authorize_path] if ENV['IDP_NAME'].present? - providers + if ENV['OKTA_DOMAIN'].present? + [['Okta', '/users/auth/okta']] + else + [] + end end def foreground_color(bg_color) diff --git a/app/models/concerns/omniauth_support.rb b/app/models/concerns/omniauth_support.rb index f57da4e2c41..2ebec11584b 100644 --- a/app/models/concerns/omniauth_support.rb +++ b/app/models/concerns/omniauth_support.rb @@ -32,9 +32,7 @@ def find_or_build_for_oauth(email:) # Does this user use an external identity provider. #provider says which one. # All other methods should return safe values if this is false. def external_idp? - okta = ENV['OKTA_DOMAIN'].present? && OauthIdentity.for_user(self).any? - openid_connect = ENV['IDP_NAME'].present? - okta || openid_connect + ENV['OKTA_DOMAIN'].present? && OauthIdentity.for_user(self).any? end # Remove the IDP present, reseting the password and diff --git a/app/models/user.rb b/app/models/user.rb index 48550802adf..4bb2859dbc9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -15,8 +15,6 @@ class User < ApplicationRecord USER_PROJECT_ID_PREFIX = "#{USER_PERMISSION_PREFIX}_project_ids".freeze EXPIRY_MINUTES = 5 - devise :omniauthable, omniauth_providers: [:openid_connect] - has_many :user_group_members, dependent: :destroy, inverse_of: :user has_many :user_groups, through: :user_group_members has_many :access_controls, through: :user_groups diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 1f6824b634e..36ba8438e54 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -9,31 +9,6 @@ manager.failure_app = CustomAuthFailure end - # This needs to be silenced because it may have already been set - silence_warnings do - OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE if Rails.env.development? - end - - config.omniauth :openid_connect, { - name: ENV['IDP_NAME'], - scope: [:openid, :email, :profile, :address], - response_type: :code, - uid_field: 'email', - client_options: { - port: ENV['IDP_PORT'], - scheme: ENV['IDP_SCHEME'], - host: ENV['IDP_HOST'], - identifier: ENV['IDP_CLIENT_ID'], - secret: ENV['IDP_SECRET_KEY'], - redirect_uri: ENV['IDP_REDIRECT_URI'], - token_endpoint: ENV['IDP_TOKEN_ENDPOINT'], - # FIXME: Development only - ssl: { - verify: ! Rails.env.development?, - }, - }, - } - # The secret key used by Devise. Devise uses this key to generate # random tokens. Changing this key will render invalid all existing # confirmation, reset password and unlock tokens in the database. diff --git a/config/routes.rb b/config/routes.rb index 3455e94afde..ff64eee4110 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,9 +24,6 @@ def matches?(request) if ENV['OKTA_DOMAIN'].present? get "/users/auth/okta/callback" => "users/omniauth_callbacks#okta" if ENV['OKTA_CLIENT_ID'] end - if ENV['OKTA_DOMAIN'].present? - get "/users/auth/okta/callback" => "users/omniauth_callbacks#okta" if ENV['IDP_NAME'].present? - end end namespace :users do diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index bdce82ea5ae..d545c087bb5 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -122,16 +122,6 @@ services: stdin_open: true tty: true command: bin/rails server -b 0.0.0.0 - # labels: - # - traefik.enable=${TRAEFIK_ENABLED:-false} - # - traefik.http.routers.op.entrypoints=web - # - traefik.http.routers.op.rule=Host(`${FQDN:-hmis-warehouse.dev.test}`) - # - traefik.http.services.op_https.loadbalancer.server.port=3000 - # - traefik.http.routers.op_https.rule=Host(`${FQDN:-hmis-warehouse.dev.test}`) - # - traefik.http.routers.op_https.tls=true - # - traefik.http.routers.op_https.entrypoints=web-secure - # - traefik.http.middlewares.op_https.redirectscheme.scheme=https - # - traefik.http.routers.op.middlewares=op_https ports: - "3000" - "9394" @@ -152,10 +142,6 @@ services: yarn: condition: service_started hostname: warehouse.dev.test - # networks: - # default: - # aliases: - # - hmis-warehouse.dev.test # To transition from a previous major version to pg13, run ./docker/pg13/upgrade.db db_previous: From 62044e527f244746b8f2b9c05a5e5f8a056b65a3 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Mon, 27 May 2024 14:51:24 -0400 Subject: [PATCH 11/12] Remove unused gem --- Gemfile | 1 - Gemfile.lock | 47 ----------------------------------------------- 2 files changed, 48 deletions(-) diff --git a/Gemfile b/Gemfile index d4430b9c699..32c0e12d4fc 100644 --- a/Gemfile +++ b/Gemfile @@ -89,7 +89,6 @@ gem 'doorkeeper' gem 'omniauth', '~> 2.1' gem 'omniauth-oauth2', '~> 1.7.3' -gem 'omniauth_openid_connect' gem 'omniauth-rails_csrf_protection', '~> 1.0.1' gem 'faraday', '~> 2.2' gem 'oauth2' diff --git a/Gemfile.lock b/Gemfile.lock index ac76e5613ee..760fda2b75c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -159,7 +159,6 @@ GEM activerecord (>= 6.0, < 7.1) addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) - aes_key_wrap (1.1.0) airbrussh (1.5.1) sshkit (>= 1.6.1, != 1.7.0) ajax_modal_rails (1.0.12) @@ -171,7 +170,6 @@ GEM ast (2.4.2) attr_encrypted (4.0.0) encryptor (~> 3.0.0) - attr_required (1.0.2) attribute_normalizer (1.2.0) authtrail (0.5.0) railties (>= 6.1) @@ -278,7 +276,6 @@ GEM benchmark-perf (0.6.0) benchmark-trend (0.4.0) bigdecimal (3.1.7) - bindata (2.5.0) bindex (0.8.1) bootsnap (1.18.3) msgpack (~> 1.2) @@ -436,8 +433,6 @@ GEM dry-initializer (3.1.1) ed25519 (1.3.0) email_check (1.0.2) - email_validator (2.2.4) - activemodel encryptor (3.0.0) erubi (1.12.0) erubis (2.7.0) @@ -451,8 +446,6 @@ GEM i18n (>= 1.8.11, < 2) faraday (2.9.0) faraday-net_http (>= 2.0, < 3.2) - faraday-follow_redirects (0.3.0) - faraday (>= 1, < 3) faraday-multipart (1.0.4) multipart-post (~> 2) faraday-net_http (3.1.0) @@ -541,13 +534,6 @@ GEM jsbundling-rails (1.3.0) railties (>= 6.0.0) json (2.7.1) - json-jwt (1.16.6) - activesupport (>= 4.2) - aes_key_wrap - base64 - bindata - faraday (~> 2.0) - faraday-follow_redirects json_schemer (2.0.0) hana (~> 1.3) regexp_parser (~> 2.0) @@ -670,22 +656,6 @@ GEM omniauth-rails_csrf_protection (1.0.1) actionpack (>= 4.2) omniauth (~> 2.0) - omniauth_openid_connect (0.7.1) - omniauth (>= 1.9, < 3) - openid_connect (~> 2.2) - openid_connect (2.3.0) - activemodel - attr_required (>= 1.0.0) - email_validator - faraday (~> 2.0) - faraday-follow_redirects - json-jwt (>= 1.16) - mail - rack-oauth2 (~> 2.2) - swd (~> 2.0) - tzinfo - validate_url - webfinger (~> 2.0) options (2.3.2) order_as_specified (1.7) activerecord (>= 5.0.0) @@ -735,13 +705,6 @@ GEM rack (>= 2.0.0) rack-mini-profiler (3.3.1) rack (>= 1.2.0) - rack-oauth2 (2.2.1) - activesupport - attr_required - faraday (~> 2.0) - faraday-follow_redirects - json-jwt (>= 1.11.0) - rack (>= 2.1.0) rack-protection (3.2.0) base64 (>= 0.1.0) rack (~> 2.2, >= 2.2.4) @@ -979,11 +942,6 @@ GEM strong_migrations (1.8.0) activerecord (>= 5.2) strscan (3.1.0) - swd (2.0.3) - activesupport (>= 3) - attr_required (>= 0.0.5) - faraday (~> 2.0) - faraday-follow_redirects sync (0.5.0) temple (0.10.3) term-ansicolor (1.7.2) @@ -1028,10 +986,6 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webfinger (2.1.3) - activesupport - faraday (~> 2.0) - faraday-follow_redirects webmock (3.23.0) addressable (>= 2.8.0) crack (>= 0.3.2) @@ -1210,7 +1164,6 @@ DEPENDENCIES omniauth (~> 2.1) omniauth-oauth2 (~> 1.7.3) omniauth-rails_csrf_protection (~> 1.0.1) - omniauth_openid_connect order_as_specified overcommit pagy From 30941e737c65ec077b88d8f877b0a0445601ee90 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Tue, 28 May 2024 09:32:24 -0400 Subject: [PATCH 12/12] Login process updates; notes for future development; better docker-compose behavior --- app/controllers/application_controller.rb | 6 ++++++ app/controllers/root_controller.rb | 3 +++ config/initializers/jwt.rb | 1 + docker/docker-compose.yml | 3 ++- 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 config/initializers/jwt.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8b1b99f12a7..499328ba483 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -64,6 +64,7 @@ def authenticate_user! end private def jwt_payload + # FIXME: this needs to validate the cookie (false should be true) @jwt_payload ||= JWT.decode(request.headers['HTTP_X_FORWARDED_ACCESS_TOKEN'], ENV['JWT_SECRET'], false, algorithm: 'RS256').first end @@ -71,9 +72,14 @@ def authenticate_user! email = request.headers['HTTP_X_FORWARDED_USER'] return unless email + # TODO: should this potentially do a find_or_create_by? user = User.find_by(email: email.downcase) return unless user + # TODO: Need to check expiration/re-request a token so we aren't signed out + # after 30 minutes if we're active + return if user_signed_in? + sign_in(user) end diff --git a/app/controllers/root_controller.rb b/app/controllers/root_controller.rb index b6900c647de..566d6c0d019 100644 --- a/app/controllers/root_controller.rb +++ b/app/controllers/root_controller.rb @@ -7,6 +7,9 @@ class RootController < ApplicationController skip_before_action :authenticate_user! def index + # Handle oauth2-proxy logins + login_jwt_user if valid_jwt? && ! user_signed_in? + # custom_content = lookup_context.exists?('homepage_content', ['root'], true) return unless current_user diff --git a/config/initializers/jwt.rb b/config/initializers/jwt.rb new file mode 100644 index 00000000000..cdb490f09e0 --- /dev/null +++ b/config/initializers/jwt.rb @@ -0,0 +1 @@ +JWT.configuration.strict_base64_decoding = true diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index d545c087bb5..dfa1b87f663 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -141,6 +141,8 @@ services: condition: service_started yarn: condition: service_started + oauth2-proxy: + condition: service_started hostname: warehouse.dev.test # To transition from a previous major version to pg13, run ./docker/pg13/upgrade.db @@ -284,7 +286,6 @@ services: - 4180:4180/tcp depends_on: - dex - - web dex: container_name: dex # image: dexidp/dex:latest-alpine