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(); //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; } } }