diff --git a/Gemfile b/Gemfile index 459f5795..442430e3 100644 --- a/Gemfile +++ b/Gemfile @@ -45,6 +45,9 @@ gem "bootsnap", require: false # gem "image_processing", "~> 1.2" gem "config" +gem "omniauth_openid_connect" +gem "hash_mapper" +gem "omniauth-rails_csrf_protection" group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem diff --git a/Gemfile.lock b/Gemfile.lock index 654dd553..96e41f35 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,9 +77,12 @@ GEM tzinfo (~> 2.0) addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) + aes_key_wrap (1.1.0) ast (2.4.2) + attr_required (1.0.2) base64 (0.2.0) bigdecimal (3.1.7) + bindata (2.5.0) bindex (0.8.1) bootsnap (1.18.3) msgpack (~> 1.2) @@ -104,9 +107,20 @@ GEM reline (>= 0.3.8) deep_merge (1.2.2) drb (2.2.1) + email_validator (2.2.4) + activemodel erubi (1.12.0) + faraday (2.9.0) + faraday-net_http (>= 2.0, < 3.2) + faraday-follow_redirects (0.3.0) + faraday (>= 1, < 3) + faraday-net_http (3.1.0) + net-http globalid (1.2.1) activesupport (>= 6.1) + hash_mapper (0.2.7) + activesupport (>= 4) + hashie (5.0.0) i18n (1.14.4) concurrent-ruby (~> 1.0) importmap-rails (2.0.1) @@ -121,6 +135,13 @@ GEM actionview (>= 5.0.0) activesupport (>= 5.0.0) json (2.7.2) + json-jwt (1.16.6) + activesupport (>= 4.2) + aes_key_wrap + base64 + bindata + faraday (~> 2.0) + faraday-follow_redirects language_server-protocol (3.17.0.3) lint_roller (1.1.0) loofah (2.22.0) @@ -137,6 +158,8 @@ GEM minitest (5.22.3) msgpack (1.7.2) mutex_m (0.2.0) + net-http (0.4.1) + uri net-imap (0.4.10) date net-protocol @@ -147,18 +170,31 @@ GEM net-smtp (0.5.0) net-protocol nio4r (2.7.1) - nokogiri (1.16.3-aarch64-linux) - racc (~> 1.4) - nokogiri (1.16.3-arm-linux) - racc (~> 1.4) - nokogiri (1.16.3-arm64-darwin) - racc (~> 1.4) - nokogiri (1.16.3-x86-linux) - racc (~> 1.4) - nokogiri (1.16.3-x86_64-darwin) - racc (~> 1.4) nokogiri (1.16.3-x86_64-linux) racc (~> 1.4) + omniauth (2.1.2) + hashie (>= 3.4.6) + rack (>= 2.2.3) + rack-protection + omniauth-rails_csrf_protection (1.0.1) + actionpack (>= 4.2) + omniauth (~> 2.0) + omniauth_openid_connect (0.7.1) + omniauth (>= 1.9, < 3) + openid_connect (~> 2.2) + openid_connect (2.3.0) + activemodel + attr_required (>= 1.0.0) + email_validator + faraday (~> 2.0) + faraday-follow_redirects + json-jwt (>= 1.16) + mail + rack-oauth2 (~> 2.2) + swd (~> 2.0) + tzinfo + validate_url + webfinger (~> 2.0) parallel (1.24.0) parser (3.3.0.5) ast (~> 2.4.1) @@ -171,6 +207,16 @@ GEM nio4r (~> 2.0) racc (1.7.3) rack (3.0.10) + rack-oauth2 (2.2.1) + activesupport + attr_required + faraday (~> 2.0) + faraday-follow_redirects + json-jwt (>= 1.11.0) + rack (>= 2.1.0) + rack-protection (4.0.0) + base64 (>= 0.1.0) + rack (>= 3.0.0, < 4) rack-session (2.0.0) rack (>= 3.0.0) rack-test (2.1.0) @@ -265,16 +311,11 @@ GEM stimulus-rails (1.3.3) railties (>= 6.0.0) stringio (3.1.0) - tailwindcss-rails (2.3.0) - railties (>= 6.0.0) - tailwindcss-rails (2.3.0-aarch64-linux) - railties (>= 6.0.0) - tailwindcss-rails (2.3.0-arm-linux) - railties (>= 6.0.0) - tailwindcss-rails (2.3.0-arm64-darwin) - railties (>= 6.0.0) - tailwindcss-rails (2.3.0-x86_64-darwin) - railties (>= 6.0.0) + swd (2.0.3) + activesupport (>= 3) + attr_required (>= 0.0.5) + faraday (~> 2.0) + faraday-follow_redirects tailwindcss-rails (2.3.0-x86_64-linux) railties (>= 6.0.0) thor (1.3.1) @@ -286,11 +327,19 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) + uri (0.13.0) + validate_url (1.0.15) + activemodel (>= 3.0.0) + public_suffix web-console (4.2.1) actionview (>= 6.0.0) activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) + webfinger (2.1.3) + activesupport + faraday (~> 2.0) + faraday-follow_redirects webrick (1.8.1) websocket (1.2.10) websocket-driver (0.7.6) @@ -301,11 +350,6 @@ GEM zeitwerk (2.6.13) PLATFORMS - aarch64-linux - arm-linux - arm64-darwin - x86-linux - x86_64-darwin x86_64-linux DEPENDENCIES @@ -313,8 +357,11 @@ DEPENDENCIES capybara config debug + hash_mapper importmap-rails jbuilder + omniauth-rails_csrf_protection + omniauth_openid_connect pg (~> 1.1) puma (>= 5.0) rails (~> 7.1.3, >= 7.1.3.2) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d12..03a8283b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,17 @@ class ApplicationController < ActionController::Base + before_action :identify_user + + private + + def identify_user + Current.user = PivotIdentity.new(auth: session_auth, recipient:) + end + + def recipient + params.fetch(:recipient, "") + end + + def session_auth + session.fetch("auth", {}) + end end diff --git a/app/controllers/claims_controller.rb b/app/controllers/claims_controller.rb new file mode 100644 index 00000000..c2fb6a67 --- /dev/null +++ b/app/controllers/claims_controller.rb @@ -0,0 +1,4 @@ +class ClaimsController < ApplicationController + def index + end +end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb new file mode 100644 index 00000000..ea24a66f --- /dev/null +++ b/app/controllers/home_controller.rb @@ -0,0 +1,4 @@ +class HomeController < ApplicationController + def home + end +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 00000000..d51f26a9 --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,11 @@ +class SessionsController < ApplicationController + def new + render :new + end + + def create + session[:auth] = request.env["omniauth.auth"] + + redirect_to claims_path(recipient: "13002526500013") + end +end diff --git a/app/models/current.rb b/app/models/current.rb new file mode 100755 index 00000000..73a9744b --- /dev/null +++ b/app/models/current.rb @@ -0,0 +1,3 @@ +class Current < ActiveSupport::CurrentAttributes + attribute :user +end diff --git a/app/models/pivot_identity.rb b/app/models/pivot_identity.rb new file mode 100755 index 00000000..5f6c4d9b --- /dev/null +++ b/app/models/pivot_identity.rb @@ -0,0 +1,29 @@ +class PivotIdentity + extend HashMapper + + attr_reader :auth, :data + + map from("info/birthdate"), to("birthdate") { |str| Date.strptime(str, "%Y-%m-%d") } + map from("info/family_name"), to("family_name") + map from("info/first_name"), to("first_names") { |str| str.split(" ") } + map from("info/gender"), to("gender") + map from("info/last_name"), to("last_name") + map from("extra/raw_info/birthcountry"), to("birth_country") + map from("extra/raw_info/birthplace"), to("birthplace") + + map from("credentials/token"), to("token") + + def initialize(recipient:, auth: {}) + @auth = auth + @data = self.class.normalize(auth) + @data[:recipient] = recipient + end + + delegate :[], to: :data + + def token + return "cnaf_qfv2" unless Rails.env.production? + + self[:token] + end +end diff --git a/app/views/claims/index.html.erb b/app/views/claims/index.html.erb new file mode 100644 index 00000000..f46a7dd2 --- /dev/null +++ b/app/views/claims/index.html.erb @@ -0,0 +1,10 @@ +

Début de la demande

+
+ +
+curl -H "Authorization: Bearer <%= Current.user.token %>" -G \
+-d 'recipient=<%= Current.user[:recipient] %>' \
+--url "https://staging.particulier.api.gouv.fr/api/v2/composition-familiale-v2"
+
+
+
<%= debug Current.user %>
diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb new file mode 100644 index 00000000..9700d139 --- /dev/null +++ b/app/views/home/index.html.erb @@ -0,0 +1,2 @@ +

Faire une demande

+<%= link_to "Je démarre", :claims %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 3dc45d46..0581f199 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -12,7 +12,7 @@ -
+
<%= yield %>
diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb new file mode 100644 index 00000000..2e0550aa --- /dev/null +++ b/app/views/sessions/new.html.erb @@ -0,0 +1,3 @@ +<%= form_tag('/auth/france_connect', method: 'post', data: {turbo: false}) do %> + +<% end %> diff --git a/config/initializers/france_connect_middleware.rb b/config/initializers/france_connect_middleware.rb new file mode 100644 index 00000000..144baf8f --- /dev/null +++ b/config/initializers/france_connect_middleware.rb @@ -0,0 +1,35 @@ +require "omniauth_openid_connect" + +module OmniAuth + module Strategies + class FranceConnect < OpenIDConnect + option :callback_path, "/callback" + option :client_auth_method, :secret + option :client_signing_alg, :HS256 + option :state, -> { SecureRandom.hex(16) } + + option :client_options, { + port: 443, + scheme: "https", + authorization_endpoint: "/api/v1/authorize?acr_values=eidas1", + token_endpoint: "/api/v1/token", + userinfo_endpoint: "/api/v1/userinfo", + } + end + end +end + +Rails.application.config.middleware.use OmniAuth::Builder do + provider( + :france_connect, + client_options: { + host: Settings.france_connect.host, + identifier: Settings.france_connect.identifier, + redirect_uri: Settings.france_connect.redirect_uri, + secret: Settings.france_connect.secret, + }, + issuer: "https://#{Settings.france_connect.host}", + name: :france_connect, + scope: %i[openid identite_pivot] + ) +end diff --git a/config/routes.rb b/config/routes.rb index 247c9cb6..b9b5ce9b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,6 +5,10 @@ # Can be used by load balancers and uptime monitors to verify that the app is live. get "up", to: "rails/health#show", as: :rails_health_check - # Defines the root path route ("/") - # root "posts#index" + # get 'auth/:provider/callback', to: 'sessions#create' + get "/callback", to: "sessions#create" + get "/login", to: "sessions#new" + + get "collecte/:recipient/démarrer", to: "claims#index", as: :claims + root "home#index" end diff --git a/config/settings.yml b/config/settings.yml index e48045e8..a7d2f6b4 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -1 +1,11 @@ # keys from rails' credentials are added under "credentials" (cf config_add_credentials.rb) +france_connect: + host: "fcp.integ01.dev-franceconnect.fr" + identifier: "211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e" + redirect_uri: "http://localhost:3000/callback" + secret: "2791a731e6a59f56b6b4dd0d08c9b1f593b5f3658b9fd731cb24248e2669af4b" +hubee: + base_url: "https://api.bas.hubee.numerique.gouv.fr" + client_id: <%= Rails.application.credentials.hubee.client_id %> + client_secret: <%= Rails.application.credentials.hubee.client_secret %> + token_url: "https://auth.bas.hubee.numerique.gouv.fr/oauth2/token"