using System; using System.Security.Claims; using System.Threading.Tasks; using Abp.Dependency; using Abp.Localization; using Abp.Localization.Sources; using WeOnlineApp.Authorization; using WeOnlineApp.Authorization.Users; using WeOnlineApp.MultiTenancy; using IwbZero; using IwbZero.Authorization.Base; using IwbZero.Authorization.Users; using Microsoft.Owin.Security; using Microsoft.Owin.Security.OAuth; namespace WeOnlineApp.Api.Providers { public class IwbAuthorizationServerProvider : OAuthAuthorizationServerProvider, ITransientDependency { private LogInManager LogInManager { get; } private ILocalizationManager LocalizationManager { get; } public IwbAuthorizationServerProvider(LogInManager logInManager) { LogInManager = logInManager; LocalizationManager = NullLocalizationManager.Instance; } public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { if (!context.TryGetBasicCredentials(out var clientId, out var clientSecret)) { context.TryGetFormCredentials(out clientId, out clientSecret); } var isValidClient = string.CompareOrdinal(clientId, "app") == 0 && string.CompareOrdinal(clientSecret, "app") == 0; if (isValidClient) { context.OwinContext.Set("as:client_id", clientId); context.Validated(clientId); } else { context.SetError("invalid client"); } return Task.FromResult(null); } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { var tenantId = context.Request.Query["tenantId"]; var result = await GetLoginResultAsync(context, context.UserName, context.Password, tenantId); if (result.Result == IwbLoginResultType.Success) { //var claimsIdentity = result.Identity; var claimsIdentity = new ClaimsIdentity(result.Identity); claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); var ticket = new AuthenticationTicket(claimsIdentity, new AuthenticationProperties()); context.Validated(ticket); } } public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context) { var originalClient = context.OwinContext.Get("as:client_id"); var currentClient = context.ClientId; // enforce client binding of refresh token if (originalClient != currentClient) { context.Rejected(); return Task.FromResult(null); } // chance to change authentication ticket for refresh token requests var newId = new ClaimsIdentity(context.Ticket.Identity); newId.AddClaim(new Claim("newClaim", "refreshToken")); var newTicket = new AuthenticationTicket(newId, context.Ticket.Properties); context.Validated(newTicket); return Task.FromResult(null); } private async Task> GetLoginResultAsync(OAuthGrantResourceOwnerCredentialsContext context, string usernameOrEmailAddress, string password, string tenancyName) { var loginResult = await LogInManager.LoginAsync(usernameOrEmailAddress, password, tenancyName); switch (loginResult.Result) { case IwbLoginResultType.Success: return loginResult; default: CreateExceptionForFailedLoginAttempt(context, loginResult.Result, usernameOrEmailAddress, tenancyName); //throw CreateExceptionForFailedLoginAttempt(context,loginResult.Result, usernameOrEmailAddress, tenancyName); return loginResult; } } private void CreateExceptionForFailedLoginAttempt(OAuthGrantResourceOwnerCredentialsContext context, IwbLoginResultType result, string usernameOrEmailAddress, string tenancyName) { switch (result) { case IwbLoginResultType.Success: throw new ApplicationException("Don't call this method with a success result!"); case IwbLoginResultType.InvalidUserNameOrEmailAddress: case IwbLoginResultType.InvalidPassword: context.SetError(L("LoginFailed"), L("InvalidUserNameOrPassword")); break; // return new UserFriendlyException(("LoginFailed"), ("InvalidUserNameOrPassword")); case IwbLoginResultType.InvalidTenancyName: context.SetError(L("LoginFailed"), L("ThereIsNoTenantDefinedWithName", tenancyName)); break; // return new UserFriendlyException(("LoginFailed"), string.Format("ThereIsNoTenantDefinedWithName{0}", tenancyName)); case IwbLoginResultType.TenantIsNotActive: context.SetError(L("LoginFailed"), L("TenantIsNotActive", tenancyName)); break; // return new UserFriendlyException(("LoginFailed"), string.Format("TenantIsNotActive {0}", tenancyName)); case IwbLoginResultType.UserIsNotActive: context.SetError(L("LoginFailed"), L("UserIsNotActiveAndCanNotLogin", usernameOrEmailAddress)); break; // return new UserFriendlyException(("LoginFailed"), string.Format("UserIsNotActiveAndCanNotLogin {0}", usernameOrEmailAddress)); case IwbLoginResultType.UserEmailIsNotConfirmed: context.SetError(L("LoginFailed"), L("UserEmailIsNotConfirmedAndCanNotLogin")); break; // return new UserFriendlyException(("LoginFailed"), ("UserEmailIsNotConfirmedAndCanNotLogin")); //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(("LoginFailed")); } } private string L(string name, params object[] args) { //return new LocalizedString(name); return LocalizationManager.GetSource(IwbZeroConsts.LocalizationSourceName).GetString(name, args); } } }