check state
This commit is contained in:
parent
98b574b031
commit
9938586d96
3 changed files with 53 additions and 4 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue