From a8b1b165faf6746590ac9eb434f3988d9e07361e Mon Sep 17 00:00:00 2001 From: Peter Saxton Date: Wed, 11 Mar 2020 19:13:06 +0000 Subject: [PATCH] wire up passwordless authentication --- Gemfile | 2 +- Gemfile.lock | 38 ++++++++++++++++++++++ app/controllers/session_controller.rb | 45 ++++++++++++++++++++++++++ app/views/layouts/application.html.erb | 6 ++++ config/routes.rb | 4 +++ docker-compose.yml | 3 +- 6 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 app/controllers/session_controller.rb diff --git a/Gemfile b/Gemfile index cacd2f1..9248f9f 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,7 @@ gem 'rails_admin' gem 'redcarpet' gem 'erubis' gem 'rack-attack' +gem 'openid_connect', '~> 1.1', '>= 1.1.8' group :development, :test do gem 'rspec-rails', '4.0.0.beta3' @@ -38,4 +39,3 @@ group :test do gem 'rails-controller-testing' gem 'simplecov', require: false end - diff --git a/Gemfile.lock b/Gemfile.lock index 411dd6a..18e5d6e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -64,7 +64,10 @@ GEM activerecord (>= 5.0, < 6.1) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) + aes_key_wrap (1.0.1) + attr_required (1.0.1) backports (3.15.0) + bindata (2.4.6) bindex (0.8.1) builder (3.2.4) byebug (11.1.1) @@ -124,6 +127,7 @@ GEM haml (5.1.2) temple (>= 0.8.0) tilt + httpclient (2.8.3) i18n (1.8.2) concurrent-ruby (~> 1.0) jquery-rails (4.3.5) @@ -133,6 +137,10 @@ GEM jquery-ui-rails (6.0.1) railties (>= 3.2.16) json (2.3.0) + json-jwt (1.11.0) + activesupport (>= 4.2) + aes_key_wrap + bindata kaminari (1.1.1) activesupport (>= 4.1.0) kaminari-actionview (= 1.1.1) @@ -169,6 +177,16 @@ GEM nio4r (2.5.2) nokogiri (1.10.8) mini_portile2 (~> 2.4.0) + openid_connect (1.1.8) + activemodel + attr_required (>= 1.0.0) + json-jwt (>= 1.5.0) + rack-oauth2 (>= 1.6.1) + swd (>= 1.0.0) + tzinfo + validate_email + validate_url + webfinger (>= 1.0.1) pg (1.2.2) public_suffix (4.0.2) puma (4.3.3) @@ -176,6 +194,12 @@ GEM rack (2.0.8) rack-attack (6.2.2) rack (>= 1.0, < 3) + rack-oauth2 (1.10.1) + activesupport + attr_required + httpclient + json-jwt (>= 1.11.0) + rack rack-pjax (1.1.0) nokogiri (~> 1.5) rack (>= 1.1) @@ -276,6 +300,10 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) + swd (1.1.2) + activesupport (>= 3) + attr_required (>= 0.0.5) + httpclient (>= 2.4) temple (0.8.2) thor (1.0.1) thread_safe (0.3.6) @@ -287,11 +315,20 @@ GEM thread_safe (~> 0.1) uglifier (4.2.0) execjs (>= 0.3.0, < 3) + validate_email (0.1.6) + activemodel (>= 3.0) + mail (>= 2.2.5) + validate_url (1.0.8) + activemodel (>= 3.0.0) + public_suffix web-console (3.7.0) actionview (>= 5.0) activemodel (>= 5.0) bindex (>= 0.4.0) railties (>= 5.0) + webfinger (1.1.0) + activesupport + httpclient (>= 2.4) websocket-driver (0.7.1) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.4) @@ -313,6 +350,7 @@ DEPENDENCIES faker jquery-rails listen + openid_connect (~> 1.1, >= 1.1.8) pg (= 1.2.2) puma rack-attack diff --git a/app/controllers/session_controller.rb b/app/controllers/session_controller.rb new file mode 100644 index 0000000..26e00ab --- /dev/null +++ b/app/controllers/session_controller.rb @@ -0,0 +1,45 @@ + +class SessionController < ApplicationController + + def authenticate + config = OpenIDConnect::Discovery::Provider::Config.discover! "https://did.app" + + client = OpenIDConnect::Client.new({ + identifier: ENV["CLIENT_ID"], + secret: ENV["CLIENT_SECRET"], + redirect_uri: "http://localhost:3000/session/callback", + issuer: config.issuer, + authorization_endpoint: config.authorization_endpoint, + jwks_uri: config.jwks_uri, + token_endpoint: config.token_endpoint, + }) + redirect_to client.authorization_uri() + end + + def callback + config = OpenIDConnect::Discovery::Provider::Config.discover! "https://did.app" + + client = OpenIDConnect::Client.new({ + identifier: ENV["CLIENT_ID"], + secret: ENV["CLIENT_SECRET"], + redirect_uri: "http://localhost:3000/session/callback", + issuer: config.issuer, + authorization_endpoint: config.authorization_endpoint, + jwks_uri: config.jwks_uri, + token_endpoint: config.token_endpoint, + }) + code = params["code"] + client.authorization_code = code + tokens = client.access_token! + + id_token = OpenIDConnect::ResponseObject::IdToken.decode tokens.id_token, config.jwks + id_token.verify!(issuer: config.issuer, client_id: client.identifier) + session[:current_user_id] = id_token.subject + redirect_to root_path + end + def terminate + session[:current_user_id] = nil + redirect_to root_path + end + +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 34428ac..d12e50b 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -24,6 +24,12 @@
  • <%= link_to 'Speakers', speakers_path %>
  • <%= link_to 'Proposals', proposals_path %>
  • <%= link_to 'Events', events_path %>
  • + <% if session[:current_user_id] %> +
  • <%= session[:current_user_id] %>
  • +
  • <%= link_to 'Sign out', sign_out_path %>
  • + <% else %> +
  • <%= link_to 'Sign in', sign_in_path %>
  • + <% end %> diff --git a/config/routes.rb b/config/routes.rb index 9167da8..3856114 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,4 +8,8 @@ resources :events, only: [:index, :show] resources :event_instances, only: [:new, :create, :show] resources :tags, only: [:show] + + get '/session/authenticate', to: 'session#authenticate', as: 'sign_in' + get '/session/callback', to: 'session#callback' + get '/session/terminate', to: 'session#terminate', as: 'sign_out' end diff --git a/docker-compose.yml b/docker-compose.yml index 58be121..ad8985d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,13 +12,14 @@ services: - 3000:3000 volumes: - ./:/opt/app - - rails_tmp:/opt/app/tmp depends_on: - db environment: - RECAPTCHA_SITE_KEY=aaaaa - RAILS_ADMIN_USERNAME=rails - RAILS_ADMIN_PASSWORD=rails + - CLIENT_ID=test_0xKvM6N9 + - CLIENT_SECRET=test_y2650o6pLoxNejD9 db: image: postgres:11.2 ports: