You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mchsamples-.net-core/AlertSoftwareKit/AlertWebAPI/Controllers/TokenController.cs

144 lines
4.9 KiB

// ========================================================================
//
// 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
{
/// <summary>
/// allows to create a token on the alert database by authenticating
/// </summary>
[Route("api/token")]
public class TokenController : Controller
{
private IConfiguration _config;
/// <summary>
/// context allowing to access the database containing the logins and passwords
/// </summary>
private readonly UserDbContext context;
/// <summary>
/// constructor
/// </summary>
/// <param name="config"></param>
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();
}
}
/// <summary>
/// creates stub data for the users database
/// </summary>
/// <param name="context"></param>
private void InitializeData(UserDbContext context)
{
context.Users.Add(new User
{
Name = "Dwight Schrute",
UserName = "dwight",
Password = "boss",
Email = "dwight.schrute@dundlermifflin.com"
});
}
/// <summary>
/// creates a token for accessing the alert database
/// [AllowAnonymous] authorizes anonymous access to this method
/// </summary>
/// <param name="login">username/password of the user asking for a token</param>
/// <returns>a token to access the alert database</returns>
[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;
}
/// <summary>
/// builds the token with the user data
/// note that it uses the config file (Key and Issuer), defined in appsettings.json
/// </summary>
/// <param name="user">the user who will get the token</param>
/// <returns>the token built</returns>
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);
}
/// <summary>
/// authenticates the login/password
/// </summary>
/// <param name="login">login/password to authenticate</param>
/// <returns>the user if authentication succeeds, null if not</returns>
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;
}
}
}