Skip to content

Commit

Permalink
Return to client app after logout
Browse files Browse the repository at this point in the history
  • Loading branch information
victormours committed Nov 15, 2024
1 parent 1378da0 commit 531860d
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 55 deletions.
21 changes: 17 additions & 4 deletions app/controllers/agents/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,27 @@ def create
end

def destroy
if session[:agent_connect_id_token]
sign_out(:agent) && set_flash_message!(:notice, :signed_out)
if params[:oauth_client_app_id].present? && params[:oauth_client_app_id].in?(session[:oauth_app_ids])
oauth_app = Doorkeeper::Application.find_by(uid: params[:oauth_client_app_id])
@oauth_client_app_post_logout_redirect_url = oauth_app.post_logout_redirect_uri
end

agent_connect_id_token = session.delete(:agent_connect_id_token)

sign_out(:agent)

if @oauth_client_app_post_logout_redirect_url
session[:post_logout_redirect_url] = @oauth_client_app_post_logout_redirect_url
else
set_flash_message!(:notice, :signed_out)
end

agent_connect_client = AgentConnectOpenIdClient::Logout.new(session.delete(:agent_connect_id_token))
if agent_connect_id_token
agent_connect_client = AgentConnectOpenIdClient::Logout.new(agent_connect_id_token)

redirect_to agent_connect_client.agent_connect_logout_url(root_url), allow_other_host: true
else
super
redirect_to after_sign_out_path_for(:agent)
end
end

Expand Down
5 changes: 3 additions & 2 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ def after_sign_in_path_for(resource)
end

def after_sign_out_path_for(resource)
return "https://#{ENV['FRANCECONNECT_HOST']}/api/v1/logout" \
if @connected_with_franceconnect
if @connected_with_franceconnect
return "https://#{ENV['FRANCECONNECT_HOST']}/api/v1/logout"
end

super
end
Expand Down
30 changes: 22 additions & 8 deletions app/controllers/search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,32 @@ class SearchController < ApplicationController
# utilisé par le Pas-de-Calais pour prendre rdv depuis leur site : https://www.pasdecalais.fr/Solidarite-Sante/Enfance-et-famille/La-Protection-Maternelle-et-Infantile/Prendre-rendez-vous-en-ligne-en-MDS-PMI-ou-service-social
after_action :allow_iframe

def home
post_logout_redirect_url = session.delete(:post_logout_redirect_url)

if post_logout_redirect_url
redirect_to post_logout_redirect_url, allow_other_host: true
return
end

if current_domain == Domain::RDV_MAIRIE
render "dsfr/rdv_mairie/homepage"
else
search_rdv
end
end

def search_rdv
# TODO : public_link_organisation_id has to work if agent is logged in ?
if current_agent && params[:prescripteur] == Prescripteur::INTERNE && session[:agent_prescripteur_organisation_id]
redirect_to search_creneau_admin_organisation_prescription_path(session[:agent_prescripteur_organisation_id], agent_search_params)
end
@context = if invitation?
WebInvitationSearchContext.new(user: current_user, query_params: query_params)
else
WebSearchContext.new(user: current_user, query_params: query_params)
end
if current_domain == Domain::RDV_MAIRIE && request.path == "/"
render "dsfr/rdv_mairie/homepage"
else
@context = if invitation?
WebInvitationSearchContext.new(user: current_user, query_params: query_params)
else
WebSearchContext.new(user: current_user, query_params: query_params)
end
render :search_rdv
end
end

Expand Down
1 change: 0 additions & 1 deletion app/views/search/_address_selection.html.slim

This file was deleted.

2 changes: 1 addition & 1 deletion app/views/search/search_rdv.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/ Adress selection partials have multiple sections
- if @context.current_step == :address_selection
= render @context, context: @context
= render(current_domain.address_selection_template_name, context: @context)
- else
section.rdv-background-color-alt-grey.py-4
= render @context, context: @context
1 change: 1 addition & 0 deletions config/anonymizer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ tables:
- name
- uid
- redirect_uri
- post_logout_redirect_uri
- scopes
- confidential
- created_at
Expand Down
15 changes: 6 additions & 9 deletions config/initializers/doorkeeper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -334,15 +334,12 @@
# Rails.logger.info(context.pre_auth.inspect)
# end
#
# after_successful_authorization do |controller, context|
# controller.session[:logout_urls] <<
# Doorkeeper::Application
# .find_by(controller.request.params.slice(:redirect_uri))
# .logout_uri
#
# Rails.logger.info(context.auth.inspect)
# Rails.logger.info(context.issued_token)
# end
after_successful_authorization do |controller, context|
oauth_application = context.issued_token.application

controller.session[:oauth_app_ids] ||= []
controller.session[:oauth_app_ids] << oauth_application.uid
end

# Under some circumstances you might want to have applications auto-approved,
# so that the user skips the authorization step.
Expand Down
5 changes: 2 additions & 3 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@
"users/rdvs/#{path_params[:id]}#{query_params}"
end), as: "rdv_short"

# TODO: remplacer `prendre_rdv` par le root_path
get "prdv", to: (redirect do |_path_params, req|
query_params = format_redirect_params(req.params)
"prendre_rdv#{query_params}"
Expand Down Expand Up @@ -342,9 +341,9 @@ def format_redirect_params(params)
get "presentation_agent" => "static_pages#presentation_for_agents"

resources :lieux, only: %i[index show]
root "search#search_rdv"

# TODO: remplacer `prendre_rdv` par le root_path
root "search#home"

get "/prendre_rdv", to: "search#search_rdv"

# temporary route after admin namespace introduction
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddOauthApplicationsLogoutUri < ActiveRecord::Migration[7.1]
def change
add_column :oauth_applications, :post_logout_redirect_uri, :text
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2024_11_04_154539) do
ActiveRecord::Schema[7.1].define(version: 2024_11_14_160009) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "pgcrypto"
Expand Down Expand Up @@ -498,6 +498,7 @@
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "logo_base64"
t.text "post_logout_redirect_uri"
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
end

Expand Down
1 change: 1 addition & 0 deletions db/seeds/rdv_insertion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@
name: "RDV Insertion",
uid: "zC24y16rYftyrBgTj8h08g1NZKkwStXWe3E_lLMGoHc",
redirect_uri: "http://localhost:8000/auth/rdvservicepublic/callback",
post_logout_redirect_uri: "http://localhost:8000/",
logo_base64: rdv_insertion_logo_base64
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ module Strategies
class RdvServicePublic < OmniAuth::Strategies::OAuth2
option :base_url, "https://demo.rdv.anct.gouv.fr" # L'url de base pour les appels

def self.sign_out_path
"/agents/sign_out"
def self.sign_out_path(oauth_client_app_id)
"/agents/sign_out?oauth_client_app_id=#{oauth_client_app_id}"
end

# On change les options passées en dernier argument par rapport à la classe mère
Expand Down
33 changes: 24 additions & 9 deletions spec/features/agents/oauth_provider_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
name: "Démarches Simplifiées",
uid: "fake_app_id",
redirect_uri: "http://localhost:4567/omniauth/rdvservicepublic/callback",
post_logout_redirect_uri: "http://localhost:4567/",
logo_base64: ""
)

Expand All @@ -34,7 +35,7 @@
end

specify "Parcours complet" do
visit "http://localhost:4567/login"
visit "http://localhost:4567/"
click_button "Se connecter avec RDV Service Public"

expect(page).to have_content("Vous devez vous connecter ou vous inscrire pour continuer")
Expand All @@ -45,10 +46,16 @@
expect(page).to have_content("Connexion réussie")
expect(page).to have_content("En continuant, vous allez permettre à Démarches Simplifiées d'accéder à votre compte RDV Solidarités lié à l'adresse [email protected]")
click_on "Continuer"
expect(page).to have_content("OAuth réussi ! Votre email est [email protected]")
expect(page).to have_content("Votre email est [email protected]")

click_on "Déconnexion"
expect(page).to have_content("Déconnexion réussie")

# On est déconnecté du client et de RDV Service Public
expect(page).to have_content("Se connecter avec RDV Service Public")
expect(page).to have_current_path("/")

visit "/"
expect(page).not_to have_content "Déconnexion réussie" # On n'affiche pas le flash sur la visite suivante

# La fois suivante, il y a uniquement besoin de se connecter, pas de reconfirmer qu'on donne la permission à l'appli
# Et on peut se connecter avant de faire l'oauth
Expand All @@ -57,25 +64,33 @@
fill_in "password", with: agent.password
click_on "Se connecter"

visit "http://localhost:4567/login"
visit "http://localhost:4567/"
click_button "Se connecter avec RDV Service Public"

expect(page).to have_content("OAuth réussi ! Votre email est [email protected]")
expect(page).to have_content("Votre email est [email protected]")

visit "http://localhost:4567/logout"

# Le lendemain, il n'y a toujours pas besoin de reconfirmer la permission
travel_to(1.day.from_now)
CronJob::DestroyOldOauthObjects.perform_now

visit "http://localhost:4567/login"
visit "http://localhost:4567/"
click_button "Se connecter avec RDV Service Public"

expect(page).to have_content("OAuth réussi ! Votre email est [email protected]")
fill_in "Email", with: agent.email
fill_in "password", with: agent.password
click_on "Se connecter"

expect(page).to have_content("Votre email est [email protected]")

visit "http://localhost:4567/logout"

# Un mois plus tard, si on ne s'est pas reconnecté, il faut à nouveau donner la permission à l'application
travel_to(31.days.from_now)
CronJob::DestroyOldOauthObjects.perform_now

visit "http://localhost:4567/login"
visit "http://localhost:4567/"
click_button "Se connecter avec RDV Service Public"

fill_in "Email", with: agent.email
Expand All @@ -86,6 +101,6 @@
expect(page).to have_content("En continuant, vous allez permettre à Démarches Simplifiées d'accéder à votre compte RDV Solidarités lié à l'adresse [email protected]")
click_on "Continuer"

expect(page).to have_content("OAuth réussi ! Votre email est [email protected]")
expect(page).to have_content("Votre email est [email protected]")
end
end
39 changes: 24 additions & 15 deletions spec/support/fake_oauth_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,38 @@ class FakeOauthClient < Sinatra::Base
scope: "write", base_url: Capybara.app_host
end

set :sessions, true
set :sessions, expire_after: 600 # temps en secondes

# Décommentez cette ligne pour avoir des logs sur stdout
# enable :logging

get "/login" do
get "/" do
status 200
<<-HTML
<form action="/omniauth/rdvservicepublic" method="post">
<button type="submit">Se connecter avec RDV Service Public</button>
</form
HTML
if session[:email]
<<-HTML
Votre email est #{session[:email]}, et votre token est #{session[:access_token]}
<a href="/logout">Déconnexion</a>
HTML
else
<<-HTML
<form action="/omniauth/rdvservicepublic" method="post">
<button type="submit">Se connecter avec RDV Service Public</button>
</form
HTML
end
end

get "/omniauth/rdvservicepublic/callback" do
email = request.env["omniauth.auth"]["info"]["agent"]["email"]
access_token = request.env["omniauth.auth"]["credentials"]["token"]
session[:email] = request.env["omniauth.auth"]["info"]["agent"]["email"]
session[:access_token] = request.env["omniauth.auth"]["credentials"]["token"]

status 200
<<-HTML
OAuth réussi !
Votre email est #{email}, et votre token est #{access_token}
<a href="#{Capybara.app_host}#{OmniAuth::Strategies::RdvServicePublic.sign_out_path}">Déconnexion</a>
HTML
redirect to("/")
end

get "/logout" do
session.delete(:email)
session.delete(:access_token)

redirect to(Capybara.app_host + OmniAuth::Strategies::RdvServicePublic.sign_out_path("fake_app_id"))
end
end

0 comments on commit 531860d

Please sign in to comment.