mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-07-23 21:51:29 +00:00
token authentication
This commit is contained in:
parent
dc2c93647f
commit
05e4d513ea
5 changed files with 76 additions and 15 deletions
|
@ -1,6 +1,7 @@
|
|||
#nullable enable
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using ProjectLighthouse.Types;
|
||||
|
||||
|
@ -15,19 +16,27 @@ namespace ProjectLighthouse.Controllers {
|
|||
if(!this.Request.Query.TryGetValue("titleID", out StringValues _))
|
||||
return this.BadRequest("");
|
||||
|
||||
// FIXME: this will not do, MM_AUTH is created by the client after POST /LOGIN
|
||||
if(!this.Request.Cookies.TryGetValue("MM_AUTH", out string? mmAuth) || mmAuth == null)
|
||||
return this.BadRequest(""); // TODO: send 403
|
||||
|
||||
await using Database database = new();
|
||||
|
||||
Token? token;
|
||||
|
||||
// ReSharper disable once InvertIf
|
||||
if(!await database.IsUserAuthenticated(mmAuth)) {
|
||||
if(!await database.AuthenticateUser(mmAuth)) return this.BadRequest(""); // TODO: send 403
|
||||
token = await database.AuthenticateUser(mmAuth);
|
||||
}
|
||||
else {
|
||||
token = await database.Tokens.FirstOrDefaultAsync(t => t.UserToken == mmAuth);
|
||||
}
|
||||
|
||||
if(token == null) return this.BadRequest(""); // TODO: send 403
|
||||
|
||||
return this.Ok(new LoginResult {
|
||||
AuthTicket = "d2c6bbec59162a1e786ed24ad95f2b73",
|
||||
LbpEnvVer = "ProjectLighthouse"
|
||||
AuthTicket = token.UserToken,
|
||||
LbpEnvVer = ServerSettings.ServerName
|
||||
}.Serialize());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,28 +38,30 @@ namespace ProjectLighthouse {
|
|||
|
||||
// MM_AUTH=psn_name:?:timestamp, potentially a user creation date?:?:user id?:user's IP:?:password? SHA1
|
||||
// just blindly trust the token for now while we get it working
|
||||
public async Task<bool> AuthenticateUser(string mmAuth) {
|
||||
if(!mmAuth.Contains(':')) return false;
|
||||
public async Task<Token?> AuthenticateUser(string loginString) {
|
||||
if(!loginString.Contains(':')) return null;
|
||||
|
||||
Token token = new() {
|
||||
UserToken = mmAuth
|
||||
};
|
||||
|
||||
string[] split = mmAuth.Split(":");
|
||||
string[] split = loginString.Split(":");
|
||||
|
||||
// TODO: don't use psn name to authenticate
|
||||
User user = await this.Users.FirstOrDefaultAsync(u => u.Username == split[0])
|
||||
?? await this.CreateUser(split[0]);
|
||||
|
||||
token.UserId = user.UserId;
|
||||
Token token = new() {
|
||||
UserToken = HashHelper.GenerateAuthToken(),
|
||||
UserId = user.UserId
|
||||
};
|
||||
|
||||
return true;
|
||||
this.Tokens.Add(token);
|
||||
await this.SaveChangesAsync();
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
public async Task<bool> IsUserAuthenticated(string mmAuth) => await UserFromMMAuth(mmAuth) != null;
|
||||
public async Task<bool> IsUserAuthenticated(string authToken) => await this.UserFromAuthToken(authToken) != null;
|
||||
|
||||
public async Task<User?> UserFromMMAuth(string mmAuth) {
|
||||
Token? token = await Tokens.FirstOrDefaultAsync(t => t.UserToken == mmAuth);
|
||||
public async Task<User?> UserFromAuthToken(string authToken) {
|
||||
Token? token = await Tokens.FirstOrDefaultAsync(t => t.UserToken == authToken);
|
||||
if(token == null) return null;
|
||||
return await Users.FirstOrDefaultAsync(u => u.UserId == token.UserId);
|
||||
}
|
||||
|
|
47
ProjectLighthouse/HashHelper.cs
Normal file
47
ProjectLighthouse/HashHelper.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace ProjectLighthouse {
|
||||
public static class HashHelper {
|
||||
// private static readonly SHA1 sha1 = SHA1.Create();
|
||||
private static readonly SHA256 sha256 = SHA256.Create();
|
||||
private static readonly Random random = new();
|
||||
|
||||
#region Hash Functions
|
||||
public static string Sha256Hash(string str) => Sha256Hash(Encoding.UTF8.GetBytes(str));
|
||||
|
||||
public static string Sha256Hash(byte[] bytes) {
|
||||
byte[] hash = sha256.ComputeHash(bytes);
|
||||
return Encoding.UTF8.GetString(hash, 0, hash.Length);
|
||||
}
|
||||
|
||||
public static string BCryptHash(string str) => BCrypt.Net.BCrypt.HashPassword(str);
|
||||
|
||||
public static string BCryptHash(byte[] bytes) => BCrypt.Net.BCrypt.HashPassword(Encoding.UTF8.GetString(bytes));
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Generates a specified amount of random bytes in an array.
|
||||
/// </summary>
|
||||
/// <param name="count">The amount of bytes to generate.</param>
|
||||
/// <returns>The bytes generated</returns>
|
||||
public static IEnumerable<byte> GenerateRandomBytes(int count) {
|
||||
byte[] b = new byte[count];
|
||||
random.NextBytes(b);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a random SHA256 & BCrypted token
|
||||
/// </summary>
|
||||
/// <returns>The token as a string.</returns>
|
||||
public static string GenerateAuthToken() {
|
||||
byte[] bytes = (byte[]) GenerateRandomBytes(256);
|
||||
|
||||
return BCryptHash(Sha256Hash(bytes));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.10" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.2" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
||||
|
|
|
@ -10,6 +10,8 @@ namespace ProjectLighthouse.Types {
|
|||
|
||||
public const int ListsQuota = 20;
|
||||
|
||||
public const string ServerName = "ProjectLighthouse";
|
||||
|
||||
private static string? dbConnectionString;
|
||||
public static string DbConnectionString {
|
||||
get {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue