April 18, 2019

How to use jQuery with Angular 7

In this post I will explain how to setup jQuery with Angular.

Step # 1 - Install jQuery using npm

Go to the root of the Angular project where angular.json file is placed, and run the following command to install jQuery dependency.

 npm install --save jquery

Step # 2 - Add jQuery script reference in scripts array

You can now directly add jQuery script reference in index.html file, but a better approach would be to add the relative path in the scripts array in angular.json file.

 "scripts": [
  "node_modules/jquery/dist/jquery.min.js"
  ]

Step # 3 - Use jQuery in component

We need to declare the variable($) for jQuery as following.

 declare var $: any;

Here we have defined $ variable with data type any to satisfy TypeScript compiler.

We have setup jQuery. Now we can write the jQuery code inside ngOnInit event of the component.

Here is sample code for AppComponent with jQuery variavble($) declarartion and its use in ngOnInit function.

 import { Component, OnInit  } from '@angular/core';
 
 declare var $: any;
 
 @Component({
   selector: 'app-root',
   templateUrl: './app.component.html',
   styleUrls: ['./app.component.css']
 })
 export class AppComponent implements OnInit {
   title = 'jQuery with Angular';

   public ngOnInit()
   {
   $(document).ready(() => {
    $('#myDiv').html('Hello world from jQuery');
   });
   }
 }

Where myDiv is the id of any empty div placed inside app.component.html template.

That's all set. Now when you run the component you should be able to see the jQuery message inside the target div.

I hope this helps some of you who may be looking to setup jQuery in Angular component.

April 8, 2019

How to prevent cross-site request forgery (CSRF) attacks in ASP.Net Web Forms

In this post I will explain how to fix CSRF attack in ASP.Net Web Forms application. I found many articles talking about how to implement this in MVC applications, but I face real trouble to develop this in Web Forms. I found following solution worked for me.

We have to write the following code in site's Master page, and this solution will apply CSRF protection to all content pages that are inherit from this Master page. Also make sure all requests making data modifications must use the ViewState.

Here is the code we need to write in Master Page code-behind file.

 public partial class SiteMaster : MasterPage
 {
   private const string AntiXsrfTokenKey = "__AntiXsrfToken";
   private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
   private string _antiXsrfTokenValue;

   protected void Page_Init(object sender, EventArgs e)
   {
  //check if we already have Anti-XSS cookie, then put it in page's global variable
  var requestCookie = Request.Cookies[AntiXsrfTokenKey];
  Guid requestCookieGuidValue;
  
  if (requestCookie != null
   && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
  {
    _antiXsrfTokenValue = requestCookie.Value;
    Page.ViewStateUserKey = _antiXsrfTokenValue;
  }
  //If we do not found CSRF cookie, then this is a new session, so create a new cookie with Anti-XSRF token
  else
  {
    _antiXsrfTokenValue = Guid.NewGuid().ToString("N");
    Page.ViewStateUserKey = _antiXsrfTokenValue;

    var responseCookie = new HttpCookie(AntiXsrfTokenKey)
    {
   HttpOnly = true,

   //Add the Anti-XSRF token to the cookie value
   Value = _antiXsrfTokenValue
    };

    //If we are using SSL, the cookie should be set to secure 
    if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
    {
   responseCookie.Secure = true;
    }

    //Add the CSRF cookie to the response
    Response.Cookies.Set(responseCookie);
  }

  Page.PreLoad += master_Page_PreLoad;
   }

   protected void master_Page_PreLoad(object sender, EventArgs e)
   {
  //During the initial page request, Add the Anti-XSRF token and user name to the ViewState
  if (!IsPostBack)
  {
    ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
    ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
  }
  //During all post back requests to the page, Validate the Anti-XSRF token
  else
  {
    if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
     || (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
    {
   throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
    }
  }
   }
 }

If Context.User.Identity.Name is empty?

In case if it does not work as per the expectations, one reason could be that the Context.User.Identity.Name is containing empty string not the real user name.

To fix this make sure you need authentication mode set to windowsAuthentication in web.config. and have disabled the anonymous authentication. Hence all the authentication mechanisms are disabled, except for the Windows Authentication.

Another alternative could be if you are manually maintaining login user's data in some Session variable, then replace that statement to read user name from that Session variable rather than Context.User.Identity.Name.

For example, after making this change of reading user name from Session variable, the code listing of master_Page_PreLoad event handler will become similar to this:

  protected void master_Page_PreLoad(object sender, EventArgs e)
   {
  //During the initial page request, Add the Anti-XSRF token and user name to the ViewState
  string userName =  String.Empty;
  if(Session["UserName"] != null)
  {
   userName = Session["UserName"].ToString();
  }
  
  if (!IsPostBack)
  {
    ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
    ViewState[AntiXsrfUserNameKey] = userName;
  }
  //During all post back requests to the page, Validate the Anti-XSRF token
  else
  {
    if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
     || (string)ViewState[AntiXsrfUserNameKey] != userName)
    {
   throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
    }
  }
   }

Thats all you need. Now all the content pages that are inherited from this master page should be able to prevent CSRF attacks.

I hope this helps some of you who get stuck with a similar problem.