-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathAuthController.cs
144 lines (121 loc) · 4.84 KB
/
AuthController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using net5_webapi.Engines;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace net5_webapi.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly IConfiguration config;
private readonly IDBEngine db;
private readonly ICryptoEngine crypto;
public AuthController(IConfiguration Configuration, IDBEngine DBEngine, ICryptoEngine CryptoEngine)
{
config = Configuration;
db = DBEngine;
crypto = CryptoEngine;
}
public class LoginBody
{
[Required]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
/// <summary>
/// Login with username and password. No previous authorization required.
/// </summary>
[HttpPost]
public async Task<ActionResult> Login([FromBody] LoginBody body)
{
string username = body.Username.ToLower();
string hash = await db.Value<string>("SELECT hash FROM User WHERE LOWER(username)=@username", new { username });
if (!string.IsNullOrEmpty(hash) && crypto.HashCheck(hash, body.Password))
{
JObject session = await LoadSession(username);
session["token"] = GenerateJwtToken(session);
return Ok(session);
}
return Unauthorized("error.credentials");
}
public class RegisterBody
{
[Required]
public string Username { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
public string Name { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
/// <summary>
/// Register with username, email, name and password. No previous authorization required.
/// </summary>
[HttpPost]
public async Task<ActionResult> Register([FromBody] RegisterBody body)
{
string username = body.Username.ToLower();
string email = body.Email.ToLower();
if (await db.Value<int>("SELECT COUNT(*) FROM User WHERE LOWER(username)=@username OR LOWER(email)=@email", new { username, email }) > 0)
return Unauthorized("error.unavailable");
await db.Execute("INSERT INTO User (username, hash, email) VALUES (@username, @hash, @email)", new { username, hash = crypto.Hash(body.Password), email });
return Ok();
}
/// <summary>
/// Returns the session data for this user.
/// </summary>
[Authorize]
[HttpGet]
public async Task<ActionResult> Session()
{
return Ok(await LoadSession());
}
private async Task<JObject> LoadSession(string username = "")
{
if (username == "")
username = User.FindFirstValue(JwtRegisteredClaimNames.Sub);
return await db.Json("SELECT id, username, email FROM User WHERE LOWER(username)=@username", new { username = username.ToLower() });
}
private string GenerateJwtToken(JObject session)
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, session["username"].ToString()),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.NameIdentifier, session["id"].ToString())
};
dynamic JwtConfig = new
{
Issuer = config.GetSection("JWT:Issuer").Value,
Key = config.GetSection("JWT:Key").Value,
ExpireMinutes = config.GetSection("JWT:ExpireMinutes").Value
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtConfig.Key));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var expires = DateTime.Now.AddMinutes(Convert.ToDouble(JwtConfig.ExpireMinutes));
var token = new JwtSecurityToken(
JwtConfig.Issuer,
JwtConfig.Issuer,
claims,
expires: expires,
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
}