diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 52a961c6c2cfcf8ae3d4aa8822cf753cdd1ae978..cc9f16a2572084418e8084ac0e8436e89d5fe78e 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -5,6 +5,7 @@ import { HomeComponent } from './home/home.component';
 import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
 import { StructureDetailsComponent } from './structure-list/components/structure-details/structure-details.component';
 import { StructureListComponent } from './structure-list/structure-list.component';
+import { UserVerificationComponent } from './user-verification/user-verification.component';
 
 const routes: Routes = [
   { path: 'print', outlet: 'print', children: [{ path: 'structure', component: StructureDetailsComponent }] },
@@ -36,6 +37,10 @@ const routes: Routes = [
     path: 'about',
     component: AboutComponent,
   },
+  {
+    path: 'users/verify/:id',
+    component: UserVerificationComponent,
+  },
   {
     path: '**',
     redirectTo: 'home',
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index e951cd68bad1da63920dfe5dc9a205f29dae98db..02649bb0928321b50390bc3aee7092d6fcdc9ef5 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -22,6 +22,7 @@ import { ModalFilterComponent } from './structure-list/components/modal-filter/m
 import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
 import { AboutComponent } from './about/about.component';
 import { MenuPhoneComponent } from './menu-phone/menu-phone.component';
+import { UserVerificationComponent } from './user-verification/user-verification.component';
 
 @NgModule({
   declarations: [
@@ -38,6 +39,7 @@ import { MenuPhoneComponent } from './menu-phone/menu-phone.component';
     LegalNoticeComponent,
     AboutComponent,
     MenuPhoneComponent,
+    UserVerificationComponent,
   ],
   imports: [
     BrowserModule,
diff --git a/src/app/header/header.component.html b/src/app/header/header.component.html
index 3e9740a8e9c152ce124d430a5e4e279c937e8064..f933d061ed0f48e2f2dee5818a41825b88a6139a 100644
--- a/src/app/header/header.component.html
+++ b/src/app/header/header.component.html
@@ -13,12 +13,16 @@
     <!-- <a routerLink="/resources" [routerLinkActive]="'active'" i18n>Ressources</a>
     <a routerLink="/projects" [routerLinkActive]="'active'" i18n>Projets</a> -->
     <a routerLink="/about" [routerLinkActive]="'active'" i18n>Qui sommes-nous ?</a>
-    <!--<a routerLink="/login" [routerLinkActive]="'active'" i18n><span class="clickable ico-mglass purple"></span></a>
-    <a routerLink="/home" [routerLinkActive]="'active'" i18n
-      ><span class="ico-profile" fxLayout="column" fxLayoutAlign="center center">
+    <!-- <a routerLink="/login" [routerLinkActive]="'active'" i18n><span class="clickable ico-mglass purple"></span></a> -->
+    <button *ngIf="!isLoggedIn" (click)="isPopUpOpen = !isPopUpOpen">
+      <span class="ico-profile" fxLayout="column" fxLayoutAlign="center center">
         <span class="head"></span>
-        <span class="body"></span> </span
-    ></a> -->
+        <span class="body"></span>
+      </span>
+    </button>
+    <button *ngIf="isLoggedIn" (click)="logout()">Logout</button>
   </div>
 </div>
 <app-menu-phone *ngIf="showMenu" (closeEvent)="closeMenu($event)"></app-menu-phone>
+<app-signup-modal *ngIf="displaySignUp" [openned]="isPopUpOpen" (closed)="closeSignUpModal($event)"></app-signup-modal>
+<app-signin-modal *ngIf="!displaySignUp" [openned]="isPopUpOpen" (closed)="closeSignInModal()"></app-signin-modal>
diff --git a/src/app/header/header.component.ts b/src/app/header/header.component.ts
index b645bfde04ca991c8c78fe03cd11123e4b27f1f0..cceb2dcf1e1f88b8b13e5a77ede032bff0ebd31f 100644
--- a/src/app/header/header.component.ts
+++ b/src/app/header/header.component.ts
@@ -1,4 +1,5 @@
 import { Component, OnInit } from '@angular/core';
+import { AuthService } from '../services/auth.service';
 
 @Component({
   selector: 'app-header',
@@ -7,8 +8,10 @@ import { Component, OnInit } from '@angular/core';
 })
 export class HeaderComponent implements OnInit {
   public showMenu = false;
+  public isPopUpOpen = false;
+  public displaySignUp = true;
 
-  constructor() {}
+  constructor(private authService: AuthService) {}
   ngOnInit(): void {}
 
   public openMenu(): void {
@@ -17,4 +20,25 @@ export class HeaderComponent implements OnInit {
   public closeMenu(): void {
     this.showMenu = false;
   }
+
+  public get isLoggedIn(): boolean {
+    return this.authService.isLoggedIn();
+  }
+
+  public logout(): void {
+    this.authService.logout();
+  }
+
+  public closeSignInModal(): void {
+    this.isPopUpOpen = false;
+    this.displaySignUp = true;
+  }
+
+  public closeSignUpModal(value: boolean): void {
+    if (!value) {
+      this.displaySignUp = false;
+    } else {
+      this.isPopUpOpen = false;
+    }
+  }
 }
diff --git a/src/app/models/user-auth.model.ts b/src/app/models/user-auth.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0c3ddbf83cffa09a4cd9eaa18e714166d55fbc0e
--- /dev/null
+++ b/src/app/models/user-auth.model.ts
@@ -0,0 +1,5 @@
+export class UserAuth {
+  username: string;
+  accessToken: string;
+  expiresAt: string;
+}
diff --git a/src/app/models/user.model.ts b/src/app/models/user.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3269aeea7176afe91ee0e1eab134afc46aae0762
--- /dev/null
+++ b/src/app/models/user.model.ts
@@ -0,0 +1,8 @@
+export class User {
+  _id: string;
+  email: string;
+  password: string;
+  emailVerified: boolean;
+  role: number;
+  validationToken: string;
+}
diff --git a/src/app/services/auth.service.spec.ts b/src/app/services/auth.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f1251cacf9dda3b3bd9dc5222583fafa110ffe8f
--- /dev/null
+++ b/src/app/services/auth.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { AuthService } from './auth.service';
+
+describe('AuthService', () => {
+  let service: AuthService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(AuthService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9834bd0077a68ea597950c43c3f40ba3dc93d3b2
--- /dev/null
+++ b/src/app/services/auth.service.ts
@@ -0,0 +1,66 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { DateTime } from 'luxon';
+import { BehaviorSubject, Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { UserAuth } from '../models/user-auth.model';
+import { User } from '../models/user.model';
+@Injectable({
+  providedIn: 'root',
+})
+export class AuthService {
+  private userSubject: BehaviorSubject<UserAuth>;
+  public user: Observable<UserAuth>;
+
+  constructor(private http: HttpClient) {
+    this.userSubject = new BehaviorSubject<UserAuth>(JSON.parse(localStorage.getItem('user')));
+    this.user = this.userSubject.asObservable();
+  }
+
+  public get userValue(): UserAuth {
+    return this.userSubject.value;
+  }
+
+  public get token(): string {
+    return this.userSubject.value.accessToken;
+  }
+
+  public logout(): void {
+    localStorage.removeItem('user');
+    this.userSubject.next(null);
+  }
+
+  public isLoggedIn(): boolean {
+    if (this.userValue) {
+      return new DateTime.local().setZone('Europe/Paris') < this.getExpiration();
+    }
+    return false;
+  }
+
+  private getExpiration(): DateTime {
+    return DateTime.fromISO(this.userValue.expiresAt, { zone: 'Europe/Paris' });
+  }
+
+  public register(user: User): Observable<any> {
+    return this.http.post('api/users', user);
+  }
+
+  public login(email: string, password: string): Observable<any> {
+    return this.http
+      .post<UserAuth>('api/auth/login', { email, password })
+      .pipe(
+        map((user) => {
+          // store user details and jwt token in local storage to keep user logged in between page refreshes
+          localStorage.setItem('user', JSON.stringify(user));
+          this.userSubject.next(user);
+          return user;
+        })
+      );
+  }
+
+  public verifyUser(userId: string, token: string): Observable<any> {
+    return this.http.post(`api/users/verify/${userId}`, null, {
+      params: { token },
+    });
+  }
+}
diff --git a/src/app/shared/components/index.ts b/src/app/shared/components/index.ts
index c16e176b8a231207116e9055974735f25a43259e..4c62240127832104c3ac9dee13a1364a9386f9f3 100644
--- a/src/app/shared/components/index.ts
+++ b/src/app/shared/components/index.ts
@@ -1,10 +1,26 @@
 import { ButtonComponent } from './button/button.component';
 import { LogoCardComponent } from './logo-card/logo-card.component';
 import { ModalComponent } from './modal/modal.component';
+import { SignUpModalComponent } from './signup-modal/signup-modal.component';
+import { SignInModalComponent } from './signin-modal/signin-modal.component';
 import { SvgIconComponent } from './svg-icon/svg-icon.component';
 
 // tslint:disable-next-line: max-line-length
-export { LogoCardComponent, SvgIconComponent, ModalComponent, ButtonComponent };
+export {
+  LogoCardComponent,
+  SvgIconComponent,
+  ModalComponent,
+  ButtonComponent,
+  SignUpModalComponent,
+  SignInModalComponent,
+};
 
 // tslint:disable-next-line:variable-name
-export const SharedComponents = [LogoCardComponent, SvgIconComponent, ModalComponent, ButtonComponent];
+export const SharedComponents = [
+  LogoCardComponent,
+  SvgIconComponent,
+  ModalComponent,
+  SignUpModalComponent,
+  SignInModalComponent,
+  ButtonComponent,
+];
diff --git a/src/app/shared/components/signin-modal/signin-modal.component.html b/src/app/shared/components/signin-modal/signin-modal.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..4d0b4c3de3b555027d9551d422bd871fd372abda
--- /dev/null
+++ b/src/app/shared/components/signin-modal/signin-modal.component.html
@@ -0,0 +1,70 @@
+<div class="cModal" [ngClass]="openned ? 'oModal' : ''">
+  <div (clickOutside)="closeModal()" fxLayout="column" fxLayoutAlign="center center">
+    <div class="ico-close-wrapper">
+      <div (click)="closeModal()" class="ico-close-details"></div>
+    </div>
+    <h4>Inscription</h4>
+    <div *ngIf="!success">
+      <form [formGroup]="form" (ngSubmit)="onSubmit()">
+        <div class="form-group">
+          <label for="email">Email</label>
+          <input
+            type="email"
+            autocomplete="on"
+            formControlName="email"
+            class="form-control"
+            [ngClass]="{ 'is-invalid': submitted && f.email.errors }"
+          />
+          <div *ngIf="submitted && f.email.errors" class="invalid-feedback">
+            <div *ngIf="f.email.errors.required">Email is required</div>
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="password">Mot de passe</label>
+          <input
+            type="password"
+            autocomplete="on"
+            formControlName="password"
+            class="form-control"
+            [ngClass]="{ 'is-invalid': submitted && f.password.errors }"
+          />
+          <div *ngIf="submitted && f.password.errors" class="invalid-feedback">
+            <div *ngIf="f.password.errors.required">Le mot de passe est obligatoire</div>
+            <div *ngIf="f.password.errors.pattern">
+              Le mot de passe doit avoir au minimun 8 caractères, une majuscule, une minuscule, un chiffre et un
+              caractère spécial.
+            </div>
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="confirmPassword">Confirmation du mot de passe</label>
+          <input
+            type="password"
+            autocomplete="on"
+            formControlName="confirmPassword"
+            class="form-control"
+            [ngClass]="{ 'is-invalid': submitted && f.confirmPassword.errors }"
+          />
+          <div *ngIf="submitted && f.confirmPassword.errors" class="invalid-feedback">
+            <div *ngIf="f.confirmPassword.errors.required">La confirmation du mot de passe est obligatoire</div>
+            <div *ngIf="f.confirmPassword.errors.mustMatch">Les mot de passe ne sont pas les mêmes</div>
+          </div>
+        </div>
+
+        <div *ngIf="userAlreadyExist">Cette addresse mail est déjà utilisée</div>
+        <div class="form-group">
+          <button [disabled]="loading" class="btn btn-primary">
+            <span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
+            Register
+          </button>
+          <a routerLink="../login" class="btn btn-link">Cancel</a>
+        </div>
+      </form>
+    </div>
+    <div *ngIf="success">
+      <p>
+        Un mail de confirmation vous a été envoyé. Merci de valider votre addresse mail avant de pouvoir vous connecter.
+      </p>
+    </div>
+  </div>
+</div>
diff --git a/src/app/shared/components/signin-modal/signin-modal.component.scss b/src/app/shared/components/signin-modal/signin-modal.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..b65234fb3d7035bd0a406e3d617d3d3a3bd107e9
--- /dev/null
+++ b/src/app/shared/components/signin-modal/signin-modal.component.scss
@@ -0,0 +1,40 @@
+@import '../../../../assets/scss/typography';
+@import '../../../../assets/scss/color';
+@import '../../../../assets/scss/buttons';
+@import '../../../../assets/scss/z-index';
+@import '../../../../assets/scss/hyperlink';
+.cModal {
+  position: fixed;
+  z-index: $modal-add-structure-z-index;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  background-color: $modal-background;
+  display: none;
+}
+.cModal > div {
+  max-width: 450px;
+  position: relative;
+  top: 40%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  background: $white;
+  text-align: center;
+  border-radius: 4px;
+  @include cn-bold-16;
+  p {
+    padding: 30px 48px 0 40px;
+  }
+}
+.oModal {
+  display: block;
+}
+.ico-close-wrapper {
+  position: absolute;
+  top: -10px;
+  right: -10px;
+}
+.ico-close-details {
+  opacity: 1;
+}
diff --git a/src/app/shared/components/signin-modal/signin-modal.component.spec.ts b/src/app/shared/components/signin-modal/signin-modal.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d7bcc9ccbd538ed5f68655312242b1093cdac0ae
--- /dev/null
+++ b/src/app/shared/components/signin-modal/signin-modal.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SignInModalComponent } from './signin-modal.component';
+
+describe('SignInModalComponent', () => {
+  let component: SignInModalComponent;
+  let fixture: ComponentFixture<SignInModalComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [SignInModalComponent],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SignInModalComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/shared/components/signin-modal/signin-modal.component.ts b/src/app/shared/components/signin-modal/signin-modal.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..253ec9136e9f410ff1a85d862d04430024d42ae8
--- /dev/null
+++ b/src/app/shared/components/signin-modal/signin-modal.component.ts
@@ -0,0 +1,71 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { FormGroup, FormBuilder, Validators, AbstractControl } from '@angular/forms';
+import { first } from 'rxjs/operators';
+import { AuthService } from '../../../services/auth.service';
+import { MustMatch } from '../../validator/form';
+
+@Component({
+  selector: 'app-signin-modal',
+  templateUrl: './signin-modal.component.html',
+  styleUrls: ['./signin-modal.component.scss'],
+})
+export class SignInModalComponent implements OnInit {
+  public form: FormGroup;
+  public loading = false;
+  public submitted = false;
+  public success = false;
+  public userAlreadyExist = false;
+
+  constructor(private formBuilder: FormBuilder, private authService: AuthService) {}
+
+  @Input() public openned: boolean;
+  @Output() closed = new EventEmitter();
+
+  ngOnInit(): void {
+    this.form = this.formBuilder.group(
+      {
+        email: ['', Validators.required],
+        password: [
+          '',
+          [Validators.required, Validators.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/)],
+        ],
+        confirmPassword: [''],
+      },
+      { validator: MustMatch('password', 'confirmPassword') }
+    );
+  }
+
+  // getter for form fields
+  get f(): { [key: string]: AbstractControl } {
+    return this.form.controls;
+  }
+
+  public closeModal(): void {
+    this.closed.emit();
+  }
+
+  public onSubmit(): void {
+    this.submitted = true;
+
+    // stop here if form is invalid
+    if (this.form.invalid) {
+      return;
+    }
+
+    this.loading = true;
+    this.authService
+      .register(this.form.value)
+      .pipe(first())
+      .subscribe(
+        () => {
+          this.success = true;
+        },
+        (error) => {
+          this.loading = false;
+          if (error.error.statusCode === 400) {
+            this.userAlreadyExist = true;
+          }
+        }
+      );
+  }
+}
diff --git a/src/app/shared/components/signup-modal/signup-modal.component.html b/src/app/shared/components/signup-modal/signup-modal.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..e12cffd1bb4d9ddf98e5be88099be372786c06c3
--- /dev/null
+++ b/src/app/shared/components/signup-modal/signup-modal.component.html
@@ -0,0 +1,46 @@
+<div class="cModal" [ngClass]="openned ? 'oModal' : ''">
+  <div (clickOutside)="closeModal()" fxLayout="column" fxLayoutAlign="center center">
+    <div class="ico-close-wrapper">
+      <div (click)="closeModal()" class="ico-close-details"></div>
+    </div>
+    <h4 class="card-header">Connexion</h4>
+    <div class="card-body">
+      <form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
+        <div class="form-group">
+          <label for="username">Identifiant</label>
+          <input
+            type="text"
+            formControlName="username"
+            autocomplete="on"
+            class="form-control"
+            [ngClass]="{ 'is-invalid': submitted && f.username.errors }"
+          />
+          <div *ngIf="submitted && f.username.errors" class="invalid-feedback">
+            <div *ngIf="f.username.errors.required">Identifiant requis</div>
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="password">Mot de passe</label>
+          <input
+            type="password"
+            formControlName="password"
+            autocomplete="on"
+            class="form-control"
+            [ngClass]="{ 'is-invalid': submitted && f.password.errors }"
+          />
+          <div *ngIf="submitted && f.password.errors">
+            <div *ngIf="f.password.errors.required">Mot de passe requis</div>
+          </div>
+        </div>
+        <div *ngIf="authFailed">Identifiant ou mot de passe invalide</div>
+        <div>
+          <button [disabled]="loading">
+            <span *ngIf="loading"></span>
+            Login
+          </button>
+          <button (click)="sendSwitchToSignIn()">Inscription</button>
+        </div>
+      </form>
+    </div>
+  </div>
+</div>
diff --git a/src/app/shared/components/signup-modal/signup-modal.component.scss b/src/app/shared/components/signup-modal/signup-modal.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..b65234fb3d7035bd0a406e3d617d3d3a3bd107e9
--- /dev/null
+++ b/src/app/shared/components/signup-modal/signup-modal.component.scss
@@ -0,0 +1,40 @@
+@import '../../../../assets/scss/typography';
+@import '../../../../assets/scss/color';
+@import '../../../../assets/scss/buttons';
+@import '../../../../assets/scss/z-index';
+@import '../../../../assets/scss/hyperlink';
+.cModal {
+  position: fixed;
+  z-index: $modal-add-structure-z-index;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  background-color: $modal-background;
+  display: none;
+}
+.cModal > div {
+  max-width: 450px;
+  position: relative;
+  top: 40%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  background: $white;
+  text-align: center;
+  border-radius: 4px;
+  @include cn-bold-16;
+  p {
+    padding: 30px 48px 0 40px;
+  }
+}
+.oModal {
+  display: block;
+}
+.ico-close-wrapper {
+  position: absolute;
+  top: -10px;
+  right: -10px;
+}
+.ico-close-details {
+  opacity: 1;
+}
diff --git a/src/app/shared/components/signup-modal/signup-modal.component.spec.ts b/src/app/shared/components/signup-modal/signup-modal.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dfc6badbb2d213984c67aab883c17f7f85c44a5e
--- /dev/null
+++ b/src/app/shared/components/signup-modal/signup-modal.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SignUpModalComponent } from './signup-modal.component';
+
+describe('SignUpModalComponent', () => {
+  let component: SignUpModalComponent;
+  let fixture: ComponentFixture<SignUpModalComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [SignUpModalComponent],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SignUpModalComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/shared/components/signup-modal/signup-modal.component.ts b/src/app/shared/components/signup-modal/signup-modal.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1ef87d4d1f9ba8924e4642ec8a60bd5b3a834f56
--- /dev/null
+++ b/src/app/shared/components/signup-modal/signup-modal.component.ts
@@ -0,0 +1,74 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { FormGroup, FormBuilder, Validators, AbstractControl } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+import { first } from 'rxjs/operators';
+import { AuthService } from '../../../services/auth.service';
+
+@Component({
+  selector: 'app-signup-modal',
+  templateUrl: './signup-modal.component.html',
+  styleUrls: ['./signup-modal.component.scss'],
+})
+export class SignUpModalComponent implements OnInit {
+  public loginForm: FormGroup;
+  public loading = false;
+  public submitted = false;
+  public authFailed = false;
+  public returnUrl: string;
+
+  constructor(
+    private formBuilder: FormBuilder,
+    private route: ActivatedRoute,
+    private router: Router,
+    private authService: AuthService
+  ) {}
+
+  @Input() public openned: boolean;
+  @Output() closed = new EventEmitter<boolean>();
+
+  ngOnInit(): void {
+    this.loginForm = this.formBuilder.group({
+      username: ['', Validators.required],
+      password: ['', Validators.required],
+    });
+    // get return url from route parameters or default to '/'
+    this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
+  }
+
+  // getter for form fields
+  get f(): { [key: string]: AbstractControl } {
+    return this.loginForm.controls;
+  }
+
+  public closeModal(): void {
+    this.closed.emit(true);
+  }
+
+  public sendSwitchToSignIn(): void {
+    this.closed.emit(false);
+  }
+
+  public onSubmit(): void {
+    this.submitted = true;
+
+    // stop here if form is invalid
+    if (this.loginForm.invalid) {
+      return;
+    }
+
+    this.loading = true;
+    this.authService
+      .login(this.f.username.value, this.f.password.value)
+      .pipe(first())
+      .subscribe(
+        () => {
+          this.router.navigate([this.returnUrl]);
+          this.closeModal();
+        },
+        () => {
+          this.loading = false;
+          this.authFailed = true;
+        }
+      );
+  }
+}
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index 4e6a02828e3c2ed7197aab10de2e29437bc177f3..3acb5e40b1e85264b0188e786f40b0c3bd29e411 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -1,13 +1,14 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
+import { FlexLayoutModule } from '@angular/flex-layout';
 import { SharedComponents } from './components';
 import { SharedPipes } from './pipes';
 import { SharedDirectives } from './directives';
-import { RouterModule } from '@angular/router';
-import { FlexLayoutModule } from '@angular/flex-layout';
 import { SvgIconComponent } from './components/svg-icon/svg-icon.component';
 @NgModule({
-  imports: [CommonModule, RouterModule, FlexLayoutModule],
+  imports: [CommonModule, RouterModule, FlexLayoutModule, ReactiveFormsModule],
   declarations: [...SharedPipes, ...SharedComponents, ...SharedDirectives, SvgIconComponent],
   exports: [...SharedPipes, ...SharedComponents, ...SharedDirectives],
 })
diff --git a/src/app/shared/validator/form.ts b/src/app/shared/validator/form.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1a1cc906def4e3e5fe38aef3e0dd61155f9a8b54
--- /dev/null
+++ b/src/app/shared/validator/form.ts
@@ -0,0 +1,16 @@
+import { FormGroup } from '@angular/forms';
+
+// custom validator to check that two fields match
+export function MustMatch(controlName: string, matchingControlName: string): any {
+  return (formGroup: FormGroup) => {
+    const control = formGroup.controls[controlName];
+    const matchingControl = formGroup.controls[matchingControlName];
+
+    // set error on matchingControl if validation fails
+    if (control.value !== matchingControl.value) {
+      matchingControl.setErrors({ mustMatch: true });
+    } else {
+      matchingControl.setErrors(null);
+    }
+  };
+}
diff --git a/src/app/user-verification/user-verification.component.html b/src/app/user-verification/user-verification.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..acb513c81be1f0418d4ccdec20f41e2644e76a97
--- /dev/null
+++ b/src/app/user-verification/user-verification.component.html
@@ -0,0 +1,13 @@
+<div fxLayout="column" class="content-container">
+  <h1 style="display: none">Vérification du mail utilisateur</h1>
+  <div class="section-container" fxLayout="colum" fxLayoutAlign="center center">
+    <p *ngIf="!verificationSuccess && !verificationIssue">Votre email est en cours de vérification ...</p>
+    <p *ngIf="verificationSuccess">
+      Vous avez correctement validé l'email associé a votre compte. Vous pouvez dès maintenant vous connecter au site.
+    </p>
+    <p *ngIf="verificationIssue">
+      Une erreur est survenue lors de la validation de votre email... Veuillez envoyer un mail au support.
+    </p>
+    <div></div>
+  </div>
+</div>
diff --git a/src/app/user-verification/user-verification.component.scss b/src/app/user-verification/user-verification.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/user-verification/user-verification.component.spec.ts b/src/app/user-verification/user-verification.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..241a7b6ad2873d8422d1b0d5563d9e0d77a0a3ec
--- /dev/null
+++ b/src/app/user-verification/user-verification.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { UserVerificationComponent } from './user-verification.component';
+
+describe('UserVerificationComponent', () => {
+  let component: UserVerificationComponent;
+  let fixture: ComponentFixture<UserVerificationComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ UserVerificationComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(UserVerificationComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/user-verification/user-verification.component.ts b/src/app/user-verification/user-verification.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e5c0e4e7903c5777b94d1d6e536f8af442850414
--- /dev/null
+++ b/src/app/user-verification/user-verification.component.ts
@@ -0,0 +1,37 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { AuthService } from '../services/auth.service';
+
+@Component({
+  selector: 'app-user-verification',
+  templateUrl: './user-verification.component.html',
+  styleUrls: ['./user-verification.component.scss'],
+})
+export class UserVerificationComponent implements OnInit {
+  public userId: string;
+  public token: string;
+  public verificationSuccess = false;
+  public verificationIssue = false;
+
+  constructor(private activatedRoute: ActivatedRoute, private authService: AuthService) {
+    this.activatedRoute.queryParams.subscribe((params) => {
+      this.token = params['token'];
+    });
+  }
+
+  ngOnInit(): void {
+    this.userId = this.activatedRoute.snapshot.paramMap.get('id');
+    this.sendVerification();
+  }
+
+  private sendVerification(): void {
+    this.authService.verifyUser(this.userId, this.token).subscribe(
+      () => {
+        this.verificationSuccess = true;
+      },
+      () => {
+        this.verificationIssue = true;
+      }
+    );
+  }
+}