Friday, November 24, 2017

Authentication in wcf rest service

Steps.

  1. Create Authenticate method which authenticates an user and also returns a token which can be used for next subsequent requests.
  2. Create a login class in business layer which has business logic to validate the user credential against database and generate the token if the credentials are valid
  3. Create a method to validate the token which would come in next subsequent requests



  • Create Authenticate method in *SVC.cs file which takes userId and password as a parameter

//Below method authenticates the user and sends a token for authenticated user which can be used for //next subsequent requests.

public stream Authenticate(string userID, string password) {<br /> &nbsp;Stream strJSONResponse = null;<br /> &nbsp;Login Obj = new + 6(); // This is your login class in business layer explained in point #2 below<br /> &nbsp;//string deviceId = string.Empty &nbsp; //Optional if you are coding for mobile devices then can be used<br /> &nbsp;WebHeaderCollection headers = WebOperationContext.Current.IncomingRequest.Headers;<br /> &nbsp;//WebHeaderCollection &nbsp;- Namespace | System.net.WebHeaderCollection<br /> &nbsp;//WebOperationContext - Namespace | System.serviceModel.web.WebOperationContext<br /> &nbsp;try {<br /> &nbsp; foreach(string headerName in headers.Allkeys) {<br /> &nbsp; &nbsp;//If you want retrieve device ID from header<br /> &nbsp; &nbsp;if (headerName == 'desiredDeviceId') {<br /> &nbsp; &nbsp; deviceId = headers[headername];<br /> &nbsp; &nbsp;}<br /> &nbsp; &nbsp;strJSONResponse = obj.Authenticate(userID, password, deviceId)<br /> &nbsp; &nbsp;return strJSONResponse;<br /> &nbsp; }<br /> &nbsp;}<br /> }<br /> <br /> <br />

  • Login class in business layer having implementation of Authenticate method


public class Login {
 public stream Authenticate(string usersId, string password, string deviceId) {
   outAuthentication objOutAuthentication = new outAuthentication();
   try {
    objOutAuthenticaton.successFlag = Decimal.One.ToString();
    if (deviceId == String.Empty) {
     objOutAuthenticaton.successMessage = "Device Id Absent";
    } else {
     objOutAuthenticaton.successMessage = "Success";
     bool bIsAuthenticatedUser = false;
     bool bIsActiveUser = false;
     DataTable dtUser = objDAL.GetUserCredentials(usersId);
     if (dtUser != null && dtUser.Rows.count > 0) {
      Decrypt objDecrypt = new clsUtilities.Decrypt();
      if `(userID.ToUpper() == convert.ToString((dtUser.Rows[0][0]).Trim().ToUpper && password == objDecrypt.DecryptString(Convert.ToString(dtUser.Rows[0][1])))
{
bIsAuthenticatedUser = true;
}
bIsAtctiveUser = Convert.ToBoolean(dtUser.Rows[0][2]);
}
}
objOutAuthenticaton.status = bIsAuthenticatedUser == true? Decimal.One.ToString() : Decimal.Zero.ToString();

if(bIsActiveUser)
{
if(bIsAuthenticatedUser)
{
Datatable dt = new DataTable();
dt = objDAL.GetUserDetail(userId)
if ( dt!= null && dt.Rows.count>0)
{
//Below code to send Authenticate key to the calling application so that it can be used for subsequent //request by authorized user. User won't have to provide ID and pwd again and again
objOutAuthenticaton.authKey = GenerateToken(usersId, "AnyStringKey", deviceId, DateTime.UtcNow.Ticks);

//Insert autorization token in session token table
InsertAuthToken(objOutAuthenticaton.authKey,DateTimeUtcNow);
}
}
}
}
}


//Database layer


  • 3. Get user credentials saved in database

public DataTable GetUserCredentials(string strUserId) {
 DataTable dt = new DataTable();
 ConnectionClass objConnection = new ConnectionClass();
 try {
  SqlParameter[] objParams = {
   new SqlParameters("UsersID", SqlDbType.Nvarchar) {
    Value = strUserId
   }
  };
  dt = ExecuteReaderDataTableSP("Login_usp_GetUserCredentials, objParams);
  }
 }

}



  • 4. Generate Token

public static string GenerateToken(string userName, string password, string deviceID, long ticks) {
 string hash = string.Join(":", new string[] {
  userName,
  deviceID,
  ticks,
  ToString()
 });
 string hashLeft = string.Empty;
 string hashRight = string.Empty

 using(HMAC hmac = HMACHA256.Create("HmacSHA256")) {
  hmac.key = Encoding.UTF8.GetBytes(GetHashedPassword(password));
  hmac.computeHash(Encoding.UTF8.GetBytes(hash));
  hashLeft = Convert.ToBase64String(hmac.Hash);
  hashRight = string.Join(":", new string[] {
   userName,
   deviceID,
   ticks.ToString()
  });
 }
 return Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Join(":", hashLeft, hashRight)));
}



5. Insert GeneratedToken into database
public bool InsertAuthToken(string token, DateTime currentDate) {
  ConnectionClass objConnection = new ConnectionClass();
  try {
   SqlParameter[] objParams = {
    new SqlParameters("token", SqlDbType.Nvarchar) {
     Value = token
    } {
     new SqlParameters("currentDate", SqlDbType.Nvarchar) {
      Value = currentDate
     }
    };
    int iCount = objConnection.ExecuteNonQuerySP("usp_InsertAuthToken", objParams);
    return icount > 0 ? true : false;
   }
  }


  • 6. IsTokenValid

Call below method in subsequent requests to verify the token sent by client is valid or not

public static string IsTokenValid(string token, string userId, string dvcId) {
 string message = String.Empty;
 try {
  string key = Encoding.UTF8.GetString(Convert.FromBase64String(token));
  int _expirationMinutes = Convert.ToInt32("20").ToString();
  // Split the parts,
  string[] parts = key.Splt(new char[] {
   ':'
  });
  if (parts.Lenth == 4) {
   string hash = parts[0];
   string username = parts[1];
   string deviceId = parts[2];
   long ticks = parts[3];
   string servicePassword = "AnyStringKey";
   string computedToken = GenerateToken(username, servicePassword, deviceId, ticks);

   if (token == computedToken) {
    string modifiedTime = GetModifiedDts(token); //check expiry date of token
    if (!string.IsNullOrEmpty(modifiedTime)) {
     boll expired = Math.Abs((DateTime.UtcNow - Convert.ToDateTime(modifiedTime)).TotalMinutes) > 20;

     if (expired) {
      message = "Auth Key Expired, please login again";
      //Delete token from session table of database
     } else {
      //update the latest timestamp in database against that token so that session time keep on extending if //attempt is valid
      DateTim currentDate = DateTime.UtcNow;
      //UpdateAuthToken(token,CurrentDate)
      message = "Authentication Key is valid";
     } |


    }
   }

   //Check whether the user name is proper from header
   if (username == userId && deviceId == dvcId) {}
  }
 }
}



Stored Procedures :

1. usp_GetUserCredentials

CREATE PROCEDURE [dbo].[usp_GetUserCredentials] @usersId nVarchar(50)
AS
BEGIN
SELECT U.UsersId,U.Password, U.isActive
FROM [DBO].[users] U
Where U.usersId = @usersId
AND @usersId IS NOT NULL;
END

2. usp_InsertAuthToken

CREATE PROCEDURE [dbo].[usp_InsertAuthToken]
@token nvarchar(max),
@curentDate DateTime
As
BEGIN
Insert INTO [DBO].SESSIONTOKENS] VALUES (ltrim(rtrim(@token, @currentDate)
END

Sunday, September 11, 2016

authentication in wcf

Authentication in wcf rest service

Steps.

  1. Create Authenticate method which authenticates an user and also returns a token which can be used for next subsequent requests.
  2. Create a login class in business layer which has business logic to validate the user credential against database and generate the token if the credentials are valid
  3. Create a method to validate the token which would come in next subsequent requests



  • Create Authenticate method in *SVC.cs file which takes userId and password as a parameter

//Below method authenticates the user and sends a token for authenticated user which can be used for //next subsequent requests.

public stream Authenticate(string userID, string password) {
 Stream strJSONResponse = null;
 Login Obj = new + 6(); // This is your login class in business layer explained in point #2 below
 //string deviceId = string.Empty   //Optional if you are coding for mobile devices then can be used
 WebHeaderCollection headers = WebOperationContext.Current.IncomingRequest.Headers;
 //WebHeaderCollection  - Namespace | System.net.WebHeaderCollection
 //WebOperationContext - Namespace | System.serviceModel.web.WebOperationContext
 try {
  foreach(string headerName in headers.Allkeys) {
   //If you want retrieve device ID from header
   if (headerName == 'desiredDeviceId') {
    deviceId = headers[headername];
   }
   strJSONResponse = obj.Authenticate(userID, password, deviceId)
   return strJSONResponse;
  }
 }
}



  • Login class in business layer having implementation of Authenticate method


public class Login {
 public stream Authenticate(string usersId, string password, string deviceId) {
   outAuthentication objOutAuthentication = new outAuthentication();
   try {
    objOutAuthenticaton.successFlag = Decimal.One.ToString();
    if (deviceId == String.Empty) {
     objOutAuthenticaton.successMessage = "Device Id Absent";
    } else {
     objOutAuthenticaton.successMessage = "Success";
     bool bIsAuthenticatedUser = false;
     bool bIsActiveUser = false;
     DataTable dtUser = objDAL.GetUserCredentials(usersId);
     if (dtUser != null && dtUser.Rows.count > 0) {
      Decrypt objDecrypt = new clsUtilities.Decrypt();
      if `(userID.ToUpper() == convert.ToString((dtUser.Rows[0][0]).Trim().ToUpper && password == objDecrypt.DecryptString(Convert.ToString(dtUser.Rows[0][1])))
{
bIsAuthenticatedUser = true;
}
bIsAtctiveUser = Convert.ToBoolean(dtUser.Rows[0][2]);
}
}
objOutAuthenticaton.status = bIsAuthenticatedUser == true? Decimal.One.ToString() : Decimal.Zero.ToString();

if(bIsActiveUser)
{
if(bIsAuthenticatedUser)
{
Datatable dt = new DataTable();
dt = objDAL.GetUserDetail(userId)
if ( dt!= null && dt.Rows.count>0)
{
//Below code to send Authenticate key to the calling application so that it can be used for subsequent //request by authorized user. User won't have to provide ID and pwd again and again
objOutAuthenticaton.authKey = GenerateToken(usersId, "AnyStringKey", deviceId, DateTime.UtcNow.Ticks);

//Insert autorization token in session token table
InsertAuthToken(objOutAuthenticaton.authKey,DateTimeUtcNow);
}
}
}
}
}


//Database layer

  • 3. Get user credentials saved in database

public DataTable GetUserCredentials(string strUserId) {
 DataTable dt = new DataTable();
 ConnectionClass objConnection = new ConnectionClass();
 try {
  SqlParameter[] objParams = {
   new SqlParameters("UsersID", SqlDbType.Nvarchar) {
    Value = strUserId
   }
  };
  dt = ExecuteReaderDataTableSP("Login_usp_GetUserCredentials, objParams);
  }
 }

}


  • 4. Generate Token

public static string GenerateToken(string userName, string password, string deviceID, long ticks) {
 string hash = string.Join(":", new string[] {
  userName,
  deviceID,
  ticks,
  ToString()
 });
 string hashLeft = string.Empty;
 string hashRight = string.Empty

 using(HMAC hmac = HMACHA256.Create("HmacSHA256")) {
  hmac.key = Encoding.UTF8.GetBytes(GetHashedPassword(password));
  hmac.computeHash(Encoding.UTF8.GetBytes(hash));
  hashLeft = Convert.ToBase64String(hmac.Hash);
  hashRight = string.Join(":", new string[] {
   userName,
   deviceID,
   ticks.ToString()
  });
 }
 return Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Join(":", hashLeft, hashRight)));
}



5. Insert GeneratedToken into database
public bool InsertAuthToken(string token, DateTime currentDate) {
  ConnectionClass objConnection = new ConnectionClass();
  try {
   SqlParameter[] objParams = {
    new SqlParameters("token", SqlDbType.Nvarchar) {
     Value = token
    } {
     new SqlParameters("currentDate", SqlDbType.Nvarchar) {
      Value = currentDate
     }
    };
    int iCount = objConnection.ExecuteNonQuerySP("usp_InsertAuthToken", objParams);
    return icount > 0 ? true : false;
   }
  }

  • 6. IsTokenValid

Call below method in subsequent requests to verify the token sent by client is valid or not

public static string IsTokenValid(string token, string userId, string dvcId) {
 string message = String.Empty;
 try {
  string key = Encoding.UTF8.GetString(Convert.FromBase64String(token));
  int _expirationMinutes = Convert.ToInt32("20").ToString();
  // Split the parts,
  string[] parts = key.Splt(new char[] {
   ':'
  });
  if (parts.Lenth == 4) {
   string hash = parts[0];
   string username = parts[1];
   string deviceId = parts[2];
   long ticks = parts[3];
   string servicePassword = "AnyStringKey";
   string computedToken = GenerateToken(username, servicePassword, deviceId, ticks);

   if (token == computedToken) {
    string modifiedTime = GetModifiedDts(token); //check expiry date of token
    if (!string.IsNullOrEmpty(modifiedTime)) {
     boll expired = Math.Abs((DateTime.UtcNow - Convert.ToDateTime(modifiedTime)).TotalMinutes) > 20;

     if (expired) {
      message = "Auth Key Expired, please login again";
      //Delete token from session table of database
     } else {
      //update the latest timestamp in database against that token so that session time keep on extending if //attempt is valid
      DateTim currentDate = DateTime.UtcNow;
      //UpdateAuthToken(token,CurrentDate)
      message = "Authentication Key is valid";
     } |


    }
   }

   //Check whether the user name is proper from header
   if (username == userId && deviceId == dvcId) {}
  }
 }
}



Stored Procedures :

1. usp_GetUserCredentials

CREATE PROCEDURE [dbo].[usp_GetUserCredentials] @usersId nVarchar(50)
AS
BEGIN
SELECT U.UsersId,U.Password, U.isActive
FROM [DBO].[users] U
Where U.usersId = @usersId
AND @usersId IS NOT NULL;
END

2. usp_InsertAuthToken

CREATE PROCEDURE [dbo].[usp_InsertAuthToken]
@token nvarchar(max),
@curentDate DateTime
As
BEGIN
Insert INTO [DBO].SESSIONTOKENS] VALUES (ltrim(rtrim(@token, @currentDate)
END

Thursday, August 18, 2016

Log4Net


log4net step by step


1. Install Log4Net either by adding log4Net.dll or by running below command,
  • PM> Install-Package log4net

2. Create XML file inside web application project as below

<? xml version = " 1.0 " ?>
< log4net >
< appender name = " FileAppender " type = " log4net.Appender.RollingFileAppender " >
< param name = " File " value = " D:\LogFile.log " />
< param name = " DatePattern " value = " yyyy.MM.dd " />
< param name = " RollingStyle " value = " Size " />
< param name = " maxSizeRollBackups " value = " 10 " />
< param name = " maximumFileSize " value = " 100KB " />
< layout type = " log4net.Layout.PatternLayout " >
< param name = " ConversionPattern " value = " %date{yyyy-MM-dd HH:mm:ss ffff} [%-3t] %-5p %logger{1}.%method: %message%newline " />
</ layout >
</ appender >
< root >
<!-- OFF, FATAL, ERROR, WARN, DEBUG, INFO, ALL -->
< level value = " ALL " />
< appender-ref ref = " FileAppender " />
</ root >
</ log4net >

Assume that "log4net.xml" is the file name of the above created xml file

3.  Configure above created xml file in web.config
  • In <appsettings> section add below entry
  • <add key = "log4net.config" value = "log4net.xml" />
4. Create Logger.cs in project and add reference of log4net.dll in the project. Mostly this would be in the utility project as we can refer utility project in any of the layer/project.

Using System;

namespace yournamespacename;
public class logger
{
private static log4net.ILog Log {get; set;}
static Logger
{
Log = log4net.LogManager.GetLogger(typeof(Logger));
}

public static void Error (Object message)
{
Log.Error(message);
}

public static void Error (Object message, Exception Ex)
{
Log.Error(message, Ex);
}

public static void Error (Exception Ex)
{
Log.Error(Ex);
bool x = Log.IsErrorEnabled;
}

public static void Info (Object message)
{
Log.Info(message);
}

}

5. Make sure the user (generally Iuser) configured in IIS to access the website has read write access to the Log file. This can be done by right click -> properties -> Security -> Edit -> Add -> select the user and give the permissions.

6. Below is the sample which can be used in catch block
  • Add reference of above project where log4net has to be used
  • Catch block can be as below
Catch (exception ex)
{
Logger.Error(ex);
}

 ====================================================================
If it is not working, follow below changes,

1. Add below line in AssemblyInfo.cs file,
[assembly: log4net.Config.XmlConfigurator(Watch = true)]

2. Add below section in App.config file,

<configSections>

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

</configSections>

<log4net>

<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">

<param name="File" value="D:\\PUDLog.log" />

<AppendToFile value="true" />

<param name="DatePattern" value="yyyy.MM.dd" />

<param name="RollingStyle" value="Size" />

<param name="maxSizeRollBackups" value="10" />

<param name="maximumFileSize" value="100KB" />

<layout type="log4net.Layout.PatternLayout">

<param name="ConversionPattern" value="%date{yyyy-MM-dd HH:mm:ss ffff} [%-3t] %-5p %logger{1}.%method: %message%newline" />

</layout>

</appender>

<root>

<!-- OFF, FATAL, ERROR, WARN, DEBUG, INFO, ALL -->

<level value="DEBUG" />

<appender-ref ref="FileAppender" />

</root>

</log4net>

Wednesday, August 3, 2016

Anonymous method in c#

Anonymous method


When to use anonymous methods

  • If we want to use the delegate only inside the same function
  • Reduce overhead of instantiating delegate i.e. performance improvement
E.g.

class program
{
delegate int pointToAddFunction(int n1,int n2);

static void Main (string[] args)
{
//Anonymous method is below
pointToAddFunction ptrObj = delegate
(int n1,int n2)
{
return n1 +n2;
};     //Note semicolon
//Anonymous method ended

int x = ptrObje.Invoice(2,2);
console.writeline(x);
}
}
 

Design patterns c# examples

Singleton Pattern

When we want only one instance of the object to be created and shared between clients (global variables of project)

To achieved/implement Singleton pattern
1. Define the constructor as private. So no instance/object can be created
2. Define instance (variables) & methods as static. This will cause one global instance to be created and shared across.

E.g.

public class clsSingleton
{
public static int intCounter;
private clsSingleTon()
{
//This is private constructor
}
private static void Hits()
{
intCounter++;
}
public static int getTotalHits()
{
return intCounter;
}
}

Client code

clsSingleTon.Hit();  // Everytime counter increments tag by 1

=========================================================================

Factory Pattern

public class clsFactoryInvoice
{
public static IInvoice getInvoice(int intInvoiceType)
{
IInvoice objinv;
if(intInvoiceType == 1)
{
objinv = new clsInvoiceWithHeaders();
}
else if (intInvoiceType == 2)
{
objinv = new clsInvoiceWithoutHeaders();
}
else
{
return null;
}
return objinv;
}
}

public Interface IInvoice
{
void print();
}

public class clsInvoiceWithHeader : IInvoice
{
public void print()
{
console.writeline("Invoice will be printed with Header");
}
}

public class clsInvoiceWithoutHeader : IInvoice
{
public void print()
{
console.writeline("Invoice will be printed without Header");
}
}

client code

class program
{
static void Main (string [] args)
{
int intInvoiceType = 0;
IInvoice objInvoice;
console.writeline("Enter Invoice Type");
intInvoiceType = console.readline();
objInvoice = clsFactoryInvoice.getInvoice(intInvoiceType );
objInvoice .print();
console.Readline();
}
}

Benefits : Client no need to know which all concrete classes available (loosely coupling) client will have object created just by passing parameter
 

Wednesday, July 20, 2016

Shadowing in c#

Shadowing in c#


new keyword explicitly hides member that is inherited from the base class (base class method is hidden or we can say derived class replaces/hides the base method) 

When you hide an inherited member, the derived version of the member replaces the base class version.


* It is an error to use both new and override on the same member, because the two modifier have mutually exclusive meanings. The new modifier creates a new member with the same name and causes the original member to become hidden. The override modifier extends the implementation for an inherited member.

public class BaseC
{
public int x;
public void invoke()
{
}
}

public class DerivedC : BaseC
{
   nenw public void Invoke()
   {
    }
}

Design patterns c#

Design patterns c#

Singleton pattern

When we want only one instance of the object to be created and shared between clients (global variables of project)

To achieve/implement singleton pattern

1. Define the constructor as private, so no instance/object can be created
2. Define instance (variables) and methods as static. This will cause one global instance to be created and shared across.

E.g.

Public class clsSingleton
{
  public static int intCounter;
  private clsSingleton()
    {
       //This is a private constructor
     }

   public static void Hits()
    {
         intCounter++;
     }
    public static int getTotalHits()
     {
        return intCounter;
      }
}

Client Code
clsSingleton.Hit();                 //Everytime counter increments by 1


Factory Pattern

public class clsFactoryInvoice
{
  public static IInvoice getInvoice(int intInvoiceType)
  {
    IInvoice objInv;
    if(intInvoiceType == 1)
    {
      objInv = new clsInvoiceWithHeader();
    }
    else if (intInvoiceType ==2)
    {
        objInv = new clsInvoiceWithoutHeader();
     }
     else
      { return null;}
    return objInv;
  }
}

public interface IInvoice
{
  public void print();
}

public class clsInvoiceWithHeader : IInvoice
{
  public void print()
  {
     console.writelinne("Invoice will be printed with header");
   }
}

public class clsInvoiceWithoutHeader : IInvoice
{
  public void print()
  {
     console.writelinne("Invoice will be printed without header");
   }
}


Benefits : Client no need to know which all concrete classes available (loosely coupled) client will have object created just by passing parameter.