// ========================================================================
//
// Copyright (C) 2017-2018 MARC CHEVALDONNE
// marc.chevaldonne.free.fr
//
// Module : TokenController.cs
// Author : Marc Chevaldonné
// Creation date : 2018-02-12
//
// ========================================================================
using AlertWebAPI.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
namespace AlertWebAPI.Controllers
{
///
/// allows to create a token on the alert database by authenticating
///
[Route("api/token")]
public class TokenController : Controller
{
private IConfiguration _config;
///
/// context allowing to access the database containing the logins and passwords
///
private readonly UserDbContext context;
///
/// constructor
///
///
public TokenController(IConfiguration config)
{
_config = config;
//creates the context to the Users database
this.context = new UserDbContext();
//if the users database is empty, creates a fake user and adds it to the database
StubData();
}
[Conditional("DEBUG")]
private void StubData()
{
if (context.Users.Count() == 0)
{
InitializeData(context);
context.SaveChanges();
}
}
///
/// creates stub data for the users database
///
///
private void InitializeData(UserDbContext context)
{
context.Users.Add(new User
{
Name = "Dwight Schrute",
UserName = "dwight",
Password = "boss",
Email = "dwight.schrute@dundlermifflin.com"
});
}
///
/// creates a token for accessing the alert database
/// [AllowAnonymous] authorizes anonymous access to this method
///
/// username/password of the user asking for a token
/// a token to access the alert database
[AllowAnonymous]
[HttpPost]
public IActionResult CreateToken([FromBody]Login login)
{
IActionResult response = Unauthorized();
//tries to authenticate with the login data
var user = Authenticate(login);
//if authentication succeeds, builds a token and returns it
if (user != null)
{
var tokenString = BuildToken(user);
response = Ok(new { token = tokenString });
}
//else, returns a Status401Unauthorized response
return response;
}
///
/// builds the token with the user data
/// note that it uses the config file (Key and Issuer), defined in appsettings.json
///
/// the user who will get the token
/// the token built
private string BuildToken(User user)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(_config["Jwt:Issuer"],
_config["Jwt:Issuer"],
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
///
/// authenticates the login/password
///
/// login/password to authenticate
/// the user if authentication succeeds, null if not
private User Authenticate(Login login)
{
User user = null;
//retrieves the first user in the database with the given login and password
user = context.Users.FirstOrDefault(u => u.UserName == login.Username && u.Password == login.Password);
//methods without users database and hard-saved login/password
//if (login.Username == "dwight" && login.Password == "boss")
//{
// user = new User { Name = "Dwight Schrute", Email = "dwight.schrute@dundlermifflin.com" };
//}
return user;
}
}
}