diff --git a/src/mailer/mail-templates/verify.ejs b/src/mailer/mail-templates/verify.ejs
index e384dae43ff76ded6f735fe586b80598c6f8fb14..2782ec1376354879a3875a0ebf3bc8e5352fe4ad 100644
--- a/src/mailer/mail-templates/verify.ejs
+++ b/src/mailer/mail-templates/verify.ejs
@@ -2,7 +2,7 @@ Bonjour<br />
 <br />
 Afin de pouvoir vous connecter sur la plateforme, merci de cliquer sur
 <a
-  href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/users/verify/<%= token %>"
+  href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/users/verify/<%= userId %>?token=<%= token %>"
   >ce lien</a
 >
 afin de valider votre inscription<br />
diff --git a/src/users/user.interface.ts b/src/users/user.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0fe05c6f856caafb64c23ff4dfbaaa778d6b5773
--- /dev/null
+++ b/src/users/user.interface.ts
@@ -0,0 +1,10 @@
+import { Document } from 'mongoose';
+
+export interface IUser extends Document {
+  readonly _id: string;
+  email: string;
+  password: string;
+  emailVerified: boolean;
+  validationToken: string;
+  role: number;
+}
diff --git a/src/users/user.schema.ts b/src/users/user.schema.ts
index daa58ed0c7f9123ad1b04af3cf8ad9f475bf9f1a..abb11e91aaac1bac06d07ab6c513567b89a6791c 100644
--- a/src/users/user.schema.ts
+++ b/src/users/user.schema.ts
@@ -1,9 +1,5 @@
 import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
-import { Document } from 'mongoose';
 import { UserRole } from './enum/user-role.enum';
-
-export type UserDocument = User & Document;
-
 @Schema()
 export class User {
   @Prop({ required: true })
diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts
index d7ebf5198487b29ebd157508033cbf2ee4cf508f..8d80697be368cc3c180d8a1c6894c2e1be5d9353 100644
--- a/src/users/users.controller.ts
+++ b/src/users/users.controller.ts
@@ -1,4 +1,5 @@
-import { Body, Controller, Get, Post, Request, UseGuards } from '@nestjs/common';
+import { Body, Controller, Get, Param, Post, Query, Req, Request, UseGuards } from '@nestjs/common';
+import { ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger';
 import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
 import { CreateUserDto } from './create-user.dto';
 import { UsersService } from './users.service';
@@ -8,13 +9,25 @@ export class UsersController {
   constructor(private usersService: UsersService) {}
 
   @UseGuards(JwtAuthGuard)
+  @ApiOperation({ description: 'Get user profile' })
+  @ApiResponse({ status: 200, description: 'Return user profil' })
+  @ApiResponse({ status: 401, description: 'User does not have sufficient rights' })
   @Get('profile')
   public getProfile(@Request() req) {
     return req.user;
   }
 
   @Post()
+  @ApiResponse({ status: 201, description: 'User created' })
   public async create(@Body() createUserDto: CreateUserDto) {
     return this.usersService.create(createUserDto);
   }
+
+  @Post('verify/:id')
+  @ApiParam({ name: 'id', type: String, required: true })
+  @ApiResponse({ status: 201, description: 'User verified' })
+  @ApiResponse({ status: 401, description: "This token does'nt exist or is not associate to this user." })
+  public async validateUser(@Param() params, @Query('token') token: string) {
+    return this.usersService.validateUser(params.id, token);
+  }
 }
diff --git a/src/users/users.service.ts b/src/users/users.service.ts
index c2f9e59ae4f494f107318700842abb9da111222f..4ea11e51fc03c9026ee7712013df0ae79bc06a11 100644
--- a/src/users/users.service.ts
+++ b/src/users/users.service.ts
@@ -6,13 +6,18 @@ import * as crypto from 'crypto';
 import { Model } from 'mongoose';
 import { LoginDto } from '../auth/login-dto';
 import { CreateUserDto } from './create-user.dto';
-import { User, UserDocument } from './user.schema';
+import { User } from './user.schema';
 import { MailerService } from '../mailer/mailer.service';
+import { IUser } from './user.interface';
 
 @Injectable()
 export class UsersService {
-  constructor(@InjectModel(User.name) private userModel: Model<UserDocument>, private mailerService: MailerService) {}
+  constructor(@InjectModel(User.name) private userModel: Model<IUser>, private mailerService: MailerService) {}
 
+  /**
+   * Create a user account
+   * @param createUserDto CreateUserDto
+   */
   public async create(createUserDto: CreateUserDto): Promise<User> {
     const userInDb = await this.findOne(createUserDto.email);
     if (userInDb) {
@@ -54,13 +59,22 @@ export class UsersService {
     return await bcrypt.hash(password, process.env.SALT);
   }
 
-  public async findOne(mail: string, passwordQuery?: boolean): Promise<User | undefined> {
+  public async findOne(mail: string, passwordQuery?: boolean): Promise<IUser | undefined> {
     if (passwordQuery) {
       return this.userModel.findOne({ email: mail }).exec();
     }
     return this.userModel.findOne({ email: mail }).select('-password').exec();
   }
 
+  public async findById(id: string): Promise<IUser | undefined> {
+    return this.userModel.findById(id).select('-password').exec();
+  }
+
+  /**
+   * Return a user after credential checking.
+   * Use for login action
+   * @param param LoginDto
+   */
   public async findByLogin({ email, password }: LoginDto): Promise<User> {
     const user = await this.findOne(email, true);
 
@@ -83,16 +97,16 @@ export class UsersService {
    * a new account.
    * @param user User
    */
-  private async verifyUserMail(user: User): Promise<any> {
+  private async verifyUserMail(user: IUser): Promise<any> {
     const config = this.mailerService.config;
     const ejsPath = this.mailerService.getTemplateLocation(config.templates.verify.ejs);
     const jsonConfig = this.mailerService.loadJsonConfig(config.templates.verify.json);
 
     const token = crypto.randomBytes(64).toString('hex');
-
     const html = await ejs.renderFile(ejsPath, {
       config,
       token: token,
+      userId: user._id,
     });
     this.mailerService.send(user.email, jsonConfig.subject, html);
 
@@ -100,4 +114,20 @@ export class UsersService {
     user.validationToken = token;
     return user;
   }
+
+  /**
+   * Check that the given token is associated to userId. If it's true, validate user account.
+   * @param userId string
+   * @param token string
+   */
+  public async validateUser(userId: string, token: string): Promise<any> {
+    const user = await this.findById(userId);
+    if (user && user.validationToken === token) {
+      user.validationToken = null;
+      user.emailVerified = true;
+      user.save();
+    } else {
+      throw new HttpException('Invalid token', HttpStatus.UNAUTHORIZED);
+    }
+  }
 }