diff --git a/Gemfile b/Gemfile
index b9c56883dbda7de87582b0912769a6551ad00cbf..e70f6e4b9da84687df3a484591384a51bb5e9b59 100644
--- a/Gemfile
+++ b/Gemfile
@@ -23,6 +23,7 @@ gem 'i18n_data'
 gem 'cancancan'
 gem 'simple_form'
 gem 'simple_form_password_with_hints'
+gem 'simple_form_image_fields', path: '../simple_form_image_fields'
 gem 'enum_help'
 gem 'enum-i18n'
 gem 'country_select'
diff --git a/Gemfile.lock b/Gemfile.lock
index 1f41739290f683afceaa5fd151a644bb9199e0fd..6f7f5e6e9f0a32a18728f5a3538393d5addd9294 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -9,6 +9,13 @@ GIT
       randexp
       rotp (>= 4.0.0)
 
+PATH
+  remote: ../simple_form_image_fields
+  specs:
+    simple_form_image_fields (0.0.2)
+      rails
+      simple_form
+
 GEM
   remote: https://rubygems.org/
   specs:
@@ -402,8 +409,8 @@ DEPENDENCIES
   sib-api-v3-sdk
   simple-navigation
   simple_form
+  simple_form_image_fields!
   simple_form_password_with_hints
-  sort_alphabetical
   spring
   two_factor_authentication!
   tzinfo-data
diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js
index ab6a73603f15a33bdf65a91a05bc952cd9d5dfb1..8b8031a4195e12d84f55c2f2add2828de08edbf8 100644
--- a/app/assets/javascripts/admin.js
+++ b/app/assets/javascripts/admin.js
@@ -1,4 +1,6 @@
 //= require jquery3
 //= require jquery_ujs
+//= require notyf/notyf.min
 //= require simple_form_password_with_hints
 //= require appstack/app
+//= require_tree ./admin
diff --git a/app/assets/javascripts/admin/notyf.js b/app/assets/javascripts/admin/notyf.js
new file mode 100644
index 0000000000000000000000000000000000000000..a70f7aa75bfbf3fa12b6bb773485c4d8ab6be41d
--- /dev/null
+++ b/app/assets/javascripts/admin/notyf.js
@@ -0,0 +1,31 @@
+/*global Notyf */
+var notyfAlerts = document.getElementsByClassName('js-notyf-alert'),
+    notyfNotices = document.getElementsByClassName('js-notyf-notice'),
+    notyf = new Notyf();
+
+if (notyfAlerts.length > 0) {
+    notyf.open({
+        type: 'error',
+        position: {
+            x: 'right',
+            y: 'top'
+        },
+        message: notyfAlerts[0].innerHTML,
+        duration: 9000,
+        ripple: true,
+        dismissible: true
+    });
+}
+if (notyfNotices.length > 0) {
+    notyf.open({
+        type: 'success',
+        position: {
+            x: 'right',
+            y: 'top'
+        },
+        message: notyfNotices[0].innerHTML,
+        duration: 9000,
+        ripple: true,
+        dismissible: true
+    });
+}
diff --git a/app/assets/javascripts/admin/user_menu.js b/app/assets/javascripts/admin/user_menu.js
new file mode 100644
index 0000000000000000000000000000000000000000..c57d6cfbf0bb350760700c13e5cddcec53109e28
--- /dev/null
+++ b/app/assets/javascripts/admin/user_menu.js
@@ -0,0 +1,6 @@
+/*global $ */
+$('.js-user-button').click(function (e) {
+    'use strict';
+    e.stopPropagation();
+    $('.js-user-dropdown-toggle').dropdown('toggle');
+});
diff --git a/app/assets/stylesheets/admin.sass b/app/assets/stylesheets/admin.sass
index 9a243d739ed6b82bee2aaa253cd886a04c095245..9d74d3b7236e3e064d132dbb42b604994e92976f 100644
--- a/app/assets/stylesheets/admin.sass
+++ b/app/assets/stylesheets/admin.sass
@@ -1,4 +1,5 @@
-@import 'appstack/light'
+@import 'notyf/notyf.min'
 @import 'simple_form_password_with_hints'
 @import 'commons/*'
 @import 'admin/*'
+@import 'appstack/light'
diff --git a/app/assets/stylesheets/application/layout.sass b/app/assets/stylesheets/application/layout.sass
index 16ae7bbad0f8b94f976cfdc05e3ed56f217ba244..5e912ccbf0ec75611bcc73c6d0785175dfca77e5 100644
--- a/app/assets/stylesheets/application/layout.sass
+++ b/app/assets/stylesheets/application/layout.sass
@@ -1,2 +1,7 @@
 footer
     margin-top: 100px
+
+.alert
+    padding: .95rem
+    &-danger
+        color: #82322F
diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb
index 779a6029ca4b17c8b65f0d99d4fbca60ba840c9c..cebe8199652dc48218a85548bce8d70439c0cb0d 100644
--- a/app/controllers/users/registrations_controller.rb
+++ b/app/controllers/users/registrations_controller.rb
@@ -4,13 +4,31 @@ class Users::RegistrationsController < Devise::RegistrationsController
   before_action :configure_sign_up_params, only: :create
   before_action :configure_account_update_params, only: :update
 
+  def update
+    # to prevent cognitive complexity (the bottom block should be in an if condition where password present)
+    # Password not provided when user from sso
+    params[:user][:password] ||= ''
+
+    if params[:user][:password].empty?
+      params[:user].delete(:password)
+    else
+      resource.reset_password(params[:user][:password], params[:user][:password])
+    end
+
+    super
+  end
+
   protected
 
+  def update_resource(resource, params)
+    resource.update(params)
+  end
+
   def configure_sign_up_params
-    devise_parameter_sanitizer.permit(:sign_up, keys: [:language_id, :first_name, :last_name])
+    devise_parameter_sanitizer.permit(:sign_up, keys: [:language_id, :first_name, :last_name, :picture, :picture_delete])
   end
 
   def configure_account_update_params
-    devise_parameter_sanitizer.permit(:account_update, keys: [:mobile_phone, :language_id])
+    devise_parameter_sanitizer.permit(:account_update, keys: [:mobile_phone, :language_id, :first_name, :last_name, :picture, :picture_delete])
   end
 end
diff --git a/app/models/user.rb b/app/models/user.rb
index 12c38e59d26612c6a3517280436e368cd7ab4ed2..70045a197e7a05e0cc3a86719ad94a67ac1ef216 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -59,7 +59,7 @@ class User < ApplicationRecord
   belongs_to :university
   belongs_to :language
   has_one :researcher, class_name: 'Research::Researcher'
-  has_one_attached :picture
+  has_one_attached_deletable :picture
 
   scope :ordered, -> { order(:last_name, :first_name) }
 
diff --git a/app/views/admin/application/_top.html.erb b/app/views/admin/application/_top.html.erb
index ec95c6a8af2a9d353ab850f083e8292f26903e38..a7941becc208c77f4673f0d804eaf22e3570752b 100644
--- a/app/views/admin/application/_top.html.erb
+++ b/app/views/admin/application/_top.html.erb
@@ -6,7 +6,7 @@
     <%= render_breadcrumbs builder: Appstack::BreadcrumbsOnRailsBuilder %>
     <ul class="navbar-nav navbar-align">
       <li class="nav-item dropdown">
-        <a class="nav-link dropdown-toggle d-none d-sm-inline-block" href="#" data-bs-toggle="dropdown">
+        <a class="nav-link dropdown-toggle d-none d-sm-inline-block js-user-dropdown-toggle" href="#" data-bs-toggle="dropdown">
           <span class="text-dark"><%= current_user %></span>
         </a>
         <div class="dropdown-menu dropdown-menu-end">
@@ -15,8 +15,12 @@
         </div>
       </li>
       <li>
-        <a class="nav-link nav-link--last" href="#">
-          <%= image_tag 'avatar.jpg', class: 'avatar img-fluid rounded-circle' %>
+        <a class="nav-link nav-link--last js-user-button" href="#">
+          <% if current_user.picture.attached? && current_user.picture.variable? %>
+            <%= image_tag current_user.picture.variant(resize: '40x40'), class: 'avatar img-fluid rounded-circle' %>
+          <% else %>
+            <%= image_tag 'avatar.jpg', class: 'avatar img-fluid rounded-circle' %>
+          <% end %>
         </a>
       </li>
     </ul>
diff --git a/app/views/admin/layouts/application.html.erb b/app/views/admin/layouts/application.html.erb
index 59d9365337a0b6e1c0d48f8b768623d7b0e8dad2..9f49453feef6018e7215150193661e3d93e166ea 100644
--- a/app/views/admin/layouts/application.html.erb
+++ b/app/views/admin/layouts/application.html.erb
@@ -12,6 +12,18 @@
     <%= favicon_link_tag 'favicon.png' %>
   </head>
   <body data-layout="fluid" data-sidebar-position="left">
+    <div class="toasts-container" style="position: fixed; top: 20px; right: 20px; z-index: 100000;">
+      <% unless notice.nil? %>
+        <div class="js-notyf-notice d-none">
+          <%= notice %>
+        </div>
+      <% end %>
+      <% unless alert.nil? %>
+        <div class="js-notyf-alert d-none">
+          <%= alert %>
+        </div>
+      <% end %>
+    </div>
     <div class="wrapper">
       <%= render 'admin/application/nav' %>
       <div class="main">
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb
index 2e6a1b6cd533f9cecd3503c52a790c335c44bc10..b6da316412ad7e065cf5350ada71b76ef7a79077 100644
--- a/app/views/devise/registrations/edit.html.erb
+++ b/app/views/devise/registrations/edit.html.erb
@@ -20,17 +20,16 @@
     <%= f.input :mobile_phone %>
     <%= f.association :language, include_blank: false %>
 
+    <%= f.input :picture,
+                      as: :single_deletable_file,
+                      input_html: { accept: '.png' } %>
+
     <%= f.input :password,
                 hint: t(".leave_blank_if_you_don_t_want_to_change_it"),
                 required: false,
                 input_html: { autocomplete: "new-password" } %>
-    <%= f.input :password_confirmation,
-                required: false,
-                input_html: { autocomplete: "new-password" } %>
-    <%= f.input :current_password,
-                hint: t(".we_need_your_current_password_to_confirm_your_changes"),
-                required: true,
-                input_html: { autocomplete: "current-password" } %>
+  
+
   </div>
 
   <div class="form-actions">
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb
index 7592267994d6a0f1247dc3accdbc5bfe11cca3aa..f72cf237af8d39437d273b4c57718fd13d8be581 100644
--- a/app/views/devise/registrations/new.html.erb
+++ b/app/views/devise/registrations/new.html.erb
@@ -15,16 +15,30 @@
                 required: true,
                 input_html: { autocomplete: "email" } %>
     <%= f.input :password,
+                as: :password_with_hints,
                 required: true,
-                hint: (t('devise.shared.minimum_password_length', count: @minimum_password_length) if @minimum_password_length),
+                allow_password_uncloaking: true,
+                validators: {
+                  length: Devise.password_length.first,
+                  uppercase_char: true,
+                  lowercase_char: true,
+                  numeric_char: true,
+                  special_char: Rails.application.config.allowed_special_chars
+                },
                 input_html: { autocomplete: "new-password" } %>
     <%= f.input :password_confirmation,
+                as: :password_with_sync,
                 required: true,
+                allow_password_uncloaking: true,
+                compare_with_field: :password,
                 input_html: { autocomplete: "new-password" } %>
     <%= f.association :language,
                       required: true,
                       label_method: lambda { |l| I18nData.languages(I18n.locale.to_s.upcase)[l.iso_code.to_s.upcase].capitalize },
                       include_blank: 'Sélectionnez une langue' %>
+    <%= f.input :picture,
+                      as: :single_deletable_file,
+                      input_html: { accept: '.png' } %>
   </div>
 
   <div class="form-actions text-center mt-3">
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 5726df05b7dfccdfaa02f973d470b85c33cbd6a5..c2009000b5c58802d3e48fd056ba82807ca6198f 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -13,6 +13,7 @@
   <body>
     <%= render 'nav' %>
     <main class="container">
+      
       <%= render_breadcrumbs builder: Appstack::BreadcrumbsOnRailsBuilder %>
       <%= yield %>
     </main>
diff --git a/app/views/layouts/devise.html.erb b/app/views/layouts/devise.html.erb
index df37364431c8d31fde821c69dbcb121bda12c558..c46882bdda74ee6569067b66aaf3cc77aa02185d 100644
--- a/app/views/layouts/devise.html.erb
+++ b/app/views/layouts/devise.html.erb
@@ -14,8 +14,8 @@
     <div class="main d-flex justify-content-center w-100">
       <main class="content d-flex p-0">
         <div class="container d-flex flex-column">
-          <% unless notice.blank? %><div class="alert alert-success mt-2" role="alert"><div class="alert-message"><%= notice.html_safe %></div></div><% end %>
-          <% unless alert.blank? %><div class="alert alert-danger mt-2" role="alert"><div class="alert-message"><%= alert.html_safe %></div></div><% end %>
+          <% unless notice.blank? %><div class="alert alert-success mt-2" role="alert"><%= notice.html_safe %></div><% end %>
+          <% unless alert.blank? %><div class="alert alert-danger mt-2" role="alert"><%= alert.html_safe %></div><% end %>
 
           <div class="row h-100">
             <div class="col-sm-10 col-md-8 col-lg-6 mx-auto d-table h-100">
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 56dec7625e7904b2e9ed2ab15503693d90c6f27d..1a81b6369aae25f6960a81070bb0ee49761564ab 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -74,6 +74,8 @@ en:
     subtitle: Sign in to your account to continue
   please-confirm: Are you sure?
   simple_form:
+    error_notification:
+      default_message: "Please review the problems below:"
     hints:
       user:
         mobile_phone: "International format (+XX)"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 1ee02d4dd3c44f37b145c265ff7aeb43aa5c95da..20c631a121de08e675ad38ca610cc4c76d2ae8c6 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -74,6 +74,8 @@ fr:
     subtitle: Vous devez être authentifié pour continuer
   please-confirm: Est-ce que vous confirmez ?
   simple_form:
+    error_notification:
+      default_message: "Les erreurs ci-dessous empêchent la validation :"
     hints:
       user:
         mobile_phone: "Format international (+XX)"
diff --git a/package.json b/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..587e1568842c4caee453f500facc75fb3cbe709a
--- /dev/null
+++ b/package.json
@@ -0,0 +1,5 @@
+{
+  "dependencies": {
+    "notyf": "^3.10.0"
+  }
+}
diff --git a/yarn.lock b/yarn.lock
index fb57ccd13afbd082ad82051c2ffebef4840661ec..a4bd56507f4daa37ac7fa233e781f35cdf13290b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,3 +2,7 @@
 # yarn lockfile v1
 
 
+notyf@^3.10.0:
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/notyf/-/notyf-3.10.0.tgz#67a64443c69ea0e6495c56ea0f91198860163d06"
+  integrity sha512-Mtnp+0qiZxgrH+TzVlzhWyZceHdAZ/UWK0/ju9U0HQeDpap1mZ8cC7H5wSI5mwgni6yeAjaxsTw0sbMK+aSuHw==