using System; using System.Threading.Tasks; using Microsoft.Owin.Security.OAuth; using Step.Database.Controllers; using Step.Model.DatabaseModels; using System.Security.Claims; using static Step.Model.Constants; using static Step.Config.ServerConfig; using System.Linq; using Microsoft.Owin.Security; using Step.CmsConnectManager; using MConnectSDK; namespace Step.Provider { public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider { public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { // Validate client context.Validated(); } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { using (UsersController usersController = new UsersController()) { try { UserModel user = usersController.FindByUsername(context.UserName); // If not exists if (user == null) { // Return 401 context.SetError("invalid_grant", "The user name or password is incorrect."); return; } if(user.IsLocal && !user.Deleted) { // Check if credentials are correct user = usersController.FindByUsernameAndPassword(context.UserName, context.Password); // If not exists if (user == null) { // Return 401 context.SetError("invalid_grant", "The user name or password is incorrect."); return; } } else { MConnectSDKWrapper _sdk = new MConnectSDKWrapper(); UserData connectUser = await _sdk.TryUserLogin(user.Username, context.Password); if(connectUser == null) { // Return 401 context.SetError("invalid_grant", "The user name or password is incorrect."); return; } } // Create a new Identity and insert custom claims var identity = new ClaimsIdentity(context.Options.AuthenticationType); // Add claims to token identity.AddClaim(new Claim(USER_ID_KEY, user.UserId.ToString())); using (MachinesUsersController machinesUsersController = new MachinesUsersController()) { // Check if user can access to the machine MachineUserModel machineUser = machinesUsersController.FindByUserId(MachineConfig.MachineId, user.UserId); if (machineUser == null) { // Return 401 bad request context.SetError("invalid_grant", "User has no access to this machine"); return; } // Add machine id identity.AddClaim(new Claim(MACHINE_ID_KEY, machineUser.MachineId.ToString())); } var tiket = new AuthenticationTicket(identity, null); tiket.Properties.IsPersistent = true; // Create Token with identity data context.Validated(tiket); RedisController.WriteCurrentUser(user.UserId); await base.GrantResourceOwnerCredentials(context); return; } catch (Exception ex) { // Return 401 bad request context.SetError("invalid_grant", ex.Message); return; } } } public override Task TokenEndpointResponse(OAuthTokenEndpointResponseContext context) { // Find userId and machineId from Claims var userId = context.Identity.Claims.FirstOrDefault(c => c.Type == USER_ID_KEY); var machineId = context.Identity.Claims.FirstOrDefault(c => c.Type == MACHINE_ID_KEY); using(MachinesUsersController machinesUsersController = new MachinesUsersController()) { // Find machineUser Id from database by machineId and userId MachineUserModel machineUser = machinesUsersController.FindByUserId(Convert.ToInt32(machineId.Value), Convert.ToInt32(userId.Value)); using (SessionsController sessionsController = new SessionsController()) { // Create new user session sessionsController.Create(machineUser.MachineUserId, context.AccessToken); } } return base.TokenEndpointResponse(context); } } }