Browse Source

#13713 - Agent Self Login

master
binita 1 year ago
parent
commit
07bae8ff1d
  1. 68
      API/GoogleAuthenticatorAPI.cs
  2. 170
      API/Model/EncryptDecryptUtility.cs
  3. 15
      API/Model/GoogleAuthenticatorModel.cs
  4. 6
      Business/Account/AccountServices.cs
  5. 3
      Business/Account/IAccountServices.cs
  6. 8
      JMEAgentSystem/Scripts/Account/Login.js
  7. 2
      JMEAgentSystem/Scripts/Customer/CustomerRegistration.js
  8. 137
      JMEAgentSystem/WebPages/Account/Authenticate.aspx
  9. 64
      JMEAgentSystem/WebPages/Account/Authenticate.aspx.cs
  10. 80
      JMEAgentSystem/WebPages/Account/Authenticate.aspx.designer.cs
  11. 13
      JMEAgentSystem/WebPages/Account/Login.aspx.cs
  12. 9
      JMEAgentSystem/WebPages/CustomerRegistration/Manage.aspx
  13. 10
      Repository/DAO/Account/AccountRepo.cs
  14. 1
      Repository/DAO/Account/IAccountRepo.cs

68
API/GoogleAuthenticatorAPI.cs

@ -0,0 +1,68 @@
using API.Model;
using Common.Utility;
using Google.Authenticator;
using System.Configuration;
using System.Web;
namespace API
{
public class GoogleAuthenticatorAPI
{
protected TwoFactorAuthenticator _tfa = new TwoFactorAuthenticator();
protected string _key = ReadWebConfig("2FAGoogle", "");
protected string _keyForEncDec = ReadWebConfig("keyForEncryptionDecryption", "");
public GoogleAuthenticatorModel GenerateCodeAndImageURL(string userName)
{
GoogleAuthenticatorModel _model = new GoogleAuthenticatorModel();
string userUniqueKeyEncrypted = EncryptDecryptUtility.Encrypt(userName + _key, _keyForEncDec);
WriteSession("UserUniqueKey", userUniqueKeyEncrypted);
var _googleSetupInfo = _tfa.GenerateSetupCode("JME REMIT", userName, userUniqueKeyEncrypted, 200, 200, true);
_model.SetupCode = _googleSetupInfo.ManualEntryKey;
_model.BarCodeImageUrl = _googleSetupInfo.QrCodeSetupImageUrl;
return _model;
}
public GoogleAuthenticatorModel GenerateCodeAndImageURL(string userName, string userUniqueKeyEncrypted)
{
GoogleAuthenticatorModel _model = new GoogleAuthenticatorModel();
var _googleSetupInfo = _tfa.GenerateSetupCode("JME REMIT", userName, userUniqueKeyEncrypted, 200, 200, true);
_model.SetupCode = _googleSetupInfo.ManualEntryKey;
_model.BarCodeImageUrl = _googleSetupInfo.QrCodeSetupImageUrl;
_model.ManualEntryKey = _googleSetupInfo.ManualEntryKey;
return _model;
}
public DbResult Verify2FA(string otp, string userUniqueKey)
{
DbResult _dbRes = new DbResult();
if (string.IsNullOrEmpty(otp))
{
_dbRes.SetError("1", "OTP Code can not be blank!", null);
return _dbRes;
}
bool isValid = _tfa.ValidateTwoFactorPIN(userUniqueKey, otp);
if (isValid)
_dbRes.SetError("0", "Two factor authentication verified successfully!", null);
else
_dbRes.SetError("1", "Please enter valid OTP!", null);
return _dbRes;
}
public static string ReadWebConfig(string key, string defValue)
{
return (ConfigurationSettings.AppSettings[key] ?? defValue).ToString();
}
public static void WriteSession(string key, string value)
{
HttpContext.Current.Session[key] = value;
}
}
}

170
API/Model/EncryptDecryptUtility.cs

@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace API.Model
{
public class EncryptDecryptUtility
{
protected static string saltValue = "K0r3@GM3";
protected static string hashAlgorithm = "SHA1";
protected static int passwordIterations = 5;
protected static string initVector = "P@s$w0rDGm3KoR3@";
protected static int keySize = 256;
/// <summary>
/// Encrypts specified plaintext using Rijndael symmetric key algorithm
/// and returns a base64-encoded result.
/// </summary>
/// <param name="plainText">Plain Text to Encrypt</param>
/// <param name="passPhrase">Pass Phrase to use in Password Generation</param>
/// <returns>Encrypted text encoded into Base 64 text format </returns>
public static string Encrypt(string plainText, string passPhrase)
{
// Convert strings into byte arrays.
// Let us assume that strings only contain ASCII codes.
// If strings include Unicode characters, use Unicode, UTF7, or UTF8
// encoding.
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
// Convert our plaintext into a byte array.
// Let us assume that plaintext contains UTF8-encoded characters.
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
// First, we must create a password, from which the key will be derived.
// This password will be generated from the specified passphrase and
// salt value. The password will be created using the specified hash
// algorithm. Password creation can be done in several iterations.
var password = new PasswordDeriveBytes(
passPhrase,
saltValueBytes,
hashAlgorithm,
passwordIterations);
// Use the password to generate pseudo-random bytes for the encryption
// key. Specify the size of the key in bytes (instead of bits).
#pragma warning disable 618, 612
byte[] keyBytes = password.GetBytes(keySize / 8);
#pragma warning restore 618, 612
// Create uninitialized Rijndael encryption object.
var symmetricKey = new RijndaelManaged();
// It is reasonable to set encryption mode to Cipher Block Chaining
// (CBC). Use default options for other symmetric key parameters.
symmetricKey.Mode = CipherMode.CBC;
// Generate encryptor from the existing key bytes and initialization
// vector. Key size will be defined based on the number of the key
// bytes.
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
keyBytes,
initVectorBytes);
var memoryStream = new MemoryStream();
// Define memory stream which will be used to hold encrypted data.
var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
// Start encrypting.
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
// Finish encrypting.
cryptoStream.FlushFinalBlock();
// Convert our encrypted data from a memory stream into a byte array.
byte[] cipherTextBytes = memoryStream.ToArray();
// Close both streams.
memoryStream.Close();
cryptoStream.Close();
// Convert encrypted data into a base64-encoded string.
string cipherText = Convert.ToBase64String(cipherTextBytes);
// Return encrypted string.
return cipherText;
}
/// <summary>
/// Decrypts specified cipherText using Rijndael symmetric key algorithm
/// and returns a plain text result.
/// </summary>
/// <param name="cipherText">Encryted Text</param>
/// <param name="passPhrase">Pass Phrase used in Password Generation</param>
/// <returns></returns>
public static string Decrypt(string cipherText, string passPhrase)
{
// Convert strings defining encryption key characteristics into byte
// arrays. Let us assume that strings only contain ASCII codes.
// If strings include Unicode characters, use Unicode, UTF7, or UTF8
// encoding.
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
// Convert our ciphertext into a byte array.
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
// First, we must create a password, from which the key will be
// derived. This password will be generated from the specified
// passphrase and salt value. The password will be created using
// the specified hash algorithm. Password creation can be done in
// several iterations.
var password = new PasswordDeriveBytes(
passPhrase,
saltValueBytes,
hashAlgorithm,
passwordIterations);
// Use the password to generate pseudo-random bytes for the encryption
// key. Specify the size of the key in bytes (instead of bits).
#pragma warning disable 618, 612
byte[] keyBytes = password.GetBytes(keySize / 8);
#pragma warning restore 618, 612
// Create uninitialized Rijndael encryption object.
var symmetricKey = new RijndaelManaged();
// It is reasonable to set encryption mode to Cipher Block Chaining
// (CBC). Use default options for other symmetric key parameters.
symmetricKey.Mode = CipherMode.CBC;
// Generate decryptor from the existing key bytes and initialization
// vector. Key size will be defined based on the number of the key
// bytes.
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(
keyBytes,
initVectorBytes);
// Define memory stream which will be used to hold encrypted data.
var memoryStream = new MemoryStream(cipherTextBytes);
// Define cryptographic stream (always use Read mode for encryption).
var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
// Since at this point we don't know what the size of decrypted data
// will be, allocate the buffer long enough to hold ciphertext;
// plaintext is never longer than ciphertext.
var plainTextBytes = new byte[cipherTextBytes.Length];
// Start decrypting.
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
// Close both streams.
memoryStream.Close();
cryptoStream.Close();
// Convert decrypted data into a string.
// Let us assume that the original plaintext string was UTF8-encoded.
string plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
// Return decrypted string.
return plainText;
}
}
}

15
API/Model/GoogleAuthenticatorModel.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace API.Model
{
public class GoogleAuthenticatorModel
{
public string BarCodeImageUrl { get; set; }
public string SetupCode { get; set; }
public string ManualEntryKey { get; set; }
}
}

6
Business/Account/AccountServices.cs

@ -23,5 +23,11 @@ namespace Business.Account
{
return _accountRepo.ChangePassword(changePassword);
}
public DbResponse AuthenticateAgent(string userId , string otp , string uniqueKey)
{
return _accountRepo.AuthenticateAgent(userId , otp, uniqueKey);
}
}
}

3
Business/Account/IAccountServices.cs

@ -1,5 +1,6 @@
using Common.Model;
using Common.Model.Account;
using Common.Utility;
using System.Data;
namespace Business.Account
@ -7,7 +8,7 @@ namespace Business.Account
public interface IAccountServices
{
DbResponse ChangePassword(PasswordChangeModel changePassword);
DataSet LoginSystem(LoginModel loginModel);
DbResponse AuthenticateAgent(string userId, string otp, string uniqueKey);
}
}

8
JMEAgentSystem/Scripts/Account/Login.js

@ -31,10 +31,16 @@ function Login() {
swal(result.Msg);
}
else {
if (result["Extra"] == "1") {
var uniqueKey = result["Extra2"];
var newUrl = "/WebPages/Account/Authenticate.aspx?referralCode=" + referralCode + "&password=" + encodeURIComponent(password) + "&uniqueKey=" + encodeURIComponent(uniqueKey);
window.location.href = newUrl;
}
//ShowAlertMessage(result.Msg, 'success', 'Success', );
else {
$(location).attr("href", "/WebPages/");
}
}
}).fail(function () {
ShowAlertMessage('Unknown error occured, please contact JME!', 'error', 'Error');
//swal(result.Msg, "Error Occured", "error");

2
JMEAgentSystem/Scripts/Customer/CustomerRegistration.js

@ -813,7 +813,7 @@ function RegisterCustomerAndReeiverFromAjaxCall() {
var branch_manual = $("#" + mId + "branch_manual").val();
var hddImgURL = $("#" + mId + "hddImgURL").val();
formData.append("MethodName", "SaveCustomerAndReceiver");
formData.append("MethodName", "SaveCustomer");
formData.append("firstName", firstName);
formData.append("middleName", middleName);
formData.append("lastName", lastName);

137
JMEAgentSystem/WebPages/Account/Authenticate.aspx

@ -0,0 +1,137 @@
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Authenticate.aspx.cs" Inherits="JMEAgentSystem.WebPages.Account.Authenticate" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<link href="../../js/jquery/jquery-ui.css" rel="stylesheet" />
<link href="../../ui/css/menu.css" rel="stylesheet" />
<link href="../../ui/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<link href="../../ui/css/waves.min.css" rel="stylesheet" />
<link href="../../ui/css/style.css" rel="stylesheet" />
<link href="../../ui/font-awesome/css/font-awesome.min.css" rel="stylesheet" />
<script src="../../ui/bootstrap/js/bootstrap.min.js"></script>
<script src="../../js/functions.js"></script>
<style>
/*body {*/
/*font-family: Arial, sans-serif;*/
/*background-color: #f7f7f7;
}*/
.page-wrapper {
margin: 30px;
}
.panel-heading {
background-color: #f7f7f7;
}
.panel-title {
font-size: 24px;
margin-bottom: 0;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
font-weight: bold;
padding-top: 7px;
color: black;
}
.form-control {
border-radius: 5px;
box-shadow: none;
border: 1px solid #ddd;
}
.btn-primary {
background-color: #007bff;
border-color: #007bff;
}
.btn-primary:hover {
background-color: #0056b3;
border-color: #0056b3;
}
.btn-primary:focus {
box-shadow: none;
}
.errormsg {
color: red;
padding-left: 5px;
}
p {
font-size: 13px;
color: black;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<contenttemplate>
<div class="page-wrapper">
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="list">
<div class="row">
<div class="col-md-8">
<div class="panel panel-default ">
<div class="panel-heading">
<h4 class="panel-title">Verify OTP</h4>
<div class="panel-actions">
<a href="#" class="panel-action panel-action-toggle" data-panel-toggle></a>
</div>
</div>
<div class="panel-body">
<div id="msg" runat="server" class="error">
<div class="alert alert-danger" runat="server" id="errMsg" visible="false"></div>
</div>
<div class="form-group">
<label class="col-md-3">
User Name :
</label>
<div class="col-md-5">
<asp:TextBox ID="txtUserId" runat="server" ReadOnly="true" CssClass="form-control"></asp:TextBox>
</div>
</div>
<div class="form-group">
<label class="col-md-3">
Enter OTP :<span class="errormsg">*</span>
</label>
<div class="col-md-5">
<asp:TextBox ID="txtOtp" runat="server" CssClass="form-control"></asp:TextBox>
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-3">
<asp:Button ID="btnVerify" runat="server" Text="Verify" ValidationGroup="user"
CssClass="btn btn-primary m-t-25" TabIndex="5" OnClick="btnVerify_Click" />
&nbsp;&nbsp;&nbsp;
<%-- <asp:Button ID="btnCancel" runat="server" Text="Cancel" ValidationGroup="user"
CssClass="btn btn-primary m-t-25" TabIndex="5" OnClick="btnCancel_Click" />--%>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</contenttemplate>
</form>
</body>
</html>

64
JMEAgentSystem/WebPages/Account/Authenticate.aspx.cs

@ -0,0 +1,64 @@
using Common.Helper;
using Common.Utility;
using System;
using Repository.DAO;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Business.Account;
using Business.Configuration;
using Common.Model;
using API;
namespace JMEAgentSystem.WebPages.Account
{
public partial class Authenticate : System.Web.UI.Page
{
protected GoogleAuthenticatorAPI _auth = new GoogleAuthenticatorAPI();
private readonly IAccountServices _accountServices = AutoFacContainer.Resolve<IAccountServices>();
private readonly string userId = GetStatic.ReadQueryString("referralCode", "");
private readonly string password = GetStatic.ReadQueryString("password", "");
private readonly string uniqueKey = GetStatic.ReadQueryString("uniqueKey", "");
private string ipAddress = "";
protected string use2FA = "Y";
protected void Page_Load(object sender, EventArgs e)
{
LoadLoginData();
}
protected void LoadLoginData()
{
txtUserId.Text = userId;
}
protected void btnVerify_Click(object sender, EventArgs e)
{
var otp = txtOtp.Text;
if (string.IsNullOrEmpty(uniqueKey))
{
errMsg.InnerText = "Please contact JME Head office to get QR code for accessing JME Remit system!";
errMsg.Visible = true;
//EnableLogin();
return;
}
// var response = _accountServices.AuthenticateAgent(userId, otp, uniqueKey);
var _dbRes = _auth.Verify2FA(otp, uniqueKey);
if (_dbRes.ErrorCode != "0")
{
errMsg.InnerText = _dbRes.Msg;
errMsg.Visible = true;
// EnableLogin();
return;
}
{
Response.Redirect("/WebPages/");
}
}
}
}

80
JMEAgentSystem/WebPages/Account/Authenticate.aspx.designer.cs

@ -0,0 +1,80 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace JMEAgentSystem.WebPages.Account
{
public partial class Authenticate
{
/// <summary>
/// Head1 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlHead Head1;
/// <summary>
/// form1 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlForm form1;
/// <summary>
/// msg control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlGenericControl msg;
/// <summary>
/// errMsg control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlGenericControl errMsg;
/// <summary>
/// txtUserId control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox txtUserId;
/// <summary>
/// txtOtp control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox txtOtp;
/// <summary>
/// btnVerify control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Button btnVerify;
}
}

13
JMEAgentSystem/WebPages/Account/Login.aspx.cs

@ -2,7 +2,6 @@
using Business.Configuration;
using Common.Helper;
using Common.Model.Account;
using Common.Utility;
using Newtonsoft.Json;
using System;
using System.Data;
@ -42,6 +41,8 @@ namespace JMEAgentSystem.WebPages.Account
protected void SystemLogin()
{
var agentUniqueId = Request.Form["AgentUniqueId"];
DataSet ds = new DataSet();
//if (string.IsNullOrEmpty(agentUniqueId))
//{
// Response.ContentType = "text/plain";
@ -59,7 +60,11 @@ namespace JMEAgentSystem.WebPages.Account
AgentUniqueId = agentUniqueId
};
bool RememberMe = Convert.ToBoolean(GetStatic.ReadFormData("RememberMe", "false"));
DataSet ds = _accountServices.LoginSystem(loginModel);
//DataRow dataRow = _accountServices.AuthenticateAgent(loginModel);
//if(dataRow["isAuthenticator"].ToString() == "Y")
//{
ds = _accountServices.LoginSystem(loginModel);
var result = GetStatic.ParseDbResult(ds.Tables[0]);
if (result.ResponseCode == "0")
@ -74,6 +79,7 @@ namespace JMEAgentSystem.WebPages.Account
GetStatic.WriteSession("agentLimit", ds.Tables[1].Rows[0]["REFERRAL_LIMIT"].ToString());
GetStatic.WriteSession("agentId", ds.Tables[1].Rows[0]["BRANCH_ID"].ToString());
GetStatic.WriteSession("isForceChangePassword", ds.Tables[1].Rows[0]["FORCE_CHANGE_PWD"].ToString());
GetStatic.WriteSession("isAuthenticator", ds.Tables[1].Rows[0]["isAuthenticator"].ToString());
GetStatic.WriteSession("countryId", "113");
@ -87,12 +93,13 @@ namespace JMEAgentSystem.WebPages.Account
GetStatic.WriteCookie("JME_Agent_System_UserData_" + dt, loginModel.ReferralCode + "|" + loginModel.Password);
else
GetStatic.DeleteCookie("JME_Agent_System_UserData_" + dt);
}
// }
Response.ContentType = "text/plain";
string json = JsonConvert.SerializeObject(result);
Response.Write(json);
Response.End();
}
}
private void Logout()
{

9
JMEAgentSystem/WebPages/CustomerRegistration/Manage.aspx

@ -343,6 +343,13 @@
</div>
</div>
</div>
<div class="row" runat="server">
<div class="form-group" style="margin-left: 41px;">
<%--<asp:Button ID="registerCustomerAndReceiver" runat="server" CssClass="btn btn-primary m-t-25" disabled="disabled" Text="Submit" OnClientClick="return CheckMasterFormValidation()" />--%>
<%--<asp:Button ID="registerCustomerAndReceiver" runat="server" CssClass="btn btn-primary m-t-25" disabled="disabled" Text="Submit" OnClientClick="return CheckMasterFormValidation()" OnClick="registerCustomerAndReceiver_Click" />--%>
<input type="button" id="registerCustomerAndReceiver" value="Register" class="btn btn-primary m-t-25" disabled="disabled" onclick="return CheckMasterFormValidation()" />
</div>
</div>
</div>
</div>
</div>
@ -508,6 +515,8 @@
</div>
</div>
</div>
</div>
<div id="tempAddress" hidden></div>
<asp:HiddenField runat="server" ID="hdnVerifyDoc1" />

10
Repository/DAO/Account/AccountRepo.cs

@ -10,6 +10,16 @@ namespace Repository.DAO.Account
{
public class AccountRepo : ApplicationDAO, IAccountRepo
{
public DbResponse AuthenticateAgent(string userId , string otp, string uniqueKey)
{
StringBuilder sp = new StringBuilder("Exec PROC_JME_AGENT_SYSTEM_ACCOUNT @flag='authenticate-agent'");
sp.AppendLine(",@otp =" + FilterString(otp));
sp.AppendLine(",@userId =" + FilterString(userId));
sp.AppendLine(",@uniqueKey =" + FilterString(uniqueKey));
return ParseDbResult(sp);
}
public DataSet SystemLogin(LoginModel loginModel)
{
StringBuilder sp = new StringBuilder("Exec PROC_JME_AGENT_SYSTEM_ACCOUNT @flag='l'");

1
Repository/DAO/Account/IAccountRepo.cs

@ -13,5 +13,6 @@ namespace Repository.DAO.Account
DbResponse LogError(HttpException lastError, string page, string userName);
DbResponse ChangePassword(PasswordChangeModel changePassword);
DbResponse AuthenticateAgent(string userId, string otp, string uniqueKey);
}
}
Loading…
Cancel
Save