mysimulation/server/FSO.Server.Api.Core/Controllers/UserOAuthController.cs
Tony Bark 22191ce648 Removed NioTSO client and server
- NioTSO client isn't needed because we're using RayLib
- Added FreeSO's API server to handle most backend operations
2024-05-01 02:55:43 -04:00

122 lines
No EOL
5.1 KiB
C#
Executable file

using FSO.Server.Api.Core.Utils;
using FSO.Server.Common;
using FSO.Server.Servers.Api.JsonWebToken;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
namespace FSO.Server.Api.Core.Controllers
{
[Route("userapi/oauth/token")]
[ApiController]
public class UserOAuthController : ControllerBase
{
[HttpPost]
public IActionResult CreateToken([FromForm] UserOAuthRequest userAuthRequest)
{
if (userAuthRequest == null) BadRequest();
var api = Api.INSTANCE;
using (var da = api.DAFactory.Get())
{
var user = da.Users.GetByUsername(userAuthRequest.username);
if (user == null || user.is_banned) return ApiResponse.Json(System.Net.HttpStatusCode.Unauthorized, new UserOAuthError("unauthorized_client", "user_credentials_invalid"));
var ip = ApiUtils.GetIP(Request);
var hashSettings = da.Users.GetAuthenticationSettings(user.user_id);
var isPasswordCorrect = PasswordHasher.Verify(userAuthRequest.password, new PasswordHash
{
data = hashSettings.data,
scheme = hashSettings.scheme_class
});
//check if account is locked due to failed attempts
var accLock = da.Users.GetRemainingAuth(user.user_id, ip);
if (accLock != null && (accLock.active || accLock.count >= AuthLoginController.LockAttempts) && accLock.expire_time > Epoch.Now)
{
return ApiResponse.Json(System.Net.HttpStatusCode.OK, new UserOAuthError("unauthorized_client", "account_locked"));
}
//if the password is incorrect and check if user failed muli times and set a time out till next try.
if (!isPasswordCorrect)
{
var durations = AuthLoginController.LockDuration;
var failDelay = 60 * durations[Math.Min(durations.Length - 1, da.Users.FailedConsecutive(user.user_id, ip))];
if (accLock == null)
{
da.Users.NewFailedAuth(user.user_id, ip, (uint)failDelay);
}
else
{
var remaining = da.Users.FailedAuth(accLock.attempt_id, (uint)failDelay, AuthLoginController.LockAttempts);
}
return ApiResponse.Json(System.Net.HttpStatusCode.OK, new UserOAuthError("unauthorized_client", "user_credentials_invalid"));
}
//user passed the password check, and now creates the claim/token
da.Users.SuccessfulAuth(user.user_id, ip);
var claims = new List<string>();
//set the permission level in the claim
switch (userAuthRequest.permission_level)
{
case 1:
claims.Add("userReadPermissions");
break;
case 2:
claims.Add("userReadPermissions");
claims.Add("userWritePermissions");
break;
case 3:
claims.Add("userReadPermissions");
claims.Add("userWritePermissions");
claims.Add("userUpdatePermissions");
break;
case 4:
claims.Add("userReadPermissions");
claims.Add("userWritePermissions");
claims.Add("userUpdatePermissions");
claims.Add("userDeletePermissions");
break;
default:
break;
}
//set the user identity
JWTUser identity = new JWTUser
{
UserID = user.user_id,
UserName = user.username,
Claims = claims
};
//generate the the tokenen and send it in a JSON format as response
var generatedToken = api.JWT.CreateToken(identity);
return ApiResponse.Json(System.Net.HttpStatusCode.OK, new UserOAuthSuccess
{
access_token = generatedToken.Token,
expires_in = generatedToken.ExpiresIn
});
}
}
}
public class UserOAuthRequest
{
public int permission_level { get; set; }
public string username { get; set; }
public string password { get; set; }
}
public class UserOAuthError
{
public string error;
public string error_description;
public UserOAuthError(string errorString,string errorDescriptionString)
{
error = errorString;
error_description = errorDescriptionString;
}
}
public class UserOAuthSuccess
{
public string access_token { get; set; }
public int expires_in { get; set; }
}
}