diff --git a/Dockerfile b/Dockerfile
index a3851616acdbb50ef12377d640803b75ad6f7f12..e441522eaa3c42fcc3a37fb1630c76a7ac5ddeb2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,6 +9,9 @@ RUN npm install
 # Copy the project
 COPY . /app
 
+# Launch postinstall script (to include crypto module)
+RUN npm run postinstall
+
 ARG conf
 
 # Building the Angular app /dist 
diff --git a/config/config-dev.json b/config/config-dev.json
index e154cc463bc6600168812652f7d706e0b587c0fb..adf822d5cb7103ae1e517c14ba05e845c154d0c4 100644
--- a/config/config-dev.json
+++ b/config/config-dev.json
@@ -1,11 +1,17 @@
 {
   "organizations": {
-    "url": "https://kong-dev.alpha.grandlyon.com/organizations/"
+    "url": "https://kong-dev.alpha.grandlyon.com/organizations/organizations/"
   },
   "resources": {
     "url": "https://kong-dev.alpha.grandlyon.com/resources/"
   },
   "mediaLibrary": {
     "url": "https://kong-dev.alpha.grandlyon.com/media-library/"
+  },
+  "authentication": {
+    "url": "https://kong-dev.alpha.grandlyon.com/authentication/"
+  },
+  "middlewareLegacyAuth": {
+    "url": "https://kong-dev.alpha.grandlyon.com/middleware-legacy/"
   }
 }
diff --git a/config/config-rec.json b/config/config-rec.json
index 99666bacf0611bdb0dc575d1877ca8fd1161b41f..804b6b67d735472bc7d026d357d0ff410c63004f 100644
--- a/config/config-rec.json
+++ b/config/config-rec.json
@@ -1,11 +1,17 @@
 {
   "organizations": {
-    "url": "https://kong-rec.alpha.grandlyon.com/organizations/"
+    "url": "https://kong-rec.alpha.grandlyon.com/organizations/organizations/"
   },
   "resources": {
     "url": "https://kong-rec.alpha.grandlyon.com/resources/"
   },
   "mediaLibrary": {
     "url": "https://kong-rec.alpha.grandlyon.com/media-library/"
+  },
+  "authentication": {
+    "url": "https://kong-rec.alpha.grandlyon.com/authentication/"
+  },
+  "middlewareLegacyAuth": {
+    "url": "https://kong-rec.alpha.grandlyon.com/middleware-legacy/"
   }
 }
diff --git a/package-lock.json b/package-lock.json
index 4880633268b69e163a910ab76ab2c76cce10bede..ed6e35f5b5e17cc2a4b35f252a2b2989200ab5e0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "admin-gui",
-  "version": "0.0.0",
+  "version": "1.0.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -1669,7 +1669,6 @@
       "version": "0.2.4",
       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
       "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
-      "dev": true,
       "requires": {
         "safer-buffer": "~2.1.0"
       }
@@ -7197,6 +7196,14 @@
         "semver": "^5.3.0"
       }
     },
+    "node-rsa": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.0.5.tgz",
+      "integrity": "sha512-9o51yfV167CtQANnuAf+5owNs7aIMsAKVLhNaKuRxihsUUnfoBMN5OTVOK/2mHSOWaWq9zZBiRM3bHORbTZqrg==",
+      "requires": {
+        "asn1": "^0.2.4"
+      }
+    },
     "node-sass": {
       "version": "4.11.0",
       "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz",
@@ -8862,8 +8869,7 @@
     "safer-buffer": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "dev": true
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
     "sass-graph": {
       "version": "2.2.4",
diff --git a/package.json b/package.json
index d9459cdc73c1364adc05fc7b717eda481ce7812f..306f117e44ada4f9e28144866dbb13ce4f9a2f27 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "admin-gui",
-  "version": "1.0.0",
+  "version": "1.1.0",
   "scripts": {
     "ng": "ng",
     "start": "ng serve",
@@ -9,7 +9,8 @@
     "build:prod": "node --max_old_space_size=4096 ./node_modules/@angular/cli/bin/ng build --configuration=production",
     "test": "ng test",
     "lint": "ng lint",
-    "e2e": "ng e2e"
+    "e2e": "ng e2e",
+    "postinstall": "node patch.js"
   },
   "private": true,
   "dependencies": {
@@ -25,6 +26,7 @@
     "@angular/router": "^7.2.4",
     "bulma": "^0.7.4",
     "core-js": "^2.6.4",
+    "node-rsa": "^1.0.5",
     "rxjs": "^6.4.0",
     "rxjs-tslint": "^0.1.7",
     "sass-recursive-map-merge": "^1.0.1",
diff --git a/patch.js b/patch.js
new file mode 100644
index 0000000000000000000000000000000000000000..909dfb2e373737981d83371f24fd67b4245e44f5
--- /dev/null
+++ b/patch.js
@@ -0,0 +1,13 @@
+const fs = require('fs');
+const f = 'node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js';
+
+fs.readFile(f, 'utf8', function (err,data) {
+  if (err) {
+    return console.log(err);
+  }
+  var result = data.replace(/node: false/g, 'node: {crypto: true}');
+
+  fs.writeFile(f, result, 'utf8', function (err) {
+    if (err) return console.log(err);
+  });
+});
\ No newline at end of file
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 9b843b6f527b5aebbae62eec91003795da9b875f..2b577c9af1411a17305f79881a6ec74139773d22 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -8,6 +8,18 @@ import { RouterModule } from '@angular/router';
 import { AppRoutingModule } from './app.routing.module';
 import { AppServices, AppConfigService } from './services';
 import { AppComponents } from './components';
+import { UserModule } from './user/user.module';
+import { UserService } from './user/services';
+
+// Function used by APP_INITIALIZER before the app start: init user info / statut (expect a promise)
+export function initUserService(authService: UserService) {
+  return (): Promise<any> => {
+    return new Promise((resolve, reject) => {
+      authService.initializeService();
+      resolve();
+    });
+  };
+}
 
 export function initAppConfig(appConfigService: AppConfigService) {
   return (): Promise<any> => {
@@ -31,9 +43,16 @@ export function initAppConfig(appConfigService: AppConfigService) {
     BrowserAnimationsModule,
     HttpClientModule,
     ReactiveFormsModule,
+    UserModule,
   ],
   providers: [
     ...AppServices,
+    {
+      provide: APP_INITIALIZER,
+      useFactory: initUserService,
+      deps: [UserService],
+      multi: true,
+    },
     {
       provide: APP_INITIALIZER,
       useFactory: initAppConfig,
diff --git a/src/app/app.routing.module.ts b/src/app/app.routing.module.ts
index 2e229688a10fc14059435ecf98a68a990b6f7dc4..e573d0832074c5a3e51e76bd3ea2ddd67b912ba3 100644
--- a/src/app/app.routing.module.ts
+++ b/src/app/app.routing.module.ts
@@ -8,11 +8,13 @@ import { ResourcesComponent } from './components/resources/list/resources.compon
 import { ResourceFormComponent } from './components/resources/edit/resource-form.component';
 import { ResourceDetailComponent } from './components/resources/detail/resource-detail.component';
 import { FormatsComponent, FormatDetailComponent, FormatFormComponent } from './components';
+import { AuthenticatedGuard } from './user/guards/authenticated.guard';
 
 const appRoutes: Routes = [
   {
     path: '',
     component: WelcomeComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Bienvenue',
     },
@@ -20,6 +22,7 @@ const appRoutes: Routes = [
   {
     path: 'organizations',
     component: OrganizationsComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Organisations',
     },
@@ -27,6 +30,7 @@ const appRoutes: Routes = [
   {
     path: 'organizations/new',
     component: OrganizationFormComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Nouvelle organisation',
     },
@@ -34,6 +38,7 @@ const appRoutes: Routes = [
   {
     path: 'organizations/:id/edit',
     component: OrganizationFormComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Modifier l\'organisation',
     },
@@ -41,6 +46,7 @@ const appRoutes: Routes = [
   {
     path: 'organizations/:id',
     component: OrganizationDetailComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Organisation',
     },
@@ -48,6 +54,7 @@ const appRoutes: Routes = [
   {
     path: 'resources',
     component: ResourcesComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Ressources',
     },
@@ -55,6 +62,7 @@ const appRoutes: Routes = [
   {
     path: 'resources/new',
     component: ResourceFormComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Nouvelle ressource',
     },
@@ -62,6 +70,7 @@ const appRoutes: Routes = [
   {
     path: 'resources/:id/edit',
     component: ResourceFormComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Modifier la ressource',
     },
@@ -69,6 +78,7 @@ const appRoutes: Routes = [
   {
     path: 'resources/:id',
     component: ResourceDetailComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Ressource',
     },
@@ -76,6 +86,7 @@ const appRoutes: Routes = [
   {
     path: 'formats',
     component: FormatsComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Formats',
     },
@@ -83,6 +94,7 @@ const appRoutes: Routes = [
   {
     path: 'formats/new',
     component: FormatFormComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Nouveau format',
     },
@@ -90,6 +102,7 @@ const appRoutes: Routes = [
   {
     path: 'formats/:id/edit',
     component: FormatFormComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Modifier le format',
     },
@@ -97,6 +110,7 @@ const appRoutes: Routes = [
   {
     path: 'formats/:id',
     component: FormatDetailComponent,
+    canActivate: [AuthenticatedGuard],
     data: {
       title: 'Format',
     },
@@ -110,7 +124,5 @@ const appRoutes: Routes = [
   exports: [
     RouterModule,
   ],
-  providers: [
-  ],
 })
-export class AppRoutingModule {}
+export class AppRoutingModule { }
diff --git a/src/app/components/welcome/welcome.component.html b/src/app/components/welcome/welcome.component.html
index 7cbaf54bb520750aec4db7993745dc014868579f..099c771bdebfe62ef89f8357e6a8805c8e2c0cbf 100644
--- a/src/app/components/welcome/welcome.component.html
+++ b/src/app/components/welcome/welcome.component.html
@@ -1,3 +1,7 @@
 <section>
-  <h2 class="has-text-centered">Services Backend de la plateforme Data Grand Lyon</h2>
-</section>
+  <div class="user-info-container">
+    <p class="welcome-back-message">Content de vous revoir {{ loggedInUserFullname }}</p>
+
+    <button class="button button-gl" (click)="loggout()">Deconnexion</button>
+  </div>
+</section>
\ No newline at end of file
diff --git a/src/app/components/welcome/welcome.component.scss b/src/app/components/welcome/welcome.component.scss
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..13ea27f83c932252bc787143512353bdbdc0272b 100644
--- a/src/app/components/welcome/welcome.component.scss
+++ b/src/app/components/welcome/welcome.component.scss
@@ -0,0 +1,9 @@
+.user-info-container {
+  text-align: center;
+  margin-top: 2rem;
+}
+
+.welcome-back-message {
+  font-size: 1.5rem;
+  margin-bottom: 1rem;
+}
diff --git a/src/app/components/welcome/welcome.component.ts b/src/app/components/welcome/welcome.component.ts
index 956948c2a3778667913f456f6c2a880408987786..4d118c0dc02557dee83bf5f83b1159c360b0b731 100644
--- a/src/app/components/welcome/welcome.component.ts
+++ b/src/app/components/welcome/welcome.component.ts
@@ -1,4 +1,7 @@
 import { Component, OnInit } from '@angular/core';
+import { UserService } from '../../user/services';
+import { Router } from '@angular/router';
+import { NotificationService } from '../../services';
 
 @Component({
   selector: 'app-welcome',
@@ -8,8 +11,20 @@ import { Component, OnInit } from '@angular/core';
 
 export class WelcomeComponent implements OnInit {
 
-  constructor() {}
+  constructor(
+    private _userService: UserService,
+    private _router: Router,
+  ) { }
 
-  ngOnInit(): void {}
+  ngOnInit(): void { }
+
+  get loggedInUserFullname() {
+    return `${this._userService.user.firstName} ${this._userService.user.lastName}`;
+  }
+
+  loggout() {
+    this._userService.resetAuth();
+    this._router.navigate(['/login']);
+  }
 
 }
diff --git a/src/app/services/app-config.service.ts b/src/app/services/app-config.service.ts
index 66e9fd31fad98efbde56154a7c9f346e8cf1dcb4..c8fb34321e489120210a882aa6c17b576b2fe8ae 100644
--- a/src/app/services/app-config.service.ts
+++ b/src/app/services/app-config.service.ts
@@ -10,6 +10,12 @@ export class AppConfig {
   mediaLibrary: {
     url: string;
   };
+  authentication: {
+    url: string;
+  };
+  middlewareLegacyAuth: {
+    url: string;
+  };
 }
 
 export let APP_CONFIG: AppConfig;
diff --git a/src/app/services/format.service.ts b/src/app/services/format.service.ts
index 722f25a8a0188f9c85742e343b50e66f59a167c7..bd2b12a3a6c1c5b27570b675282159bf9922bfa4 100644
--- a/src/app/services/format.service.ts
+++ b/src/app/services/format.service.ts
@@ -58,18 +58,18 @@ export class FormatService {
   }
 
   delete(id) {
-    return this._httpClient.delete(this.formatServiceUrl + id);
+    return this._httpClient.delete(this.formatServiceUrl + id, { withCredentials: true });
   }
 
   replaceOrCreate(data): Observable<Format> {
     if (data.id) {
-      return this._httpClient.put<IFormat>(this.formatServiceUrl + data.id, data).pipe(
+      return this._httpClient.put<IFormat>(this.formatServiceUrl + data.id, data, { withCredentials: true }).pipe(
         map((response) => {
           return new Format(response);
         }),
       );
     }
-    return this._httpClient.post<IFormat>(this.formatServiceUrl, data).pipe(
+    return this._httpClient.post<IFormat>(this.formatServiceUrl, data, { withCredentials: true }).pipe(
       map((response) => {
         return new Format(response);
       }),
diff --git a/src/app/services/organization.service.ts b/src/app/services/organization.service.ts
index d5a82d7ce9d00a5b3a3aeebd765a1a93fca73923..689c7407ef08430af970d1ed7eb7fabde66bab85 100644
--- a/src/app/services/organization.service.ts
+++ b/src/app/services/organization.service.ts
@@ -50,7 +50,7 @@ export class OrganizationService {
   }
 
   delete(id) {
-    return this._httpClient.delete(APP_CONFIG.organizations.url + id);
+    return this._httpClient.delete(APP_CONFIG.organizations.url + id, { withCredentials: true });
   }
 
   uploadLogoAndSaveOrganization(logoFile, organization) {
@@ -66,7 +66,7 @@ export class OrganizationService {
     const formData = new FormData();
     formData.append('file', logoFile);
 
-    return this._httpClient.post<string>(`${APP_CONFIG.mediaLibrary.url}media`, formData).pipe(
+    return this._httpClient.post<string>(`${APP_CONFIG.mediaLibrary.url}media`, formData, { withCredentials: true }).pipe(
       map((response) => {
         return response;
       }),
@@ -75,14 +75,14 @@ export class OrganizationService {
 
   replaceOrCreate(data: Organization): Observable<Organization> {
     if (data.id) {
-      return this._httpClient.put<IOrganization>(APP_CONFIG.organizations.url + data.id, data).pipe(
+      return this._httpClient.put<IOrganization>(APP_CONFIG.organizations.url + data.id, data, { withCredentials: true }).pipe(
         map((response) => {
           return new Organization(response);
         }),
       );
     }
 
-    return this._httpClient.post<IOrganization>(APP_CONFIG.organizations.url, data).pipe(
+    return this._httpClient.post<IOrganization>(APP_CONFIG.organizations.url, data, { withCredentials: true }).pipe(
       map((response) => {
         return new Organization(response);
       }),
diff --git a/src/app/services/resource.service.ts b/src/app/services/resource.service.ts
index b598eb31653bfe0f7fd8005c2d93a78bb996abf5..a46b3d35be2e366d01c26696c4b87fa7ab1db43f 100644
--- a/src/app/services/resource.service.ts
+++ b/src/app/services/resource.service.ts
@@ -52,18 +52,18 @@ export class ResourceService {
   }
 
   delete(id) {
-    return this._httpClient.delete(this.resourceServiceUrl + id);
+    return this._httpClient.delete(this.resourceServiceUrl + id, { withCredentials: true });
   }
 
   replaceOrCreate(data): Observable<Resource> {
     if (data.id) {
-      return this._httpClient.put<IResource>(this.resourceServiceUrl + data.id, data).pipe(
+      return this._httpClient.put<IResource>(this.resourceServiceUrl + data.id, data, { withCredentials: true }).pipe(
         map((response) => {
           return new Resource(response);
         }),
       );
     }
-    return this._httpClient.post<IResource>(this.resourceServiceUrl, data).pipe(
+    return this._httpClient.post<IResource>(this.resourceServiceUrl, data, { withCredentials: true }).pipe(
       map((response) => {
         return new Resource(response);
       }),
@@ -73,7 +73,7 @@ export class ResourceService {
   createResourceFormats(resourceId: string, resourceFormats: IResourceFormat[]): Observable<IResourceFormat> {
     return from(resourceFormats).pipe(
       concatMap((rf) => {
-        return this._httpClient.post<IResourceFormat>(`${this.resourceServiceUrl}${resourceId}/formats`, rf);
+        return this._httpClient.post<IResourceFormat>(`${this.resourceServiceUrl}${resourceId}/formats`, rf, { withCredentials: true });
       }),
     );
   }
@@ -81,7 +81,11 @@ export class ResourceService {
   updateResourceFormats(resourceId: string, resourceFormats: IResourceFormat[]) {
     return from(resourceFormats).pipe(
       concatMap((rf) => {
-        return this._httpClient.put<IResourceFormat>(`${this.resourceServiceUrl}${resourceId}/formats/${rf.id}`, rf);
+        return this._httpClient.put<IResourceFormat>(
+          `${this.resourceServiceUrl}${resourceId}/formats/${rf.id}`,
+          rf,
+          { withCredentials: true },
+        );
       }),
     );
   }
@@ -89,7 +93,10 @@ export class ResourceService {
   deleteResourceFormats(resourceId: string, resourceFormatsId: string[]) {
     return from(resourceFormatsId).pipe(
       concatMap((rfId) => {
-        return this._httpClient.delete<IResourceFormat>(`${this.resourceServiceUrl}${resourceId}/formats/${rfId}`);
+        return this._httpClient.delete<IResourceFormat>(
+          `${this.resourceServiceUrl}${resourceId}/formats/${rfId}`,
+          { withCredentials: true },
+        );
       }),
     );
   }
diff --git a/src/app/user/components/index.ts b/src/app/user/components/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e17c0f5ba56dc2c38e8c16548e2044d3f180da61
--- /dev/null
+++ b/src/app/user/components/index.ts
@@ -0,0 +1,8 @@
+import { LoginComponent } from './login/login.component';
+
+export { LoginComponent };
+
+// tslint:disable-next-line:variable-name
+export const UserComponents = [
+  LoginComponent,
+];
diff --git a/src/app/user/components/login/login.component.html b/src/app/user/components/login/login.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..9879ce5af188eff8f3b9d77c8c05f7174cdbfd8b
--- /dev/null
+++ b/src/app/user/components/login/login.component.html
@@ -0,0 +1,56 @@
+<h1 class="has-text-centered" i18n="@@login.signIn">Sign In</h1>
+
+<div class="login-form-container">
+  <form [formGroup]="form" (ngSubmit)="login()">
+    <div class="columns">
+      <div class="column is-8-touch is-offset-2-touch is-6 is-offset-3">
+        <div class="notification is-danger" *ngIf="errorStatus !== null">
+          <button class="delete" (click)="closeErrorMessage()"></button>
+          <span *ngIf="errorStatus === 400; else genericErrorTemplate" i18n="@@login.incorrectCredentials">Your
+            credentials are not correct.</span>
+          <ng-template #genericErrorTemplate><span i18n="@@login.internalError">Something went wrong, please try again
+              later.</span></ng-template>
+        </div>
+
+        <div class="field">
+          <label class="label" for="username">Email:</label>
+          <p class="control has-icons-left">
+            <input id="username" class="input" type="email" formControlName="username"
+              [ngClass]="{'is-danger': fieldIsInvalid('username'), 'is-success': fieldIsValid('username')}">
+            <span class="icon is-small is-left">
+              <i class="fas fa-envelope"></i>
+            </span>
+          </p>
+          <div class="form-incorrect-field-message" *ngIf="fieldIsInvalid('username')">
+            <div *ngIf="username.errors['required']" i18n="@@login.emailRequired">
+              Email is required.
+            </div>
+            <div *ngIf="username.errors['email']" i18n="@@login.incorrectEmail">
+              You need to provide a valid email.
+            </div>
+          </div>
+        </div>
+
+        <div class="field">
+          <label class="label" for="password" i18n="@@login.password">Password:</label>
+          <p class="control has-icons-left">
+            <input id="password" class="input" type="password" formControlName="password"
+              [ngClass]="{'is-danger': fieldIsInvalid('password'), 'is-success': fieldIsValid('password')}">
+            <span class="icon is-small is-left">
+              <i class="fas fa-lock"></i>
+            </span>
+          </p>
+          <div *ngIf="fieldIsInvalid('password')" class="form-incorrect-field-message">
+            <div *ngIf="password.errors['required']" i18n="@@login.passwordRequired">
+              Password is required.
+            </div>
+          </div>
+        </div>
+        <div class="has-text-centered button-wrapper">
+          <button class="button button-gl sign-in-btn" type="submit" [ngClass]="{'is-loading': formDisabled}"
+            [disabled]="form.invalid || formDisabled" i18n="@@login.signInBtn">Sign In</button>
+        </div>
+      </div>
+    </div>
+  </form>
+</div>
\ No newline at end of file
diff --git a/src/app/user/components/login/login.component.scss b/src/app/user/components/login/login.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..9d2018c16e0f25a6bff458d4dbef43df82b806ba
--- /dev/null
+++ b/src/app/user/components/login/login.component.scss
@@ -0,0 +1,71 @@
+h1 {
+  font-size: 2rem;
+  margin: 0;
+  padding: 1.25rem;
+  background-color: white;
+}
+
+.login-form-container {
+  background-color: white;
+  padding: 0 1rem 1rem 1rem;
+  margin: 1.5rem;
+
+  .columns:first-of-type {
+    margin-top: 0;
+  }
+}
+
+.notification {
+  padding: 0.5rem 1.75rem 0.5rem 0.75rem;
+}
+
+.button-wrapper {
+  margin-top: 1rem;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  .sign-in-btn {
+    margin-right: 1rem;
+  }
+}
+
+.inline {
+  display: inline-block;
+  padding: 0 0.5rem;
+
+  a {
+    img {
+      max-height: 100%;
+      margin: 0.5rem 0.5rem;
+    }
+  }
+}
+
+.no-account-info {
+  margin-bottom: 1rem;
+  display: block
+}
+
+// Form
+label {
+  font-size: 1rem;
+  font-weight: normal;
+  font-style: normal;
+
+  &:hover {
+    cursor: pointer;
+  }
+}
+
+label .required-field {
+  color: #F72F2F;
+  padding-left: 0.25rem;
+}
+
+.form-incorrect-field-message {
+  color: #333744;
+  font-style: italic;
+  font-size: 0.875rem;
+  margin-top: 0.2rem;
+}
diff --git a/src/app/user/components/login/login.component.spec.ts b/src/app/user/components/login/login.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7336d9ae5d62d9dff254c5934a3c8546ccaa4df2
--- /dev/null
+++ b/src/app/user/components/login/login.component.spec.ts
@@ -0,0 +1,48 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LoginComponent } from './login.component';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+import { UserService } from '../../services';
+
+export class UserServiceMock {
+
+  constructor() { }
+
+  get userIsSignedIn() {
+    return false;
+  }
+
+}
+
+describe('LoginComponent', () => {
+  let component: LoginComponent;
+  let fixture: ComponentFixture<LoginComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      imports: [
+        ReactiveFormsModule,
+        RouterTestingModule,
+      ],
+      declarations: [LoginComponent],
+      providers: [
+        {
+          provide: UserService,
+          useClass: UserServiceMock,
+        },
+      ],
+    })
+      .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(LoginComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/user/components/login/login.component.ts b/src/app/user/components/login/login.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..97a973cece6c5641a287258eba65240ee532ace7
--- /dev/null
+++ b/src/app/user/components/login/login.component.ts
@@ -0,0 +1,73 @@
+import { Component, OnInit } from '@angular/core';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+import { HttpErrorResponse } from '@angular/common/http';
+import { UserService } from '../../services';
+
+@Component({
+  selector: 'app-login',
+  templateUrl: './login.component.html',
+  styleUrls: ['./login.component.scss'],
+})
+export class LoginComponent implements OnInit {
+
+  form: FormGroup;
+  errorStatus: number = null;
+
+  constructor(
+    private _fb: FormBuilder,
+    private _userService: UserService,
+    private _router: Router,
+  ) {
+
+    this.form = this._fb.group({
+      username: ['', [Validators.required, Validators.email]],
+      password: ['', Validators.required],
+    });
+  }
+
+  ngOnInit() { }
+
+  login() {
+    if (this.form.valid) {
+      this.form.disable();
+      this._userService.login(this.form.value).subscribe(
+        (res) => {
+          this.form.enable();
+          this.errorStatus = null;
+          this._router.navigate(['/']);
+        },
+        (err) => {
+          if (err instanceof HttpErrorResponse) {
+            this.errorStatus = err.status;
+          } else {
+            this.errorStatus = 500;
+          }
+          this.form.enable();
+        },
+      );
+    } else {
+      this.errorStatus = 400;
+    }
+  }
+
+  closeErrorMessage() {
+    this.errorStatus = null;
+  }
+
+  fieldIsValid(field: string) {
+    return (this.form.get(field).touched) && this.form.get(field).valid;
+  }
+
+  fieldIsInvalid(field: string) {
+    return (this.form.get(field).touched) && this.form.get(field).invalid;
+  }
+
+  get username() { return this.form.get('username'); }
+  get password() { return this.form.get('password'); }
+
+  get formDisabled() {
+    return this.form.disabled;
+  }
+
+}
diff --git a/src/app/user/guards/authenticated.guard.ts b/src/app/user/guards/authenticated.guard.ts
new file mode 100644
index 0000000000000000000000000000000000000000..80a52ae68aa2c91ab11cd7970bfbfae45cf91e07
--- /dev/null
+++ b/src/app/user/guards/authenticated.guard.ts
@@ -0,0 +1,17 @@
+import { Injectable } from '@angular/core';
+import { Router, CanActivate } from '@angular/router';
+import { UserService } from '../services';
+
+@Injectable()
+export class AuthenticatedGuard implements CanActivate {
+
+  constructor(public _userService: UserService, public router: Router) { }
+
+  canActivate(): boolean {
+    if (!this._userService.userIsSignedIn) {
+      this.router.navigate(['/login']);
+      return false;
+    }
+    return true;
+  }
+}
diff --git a/src/app/user/guards/index.ts b/src/app/user/guards/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cf44fd86f547bd0e0d759d623bd5788fc0f22240
--- /dev/null
+++ b/src/app/user/guards/index.ts
@@ -0,0 +1,8 @@
+import { AuthenticatedGuard } from './authenticated.guard';
+import { UnauthenticatedGuard } from './unauthenticated.guard';
+
+// tslint:disable-next-line:variable-name
+export const UserGuards = [
+  AuthenticatedGuard,
+  UnauthenticatedGuard,
+];
diff --git a/src/app/user/guards/unauthenticated.guard.ts b/src/app/user/guards/unauthenticated.guard.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e41261c1340f3f4073c371e67ed58b295dc10299
--- /dev/null
+++ b/src/app/user/guards/unauthenticated.guard.ts
@@ -0,0 +1,29 @@
+import { Injectable } from '@angular/core';
+import { Router, CanActivate } from '@angular/router';
+import { UserService } from '../services';
+import { NotificationService } from '../../services';
+
+@Injectable()
+export class UnauthenticatedGuard implements CanActivate {
+
+  constructor(
+    private _userService: UserService,
+    private _router: Router,
+    private _notificationService: NotificationService,
+  ) { }
+
+  // This guard is used to restrict the access to unauthenticated user on particular routes
+  // example: login, signup, resetPassword...
+  // It also notify the user that he is already logged in
+  canActivate(): boolean {
+    if (this._userService.userIsSignedIn) {
+      this._router.navigate(['/']);
+      this._notificationService.notify({
+        type: 'warning',
+        message: 'Vous ne pouvez pas accéder à cette page lorsque vous êtes déjà authentifié.',
+      });
+      return false;
+    }
+    return true;
+  }
+}
diff --git a/src/app/user/interceptors/auth-interceptor.ts b/src/app/user/interceptors/auth-interceptor.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2f8f113eaf85d5183915cb387743d1faed7300e5
--- /dev/null
+++ b/src/app/user/interceptors/auth-interceptor.ts
@@ -0,0 +1,23 @@
+import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+
+@Injectable()
+export class AuthInterceptor implements HttpInterceptor {
+
+  intercept(
+    req: HttpRequest<any>,
+    next: HttpHandler,
+  ): Observable<HttpEvent<any>> {
+    const xsrfToken = localStorage.getItem('xsrfToken');
+    let request = req;
+
+    // && req.url.includes('https://data-intothesky.alpha.grandlyon.com/authentication/api/logout'
+    if (xsrfToken) {
+      request = req.clone({
+        headers: req.headers.set('x-xsrf-token', xsrfToken),
+      });
+    }
+    return next.handle(request);
+  }
+}
diff --git a/src/app/user/models/index.ts b/src/app/user/models/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4841469cfaaabda156dbf83a13accd4c3df551f1
--- /dev/null
+++ b/src/app/user/models/index.ts
@@ -0,0 +1,8 @@
+import {
+  User, ILoginResponse, ICreateAccountForm, LegacyAccount, IUserInfo, PasswordUpdateForm,
+  IPasswordForgottenForm,
+} from './user.model';
+
+export {
+  IUserInfo, PasswordUpdateForm, User, ILoginResponse, ICreateAccountForm, LegacyAccount, IPasswordForgottenForm,
+};
diff --git a/src/app/user/models/user.model.ts b/src/app/user/models/user.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cbb42c8d96ecbd18e7ba98b0a6ad1a4ddffc73c8
--- /dev/null
+++ b/src/app/user/models/user.model.ts
@@ -0,0 +1,120 @@
+export class User {
+  firstName: string;
+  lastName: string;
+  email: string;
+  username: string;
+
+  //  payload is the decrypted payload of the JWT token
+  constructor(payload) {
+    if (payload) {
+      this.firstName = payload.firstName;
+      this.lastName = payload.lastName;
+      this.email = payload.email;
+      this.username = payload.username;
+    }
+  }
+}
+
+export interface ILoginResponse {
+  token: string;
+}
+
+export interface ICreateAccountForm {
+  firstName: string;
+  lastName: string;
+  email: string;
+  emailConfirmation: string;
+  password: string;
+  passwordConfirmation: string;
+  acceptMessages: boolean;
+  entreprise: string;
+  address: string;
+  zipcode: string;
+  city: string;
+  country: string;
+  // cgu: boolean;
+  consent: boolean;
+}
+
+export class LegacyAccount {
+  firstName: string;
+  lastName: string;
+  username: string;
+  email: string;
+  password: string;
+  acceptMessages: boolean;
+  entreprise: string;
+  address: string;
+  zipcode: string;
+  city: string;
+  country: string;
+
+  constructor(form: ICreateAccountForm) {
+    this.firstName = form.firstName;
+    this.lastName = form.lastName;
+    this.username = form.email;
+    this.email = form.email;
+    this.password = form.password;
+    this.acceptMessages = form.acceptMessages;
+    this.entreprise = form.entreprise;
+    this.address = form.address;
+    this.zipcode = form.zipcode;
+    this.city = form.city;
+    this.country = form.country;
+  }
+}
+
+export interface IUserInfo {
+  username: string;
+  lastName: string;
+  firstName: string;
+  geosourceId: number;
+  entreprise: string;
+  address: string;
+  city: string;
+  country: string;
+  zipcode: string;
+  acceptMessages: boolean;
+  email: string;
+  consent: boolean;
+}
+
+export class UserInfo {
+  username: string;
+  lastName: string;
+  firstName: string;
+  entreprise: string;
+  address: string;
+  city: string;
+  country: string;
+  zipcode: string;
+  acceptMessages: boolean;
+  email: string;
+
+  constructor(form: IUserInfo) {
+    this.firstName = form.firstName;
+    this.lastName = form.lastName;
+    this.username = form.email;
+    this.email = form.email;
+    this.acceptMessages = form.acceptMessages;
+    this.entreprise = form.entreprise;
+    this.address = form.address;
+    this.zipcode = form.zipcode;
+    this.city = form.city;
+    this.country = form.country;
+  }
+}
+
+export class PasswordUpdateForm {
+  newPassword: string;
+  oldPassword: string;
+
+  constructor(newPassword: string, oldPassword: string) {
+    this.newPassword = newPassword;
+    this.oldPassword = oldPassword;
+  }
+}
+
+export interface IPasswordForgottenForm {
+  email: string;
+}
diff --git a/src/app/user/services/index.ts b/src/app/user/services/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8bade8aea9a865b147bc4a37fc292b782aa4a2f4
--- /dev/null
+++ b/src/app/user/services/index.ts
@@ -0,0 +1,8 @@
+import { UserService } from '../services/user.service';
+
+export { UserService };
+
+// tslint:disable-next-line:variable-name
+export const UserServices = [
+  UserService,
+];
diff --git a/src/app/user/services/user.service.ts b/src/app/user/services/user.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1385b94d5daf2a213f264bad1f9a2e50b972c5e6
--- /dev/null
+++ b/src/app/user/services/user.service.ts
@@ -0,0 +1,126 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable, Subject } from 'rxjs';
+import { IUserInfo, User, ILoginResponse } from '../models';
+import { map, mergeMap, tap } from 'rxjs/operators';
+import * as NodeRSA from 'node-rsa';
+import { APP_CONFIG } from '../../services/app-config.service';
+import { NotificationService } from '../../services';
+import { Router } from '@angular/router';
+
+@Injectable()
+export class UserService {
+
+  private _user: User = null;
+  _userStatusChangedSubject: Subject<boolean>;
+
+  constructor(
+    private _http: HttpClient,
+    private _notificationService: NotificationService,
+  ) {
+    this._userStatusChangedSubject = new Subject<boolean>();
+  }
+
+  initializeService() {
+    this.setUserInfo();
+  }
+
+  // Function and helpers allowing the management of the user session (jwt), info...
+  setSession(authResult): boolean {
+    let success = false;
+    if (authResult && authResult.userInfo && authResult.xsrfToken) {
+      localStorage.setItem('userInfo', JSON.stringify(authResult.userInfo));
+      localStorage.setItem('xsrfToken', authResult.xsrfToken);
+      this.setUserInfo();
+      success = true;
+      this._userStatusChangedSubject.next(true);
+    } else {
+      this.resetAuth();
+    }
+
+    return success;
+  }
+
+  setUserInfo() {
+    const userInfo = JSON.parse(localStorage.getItem('userInfo'));
+    if (userInfo) {
+      this._user = new User(userInfo);
+    }
+  }
+
+  resetAuth() {
+    localStorage.removeItem('userInfo');
+    localStorage.removeItem('xsrfToken');
+    this.logout().subscribe();
+    this._user = null;
+    this._userStatusChangedSubject.next(false);
+  }
+
+  get user() {
+    return this._user;
+  }
+
+  get userIsSignedIn() {
+    return this._user != null;
+  }
+
+  get userStatusChanged$(): Observable<boolean> {
+    return this._userStatusChangedSubject.asObservable();
+  }
+
+  // HTTP Calls
+  login(loginForm): Observable<boolean> {
+    // Make sure not to mofidy the object passed in parameter (object reference) when encrypting the password
+    const form = Object.assign({}, loginForm);
+    return this.getPublicKey().pipe(
+      tap(
+        (publicKey) => {
+          form.password = this.encrypt(form.password, publicKey);
+        },
+      ),
+      mergeMap(() => {
+        return this._http.post<ILoginResponse>(
+          `${APP_CONFIG.authentication.url}login/legacy`,
+          form,
+          { withCredentials: true },
+        );
+      }),
+      map(
+        (res) => {
+          return this.setSession(res);
+        },
+      ),
+    );
+  }
+
+  logout(): Observable<boolean> {
+    return this._http.get<boolean>(`${APP_CONFIG.authentication.url}logout`, { withCredentials: true });
+  }
+
+  getUserInfo(): Observable<IUserInfo> {
+    return this._http.get<IUserInfo>(`${APP_CONFIG.authentication.url}user`, { withCredentials: true });
+  }
+
+  getPublicKey(): Observable<any> {
+    return this._http.get<any>(`${APP_CONFIG.middlewareLegacyAuth.url}publicKey`).pipe(
+      map(
+        (res) => {
+          return res.publicKey;
+        },
+      ),
+    );
+  }
+
+  /**
+   * Takes un unencrypted string as params and returns it encrypted with the public key provided by the backend service
+   */
+  encrypt(unencrypted: string, publicKey: string): string {
+    if (!publicKey) {
+      throw new Error('Can\'t encrypt without public key');
+    } else {
+      const key = new NodeRSA(publicKey);
+      const encrypted = key.encrypt(unencrypted, 'base64');
+      return encrypted;
+    }
+  }
+}
diff --git a/src/app/user/user-routing.module.ts b/src/app/user/user-routing.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f2b714b694423c5c5c0d5938e01c7268416765df
--- /dev/null
+++ b/src/app/user/user-routing.module.ts
@@ -0,0 +1,21 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { LoginComponent } from './components';
+import { UnauthenticatedGuard } from './guards/unauthenticated.guard';
+
+export const routes: Routes = [
+  {
+    path: 'login',
+    component: LoginComponent,
+    canActivate: [UnauthenticatedGuard],
+    data: {
+      title: 'Connexion',
+    },
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class UserRoutingModule { }
diff --git a/src/app/user/user.module.ts b/src/app/user/user.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7ea52171e0bc3c7ccf513cd4abc1aeeb2fd6a9f5
--- /dev/null
+++ b/src/app/user/user.module.ts
@@ -0,0 +1,29 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { UserRoutingModule } from './user-routing.module';
+import { UserServices } from './services';
+import { UserComponents } from './components';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { HTTP_INTERCEPTORS } from '@angular/common/http';
+import { AuthInterceptor } from './interceptors/auth-interceptor';
+import { UserGuards } from './guards';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    UserRoutingModule,
+    FormsModule,
+    ReactiveFormsModule,
+  ],
+  providers: [
+    ...UserGuards,
+    ...UserServices,
+    {
+      provide: HTTP_INTERCEPTORS,
+      useClass: AuthInterceptor,
+      multi: true,
+    },
+  ],
+  declarations: [...UserComponents],
+})
+export class UserModule { }
diff --git a/src/app/user/validators/password.validator.ts b/src/app/user/validators/password.validator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6c0107a3cff3c4edd33755fb7a901a561d7754aa
--- /dev/null
+++ b/src/app/user/validators/password.validator.ts
@@ -0,0 +1,34 @@
+import { AbstractControl } from '@angular/forms';
+
+const passwordBlackList = ['grandlyon', 'smartdata', 'lyon'];
+
+// tslint:disable-next-line:function-name
+export function ValidatePassword(control: AbstractControl) {
+  const errors = {};
+  let res = null;
+  if (!new RegExp(/^[\u0020-\u007e]*$/).test(control.value)) {
+    errors['invalidCharacters'] = true;
+  }
+  if (!new RegExp(/[~`!#$%\$\(@\)\^&*\.+=\-\[\]\\';,/{}|\\":<>\?]/).test(control.value)) {
+    errors['missingSpecialCharacters'] = true;
+  }
+  if (!new RegExp(/[A-Z]/).test(control.value)) {
+    errors['missingUppercasedLetter'] = true;
+  }
+  if (!new RegExp(/[a-z]/).test(control.value)) {
+    errors['missingLowercasedLetter'] = true;
+  }
+  if (!new RegExp(/[0-9]/).test(control.value)) {
+    errors['missingNumber'] = true;
+  }
+  if (new RegExp(passwordBlackList.join('|')).test(control.value)) {
+    errors['forbiddenWord'] = true;
+  }
+
+  if (errors !== {}) {
+    res = errors;
+  }
+
+  return res;
+
+}
diff --git a/src/assets/config/config.json b/src/assets/config/config.json
index 43cecd099741db2447135e4a96bc1d43339ac48c..bd7b9118581dd65b61327035dc36e33dd3805322 100644
--- a/src/assets/config/config.json
+++ b/src/assets/config/config.json
@@ -7,5 +7,11 @@
   },
   "mediaLibrary": {
     "url": "http://localhost:3006/"
+  },
+  "authentication": {
+    "url": "http://localhost:3002/"
+  },
+  "middlewareLegacyAuth": {
+    "url": "http://localhost:3004/"
   }
 }
diff --git a/src/styles.scss b/src/styles.scss
index 40d762110c62519cfb2acd2506d6c3d54a94ca23..bf73b5d1a06258854bb9c4790a85956889795f62 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -6,6 +6,12 @@ $menu-item-active-background-color: #222222;
 
 $tomato-color: #f72f2f;
 $dark-blue: #333745;
+$brand-color: #333744;
+$grey-dark-color: #515151;
+$grey-light-color: #818080;
+$grey-background-color: #F2F2F2;
+$grey-super-light-color: #B4B4B4;
+$link-color: #1D92FF;
 
 $pagination-current-background-color: $tomato-color;
 $pagination-current-border-color: $tomato-color;
@@ -24,32 +30,49 @@ body {
   line-height: 1em;
 }
 
-h1, h2, h3, h4, h5, div, span, p, select, input, ul, tbody {
+h1,
+h2,
+h3,
+h4,
+h5,
+div,
+span,
+p,
+select,
+input,
+ul,
+tbody {
   color: $dark-blue;
 }
 
-h1, .h1 {
+h1,
+.h1 {
   font-size: $size-1;
   line-height: $size-3;
   margin-top: $size-4;
   margin-bottom: $size-4;
 }
 
-h2, .h2 {
+h2,
+.h2 {
   font-size: $size-3;
   line-height: $size-2;
   margin-top: $size-4;
   margin-bottom: $size-4;
 }
 
-h3, .h3 {
+h3,
+.h3 {
   font-size: $size-4;
   line-height: $size-3;
   margin-top: $size-4;
   margin-bottom: $size-4;
 }
 
-h4, .h4, h5, .h5 {
+h4,
+.h4,
+h5,
+.h5 {
   font-size: $size-5;
   line-height: $size-5;
   margin-top: $size-4;
@@ -72,18 +95,22 @@ section {
   color: $tomato-color;
 }
 
-input.ng-invalid:not(form).ng-dirty, input.ng-invalid:not(form).ng-touched,
-textarea.ng-invalid:not(form).ng-dirty, textarea.ng-invalid:not(form).ng-touched {
-  border-left: 3px solid $tomato-color; /* red */
+input.ng-invalid:not(form).ng-dirty,
+input.ng-invalid:not(form).ng-touched,
+textarea.ng-invalid:not(form).ng-dirty,
+textarea.ng-invalid:not(form).ng-touched {
+  border-left: 3px solid $tomato-color;
+  /* red */
 }
 
 .button-gl {
-  min-width: 7rem;
+  min-width: 8rem;
   background: $tomato-color;
   border-radius: 2px;
   border-width: 0;
   font-size: $size-6;
   color: white;
+  text-transform: capitalize;
   line-height: unset;
 
   &:hover,
@@ -93,8 +120,39 @@ textarea.ng-invalid:not(form).ng-dirty, textarea.ng-invalid:not(form).ng-touched
     opacity: 0.92;
   }
 
+  &.is-outlined {
+    border: 1px solid $grey-super-light-color;
+    color: $grey-light-color;
+    background: transparent;
+
+    &:hover,
+    &:focus {
+      border-color: $tomato-color;
+      box-shadow: none;
+    }
+
+    &:disabled {
+      color: $grey-light-color;
+      background-color: transparent;
+      opacity: 0.38;
+      border-color: $grey-super-light-color;
+    }
+  }
+
   &:disabled {
     background: $tomato-color;
     opacity: 0.38;
   }
-}
\ No newline at end of file
+
+  &.is-flat {
+    background: transparent;
+    color: $brand-color;
+    font-weight: bold;
+
+    &:hover,
+    &:focus {
+      box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.16);
+      background-color: #e8ecef;
+    }
+  }
+}