check state

This commit is contained in:
simon lehericey 2022-04-11 13:11:04 +02:00
parent 98b574b031
commit 9938586d96
3 changed files with 53 additions and 4 deletions

View file

@ -1,12 +1,19 @@
# doc: https://github.com/france-connect/Documentation-AgentConnect
class AgentConnect::AgentController < ApplicationController
before_action :redirect_to_login_if_fc_aborted, only: [:callback]
before_action :check_state, only: [:callback]
STATE_COOKIE_NAME = :agentConnect_state
def index
end
def login
redirect_to AgentConnectService.authorization_uri
uri, state = AgentConnectService.authorization_uri
cookies.encrypted[STATE_COOKIE_NAME] = state
redirect_to uri
end
def callback
@ -50,4 +57,13 @@ class AgentConnect::AgentController < ApplicationController
flash.alert = t('errors.messages.france_connect.connexion')
redirect_to(new_user_session_path)
end
def check_state
if cookies.encrypted[STATE_COOKIE_NAME] != params[:state]
flash.alert = t('errors.messages.france_connect.connexion')
redirect_to(new_user_session_path)
else
cookies.encrypted[STATE_COOKIE_NAME] = nil
end
end
end

View file

@ -6,12 +6,16 @@ class AgentConnectService
def self.authorization_uri
client = AgentConnectClient.new
client.authorization_uri(
state = SecureRandom.hex(16)
uri = client.authorization_uri(
scope: [:openid, :email],
state: SecureRandom.hex(16),
state: state,
nonce: SecureRandom.hex(16),
acr_values: 'eidas1'
)
[uri, state]
end
def self.user_info(code)

View file

@ -1,10 +1,20 @@
describe AgentConnect::AgentController, type: :controller do
describe '#login' do
before { get :login }
it { expect(state_cookie).not_to be_nil }
end
describe '#callback' do
let(:email) { 'i@email.com' }
subject { get :callback, params: { code: code } }
let(:original_state) { 'original_state' }
subject { get :callback, params: { code: code, state: state } }
before { cookies.encrypted[controller.class::STATE_COOKIE_NAME] = original_state }
context 'when the callback code is correct' do
let(:code) { 'correct' }
let(:state) { original_state }
let(:user_info) { { 'sub' => 'sub', 'email' => ' I@email.com' } }
context 'and user_info returns some info' do
@ -26,6 +36,7 @@ describe AgentConnect::AgentController, type: :controller do
expect(last_user.confirmed_at).to be_present
expect(last_user.instructeur.agent_connect_id).to eq('sub')
expect(response).to redirect_to(instructeur_procedures_path)
expect(state_cookie).to be_nil
end
end
@ -77,8 +88,22 @@ describe AgentConnect::AgentController, type: :controller do
end
end
context 'when the callback state is not the original' do
let(:code) { 'correct' }
let(:state) { 'another state' }
before { subject }
it 'aborts the processus' do
expect { subject }.to change { User.count }.by(0).and change { Instructeur.count }.by(0)
expect(response).to redirect_to(new_user_session_path)
end
end
context 'when the callback code is blank' do
let(:code) { '' }
let(:state) { original_state }
it 'aborts the processus' do
expect { subject }.to change { User.count }.by(0).and change { Instructeur.count }.by(0)
@ -87,4 +112,8 @@ describe AgentConnect::AgentController, type: :controller do
end
end
end
def state_cookie
cookies.encrypted[controller.class::STATE_COOKIE_NAME]
end
end