Skip to content

Commit

Permalink
Remplace InclusionConnect par ProConnect
Browse files Browse the repository at this point in the history
  • Loading branch information
etienneCharignon committed Oct 21, 2024
1 parent f730e9a commit a934188
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 105 deletions.
42 changes: 0 additions & 42 deletions app/controllers/inclusion_connect_controller.rb

This file was deleted.

49 changes: 49 additions & 0 deletions app/controllers/pro_connect_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

class ProConnectController < ApplicationController
def auth
session[:pc_state] = Digest::SHA256.hexdigest("ProConnect - #{SecureRandom.hex(32)}")
session[:pc_nonce] = Digest::SHA256.hexdigest("ProConnect - #{SecureRandom.hex(32)}")
redirect_to ProConnectHelper.auth_path(session[:pc_state], session[:pc_nonce],
pro_connect_callback_url),
allow_other_host: true
end

def callback
tokens = correct_state? &&
ProConnectHelper.recupere_tokens(params[:code], pro_connect_callback_url)
compte = lit_tokens(tokens)
echec_login and return if compte.blank?

session[:pc_logout_token] = tokens['id_token']
sign_in_and_redirect compte, scope: :compte
end

def lit_tokens(tokens)
tokens &&
ProConnectHelper.verifie(tokens['id_token'], session[:pc_nonce]) &&
ProConnectHelper.compte(tokens['access_token'])
end

def logout
if session[:pc_state].blank? || session[:pc_logout_token].blank?
redirect_to destroy_compte_session_url and return
end

sign_out current_compte
redirect_to ProConnectHelper.logout(session, destroy_compte_session_url),
allow_other_host: true
end

private

def echec_login
flash[:error] = I18n.t('.pro-connect.authentification-impossible',
email_contact: Eva::EMAIL_SUPPORT)
redirect_to new_compte_session_path
end

def correct_state?
params[:state] == session[:pc_state]
end
end
Original file line number Diff line number Diff line change
@@ -1,58 +1,70 @@
# frozen_string_literal: true

module InclusionConnectHelper
IC_CLIENT_ID = ENV.fetch('INCLUSION_CONNECT_CLIENT_ID', nil)
IC_CLIENT_SECRET = ENV.fetch('INCLUSION_CONNECT_CLIENT_SECRET', nil)
IC_BASE_URL = ENV.fetch('INCLUSION_CONNECT_BASE_URL', nil)
module ProConnectHelper
PC_CLIENT_ID = ENV.fetch('PRO_CONNECT_CLIENT_ID', nil)
PC_CLIENT_SECRET = ENV.fetch('PRO_CONNECT_CLIENT_SECRET', nil)
PC_BASE_URL = ENV.fetch('PRO_CONNECT_BASE_URL', nil)

class << self
def auth_path(ic_state, callback_url)
def auth_path(pc_state, pc_nonce, callback_url)
query = {
response_type: 'code',
client_id: IC_CLIENT_ID,
client_id: PC_CLIENT_ID,
redirect_uri: callback_url,
scope: 'openid email profile',
state: ic_state,
nonce: Digest::SHA1.hexdigest('Something to check when it come back ?'),
from: 'community'
acr_values: 'eidas1',
scope: 'openid email usual_name given_name',
state: pc_state,
nonce: pc_nonce
}
"#{IC_BASE_URL}/auth/authorize?#{query.to_query}"
"#{PC_BASE_URL}/api/v2/authorize?#{query.to_query}"
end

def logout_confirmed(post_logout_redirect_uri)
query = {
client_id: IC_CLIENT_ID,
client_id: PC_CLIENT_ID,
post_logout_redirect_uri: post_logout_redirect_uri
}
"#{IC_BASE_URL}/auth/logout?#{query.to_query}"
"#{PC_BASE_URL}/api/v2/session/end?#{query.to_query}"
end

def logout(session, post_logout_redirect_uri)
query = {
state: session[:ic_state],
id_token_hint: session[:ic_logout_token],
state: session[:pc_state],
id_token_hint: session[:pc_logout_token],
post_logout_redirect_uri: post_logout_redirect_uri
}
session[:ic_logout_token] = nil
"#{IC_BASE_URL}/auth/logout?#{query.to_query}"
session[:pc_logout_token] = nil
"#{PC_BASE_URL}/api/v2/session/end?#{query.to_query}"
end

def compte(token)
return false if token.blank?
def decode_jwt(jwt)
decode = JWT.decode(jwt, PC_CLIENT_SECRET, true, { algorithm: 'HS256' })
yield(decode[0])
rescue JWT::DecodeError => e
Rails.logger.warn "erreur JWT: #{e}"
false
end

def verifie(id_token_jwt, nonce)
decode_jwt(id_token_jwt) { |id_token| id_token['nonce'] == nonce }
end

user_info = get_user_info(token)
def compte(access_token)
return false if access_token.blank?

user_info = get_user_info(access_token)
return false if user_info.blank?

cree_ou_recupere_compte(user_info)
end

def recupere_tokens(code, callback_url)
data = { grant_type: 'authorization_code',
client_id: IC_CLIENT_ID, client_secret: IC_CLIENT_SECRET,
client_id: PC_CLIENT_ID, client_secret: PC_CLIENT_SECRET,
code: code, redirect_uri: callback_url }

res = Typhoeus.post(
URI("#{IC_BASE_URL}/auth/token/"),
URI("#{PC_BASE_URL}/api/v2/token"),
body: data.to_query,
headers: { 'Content-Type' => 'application/x-www-form-urlencoded' }
)
Expand All @@ -62,18 +74,17 @@ def recupere_tokens(code, callback_url)
end

def get_user_info(token)
uri = URI("#{IC_BASE_URL}/auth/userinfo/")
uri.query = URI.encode_www_form({ schema: 'openid' })
uri = URI("#{PC_BASE_URL}/api/v2/userinfo")

res = Typhoeus.get(uri, headers: { 'Authorization' => "Bearer #{token}" })
return false unless res.success?

JSON.parse(res.body)
decode_jwt(res.body) { |user_info| user_info }
end

def cree_ou_recupere_compte(user_info)
email = user_info['email'].strip.downcase
compte = Compte.find_by(id_inclusion_connect: user_info['sub'])
compte = Compte.find_by(id_pro_connect: user_info['sub'])
if compte.present? && compte.email != email
compte = actualise_email_compte_existant(compte, email)
end
Expand All @@ -88,7 +99,7 @@ def cree_ou_recupere_compte(user_info)
def actualise_email_compte_existant(compte, email)
compte_existant = Compte.find_by(email: email)
if compte_existant.present?
compte.update!(id_inclusion_connect: nil)
compte.update!(id_pro_connect: nil)
compte = compte_existant
else
compte.email = email
Expand All @@ -99,9 +110,9 @@ def actualise_email_compte_existant(compte, email)
end

def actualise_autres_champs(compte, user_info)
compte.id_inclusion_connect = user_info['sub']
compte.id_pro_connect = user_info['sub']
compte.prenom = user_info['given_name']
compte.nom = user_info['family_name']
compte.nom = user_info['usual_name']
compte.password = SecureRandom.uuid if compte.encrypted_password.blank?
compte.confirmed_at ||= Time.zone.now
end
Expand Down
4 changes: 2 additions & 2 deletions app/views/active_admin/devise/sessions/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
<p class="espace-pro-connect-transition" ><%= t('.pro-connect.transition') %></p>
<div class="bouton-action bouton-action--centre">
<div class='pro-connect-group'>
<%= link_to inclusion_connect_auth_path, class:'btn-pro-connect' do %>
<%= link_to pro_connect_auth_path, class:'btn-pro-connect' do %>
<span class="pro-connect__login">S’identifier avec</span>
<span class="pro-connect__brand">ProConnect</span>
<% end %>
<p>
<a href="https://proconnect.gouv.fr/" target="_blank" rel="noopener" title="<%= t('.pro-connect.libelle-lien-pro-connect') %> - nouvelle fenêtre">
<a href="https://www.proconnect.gouv.fr/" target="_blank" rel="noopener" title="<%= t('.pro-connect.libelle-lien-pro-connect') %> - nouvelle fenêtre">
<%= t('.pro-connect.libelle-lien-pro-connect') %>
</a>
</p>
Expand Down
2 changes: 1 addition & 1 deletion config/initializers/active_admin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
# will call the method to return the path.
#
# Default:
config.logout_link_path = :inclusion_connect_logout_path
config.logout_link_path = :pro_connect_logout_path
# This setting changes the http method used when rendering the
# link. For example :get, :delete, :put, etc..
#
Expand Down
3 changes: 0 additions & 3 deletions config/locales/inclusion_connect.yml

This file was deleted.

3 changes: 3 additions & 0 deletions config/locales/pro_connect.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fr:
pro-connect:
authentification-impossible: Nous n'avons pas pu vous authentifier avec ProConnect. Connectez-vous directement sur eva ou réessayez plus tard.
6 changes: 3 additions & 3 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
end
get '/admin', to: redirect('/pro/admin/dashboard')

get "inclusion_connect/logout" => "inclusion_connect#logout"
get "inclusion_connect/auth" => "inclusion_connect#auth"
get "inclusion_connect/callback" => "inclusion_connect#callback"
get "pro_connect/logout" => "pro_connect#logout"
get "pro_connect/auth" => "pro_connect#auth"
get "pro_connect/callback" => "pro_connect#callback"
get "demo" => "demo#show"
post "demo/connect" => "demo#connect"

Expand Down
Loading

0 comments on commit a934188

Please sign in to comment.