using System; using System.Threading.Tasks; using System.Web.Http; using Abp.UI; using Abp.Web.Models; using Abp.WebApi.Controllers; using WePlatform.Api.Models; using WePlatform.Authorization; using WePlatform.Authorization.Users; using WePlatform.MultiTenancy; using IwbZero; using IwbZero.Authorization.Base; using IwbZero.Authorization.Users; using Microsoft.Extensions.Internal; using Microsoft.Owin.Security; using Microsoft.Owin.Security.OAuth; namespace WePlatform.Api.Controllers { public class AccountController : AbpApiController { public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; } private readonly LogInManager _logInManager; static AccountController() { OAuthBearerOptions = new OAuthBearerAuthenticationOptions(); } public AccountController(LogInManager logInManager) { _logInManager = logInManager; LocalizationSourceName = IwbZeroConsts.LocalizationSourceName; } [HttpPost] public async Task Authenticate(LoginModel loginModel) { CheckModelState(); var loginResult = await GetLoginResultAsync( loginModel.UsernameOrEmailAddress, loginModel.Password, loginModel.TenancyName ); var ticket = new AuthenticationTicket(loginResult.Identity, new AuthenticationProperties()); var currentUtc = new SystemClock().UtcNow; ticket.Properties.IssuedUtc = currentUtc; ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30)); return new AjaxResponse(OAuthBearerOptions.AccessTokenFormat.Protect(ticket)); } private async Task> GetLoginResultAsync(string usernameOrEmailAddress, string password, string tenancyName) { var loginResult = await _logInManager.LoginAsync(usernameOrEmailAddress, password, tenancyName); switch (loginResult.Result) { case IwbLoginResultType.Success: return loginResult; default: throw CreateExceptionForFailedLoginAttempt(loginResult.Result, usernameOrEmailAddress, tenancyName); } } private Exception CreateExceptionForFailedLoginAttempt(IwbLoginResultType result, string usernameOrEmailAddress, string tenancyName) { switch (result) { case IwbLoginResultType.Success: return new ApplicationException("Don't call this method with a success result!"); case IwbLoginResultType.InvalidUserNameOrEmailAddress: case IwbLoginResultType.InvalidPassword: return new UserFriendlyException(L("LoginFailed"), L("InvalidUserNameOrPassword")); case IwbLoginResultType.InvalidTenancyName: return new UserFriendlyException(L("LoginFailed"), L("ThereIsNoTenantDefinedWithName{0}", tenancyName)); case IwbLoginResultType.TenantIsNotActive: return new UserFriendlyException(L("LoginFailed"), L("TenantIsNotActive", tenancyName)); case IwbLoginResultType.UserIsNotActive: return new UserFriendlyException(L("LoginFailed"), L("UserIsNotActiveAndCanNotLogin", usernameOrEmailAddress)); case IwbLoginResultType.UserEmailIsNotConfirmed: return new UserFriendlyException(L("LoginFailed"), "Your email address is not confirmed. You can not login"); //TODO: localize message default: //Can not fall to default actually. But other result types can be added in the future and we may forget to handle it Logger.Warn("Unhandled login fail reason: " + result); return new UserFriendlyException(L("LoginFailed")); } } protected virtual void CheckModelState() { if (!ModelState.IsValid) { throw new UserFriendlyException("Invalid request!"); } } } }