Skip to content

Commit

Permalink
Add SLO Logout (#443)
Browse files Browse the repository at this point in the history
* start putting together SLO

* remove junk, add junk, fix signing

* finalize SLO

* set the logout relay

* less dopiness

* delete the user too

* do not delete the user

* implement suggestions from Bill

* change the action name
  • Loading branch information
aub authored Nov 4, 2016
1 parent c3fc556 commit 2d8f2f4
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 6 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ before_script:
- export SAML_CERTIFICATE_FILE="spec/support/certificates/ruby-saml.crt"
- export SAML_KEY_FILE="spec/support/certificates/ruby-saml.key"
- export SAML_RELAY="http://localhost:3001/auth/login/callback"
- export SAML_LOGOUT_RELAY="http://localhost:3001/logout"
- export REDIS_HOST="localhost"
- export REDIS_PORT="6379"
- export MHV_HOST='https://mock-prescriptions-api.herokuapp.com'
Expand Down
39 changes: 36 additions & 3 deletions app/controllers/v0/sessions_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module V0
class SessionsController < ApplicationController
skip_before_action :authenticate, only: [:new, :saml_callback]
skip_before_action :authenticate, only: [:new, :saml_callback, :saml_logout_callback]

def new
saml_auth_request = OneLogin::RubySaml::Authrequest.new
Expand All @@ -13,8 +13,21 @@ def show
end

def destroy
@session.destroy
head :no_content
logout_request = OneLogin::RubySaml::Logoutrequest.new
logger.info "New SP SLO for userid '#{@session.uuid}'"

saml_settings.name_identifier_value = @session.uuid
saml_settings.security[:logout_requests_signed] = true
saml_settings.security[:embed_sign] = true

render json: { logout_via_get: logout_request.create(saml_settings, RelayState: @session.token) }, status: 202
end

def saml_logout_callback
if params[:SAMLResponse]
# We initiated an SLO and are receiving the bounce-back after the IDP performed it
handle_completed_slo
end
end

def saml_callback
Expand Down Expand Up @@ -93,5 +106,25 @@ def async_create_evss_account(user)
auth_headers = EVSS::AuthHeaders.new(user).to_h
EVSS::CreateUserAccountJob.perform_async(auth_headers)
end

# :nocov:
def handle_completed_slo
logout_response = OneLogin::RubySaml::Logoutresponse.new(params[:SAMLResponse], saml_settings)

logger.info "LogoutResponse is: #{logout_response}"

if !logout_response.validate
logger.error 'The SAML Logout Response is invalid'
redirect_to SAML_CONFIG['logout_relay'] + '?success=false'
elsif logout_response.success?
delete_session(params[:RelayState])
redirect_to SAML_CONFIG['logout_relay'] + '?success=true'
end
end

def delete_session(token)
Session.find(token)&.destroy
end
# :nocov:
end
end
2 changes: 1 addition & 1 deletion config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Application < Rails::Application
allow do
origins { |source, _env| ENV['WEB_ORIGIN'].split(',').include?(source) }
resource '*', headers: :any,
methods: [:get, :post, :put, :delete, :options],
methods: :any,
credentials: true
end
end
Expand Down
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
match '/v0/*path', to: 'application#cors_preflight', via: [:options]

get '/saml/metadata', to: 'saml#metadata'
get '/auth/saml/logout', to: 'v0/sessions#saml_logout_callback', as: 'saml_logout'
post '/auth/saml/callback', to: 'v0/sessions#saml_callback', module: 'v0'

namespace :v0, defaults: { format: 'json' } do
resource :sessions, only: [:new, :destroy] do
post :saml_callback, to: 'sessions#saml_callback'
post :saml_slo_callback, to: 'sessions#saml_slo_callback'
get 'current', to: 'sessions#show'
end

Expand Down
2 changes: 2 additions & 0 deletions config/saml.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ development: &defaults
certificate: <%= File.read(File.expand_path(ENV["SAML_CERTIFICATE_FILE"])).dump %>
key: <%= File.read(File.expand_path(ENV['SAML_KEY_FILE'])).dump %>
relay: http://localhost:3001/auth/login/callback
logout_relay: http://localhost:3001/logout

test:
<<: *defaults
Expand All @@ -18,3 +19,4 @@ production:
certificate: <%= File.read(File.expand_path(ENV["SAML_CERTIFICATE_FILE"])).dump %>
key: <%= File.read(File.expand_path(ENV["SAML_KEY_FILE"])).dump %>
relay: <%= ENV["SAML_RELAY"] %>
logout_relay: <%= ENV["SAML_LOGOUT_RELAY"] %>
3 changes: 1 addition & 2 deletions spec/controllers/v0/sessions_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,8 @@

it 'destroys a session' do
request.env['HTTP_AUTHORIZATION'] = auth_header
expect_any_instance_of(Session).to receive(:destroy)
delete :destroy
expect(response).to have_http_status(:no_content)
expect(response).to have_http_status(202)
end
end
end

0 comments on commit 2d8f2f4

Please sign in to comment.