Enabling SSL in IIS Express

This blog post is intended to help lay the groundwork to eventually setup and configure Mutual Authentication (Two Way TLS/Client Cert).  For now, I will demonstrate how to just setup and configure basic SSL in IIS Express.  For this exercise, I will be using a self-signed certificate that Visual Studio automatically generates and installs for us.

In the next blog, I will then show how to setup and configure a Client Cert for Mutual Authentication for your Web API.  Finally, I will demonstrate how to deploy this to an Azure App Service and test using Chrome and Postman.

Prerequisites:  Visual Studio 2017 Community Edition on Windows 10 Home Edition or similar development environment.

Assumption:  You know C#, WebApi and do not need every exact step for creating a Web API project.

My source code can be found here:

Creating a Sample Project

First, let’s start by creating an Empty WebApi project.

NewProject.JPG

After clicking the “Ok” button, then check MVC and WebApi.

EmptyWebApiProject.JPG

Then click “Ok” again.  Now we are ready to add a new API endpoint.  Right click on the Controllers folder and add a new Controller.  Since this is a WebApi, make sure your controller inherits from ApiController.

Next, let’s add a test endpoint that returns various useful information:

public IHttpActionResult Get()
{
     var testResult = new
     {
          ApiName = "SSLSample",
          ServerInstance = Environment.MachineName,
          Version = "1.0",
          UsingSSL = (this.ActionContext.Request.RequestUri.Scheme == Uri.UriSchemeHttps),
          HealthMeter = 100
     };

     return Ok(testResult); // Returns an OkNegotiatedContentResult
 }

Next run and test the endpoint to verify that our endpoint works and returns the expected result using your favorite browser with the appropriate URL.

ChromeHttpResult.JPG

The results will look similar to this:

{
 "ApiName": "SSLSample",
 "ServerInstance": "ASUS",
 "Version": "1.0",
 "UsingSSL": false,
 "HealthMeter": 100
}

Note:  Your URL may be different.  Check the properties of your project for the URL your project is configured for.  It will usually very by port number.

Now we know we have a working API.  Let’s configure SSL.

Configuring SSL

This is really, really difficult so make sure your read carefully (note the sarcasm).   Microsoft has really overly simplified this process compared to 10 years ago.  First, right click on the project and click “Properties”.

In the “Properties” section, enable SSL.

EnablingSSL.JPG

Now, run  the WebApi.  The first time when your run the WebApi project, you will need to trust the IIS Express SSL Certificate.

TestSelfSignedCert.JPG

Then another dialog will pop-up asking you to install the certificate.

TrustingTheCert.JPG

Once this is up and running, let’s test the endpoint using HTTPS.  Obviously, make sure your are using the appropriate URL when testing HTTPS.

ChromeHttpsResult.JPG

Notice that both HTTP and HTTPS URLs will work.  It is up to you to decide if you need to block access to your endpoints for HTTP.  There are several ways to do that.

Conclusion

This blog has demonstrated how simple it is now to develop and run Web API in IIS Express using SSL.  Ten years ago doing this was very convoluted and error prone.  Now it is overly simplified so any developer can easily setup their dev environment to run SSL.  Next, I will dive into Mutual Authentication for IIS Express.

References

 

 

 

Ionic 2 Issues on Windows 10

The last couple days I have been struggling with installing Ionic 2 on my Windows 10 laptop.

Here is my Ionic info:

C:\Dev\ionicProjects>ionic info

Your system information:

Cordova CLI: 6.3.1
Gulp version: CLI version 3.9.0
Gulp local:
Ionic CLI Version: 2.1.0
Ionic App Lib Version: 2.1.0-beta.1
OS:
Node Version: v6.7.0

Here is the error I was getting when trying to start a project.  Really helpful, right?

C:\Dev\ionicProjects>ionic start –v2 myApp
Creating Ionic app in folder C:\Dev\ionicProjects\myApp based on tabs project
Downloading: https://github.com/driftyco/ionic2-app-base/archive/master.zip
[=============================] 100% 0.0s
Downloading: https://github.com/driftyco/ionic2-starter-tabs/archive/master.zip
[=============================] 100% 0.0s
Installing npm packages…
Error with start undefined
Error Initializing app: There was an error with the spawned command: npminstall
There was an error with the spawned command: npminstall
Caught exception:
undefined

Mind letting us know? https://github.com/driftyco/ionic-cli/issues

So I struggled trying many different things and finally figured out that I needed to install git which is needed for running ionic start.

SOLUTION:  Download and install git from here

https://git-for-windows.github.io/

Then restart your command prompt and hopefully it work just as it did for me…

 

Cordova Hook: Internationalizing your App Name for Android

On a recent app I worked on, we needed to internationalize the App Name.  Currently, Cordova does not allow you to easily handle this via configuration.  One alternative is to open the Android project and modify it to include the internationalization.  However, if a developer removes the platform, the process has to be repeated.  This article explains how to accomplish this in a repeatable process that works when the developer removes and adds the Android App.  I will be using the Ionic Framework to build this sample app; however, this should work for any Cordova project.

Why do I want this repeatable?  Great, question.  Maybe I have an App that is used by multiple clients so I need a configurable build process for each client where one client supports English but another supports English and Spanish.  If so, this builds the basic foundation necessary to create such a dynamic build environment.

Assumptions:  I am assuming you have some experience writing Mobile Hybrid Apps with Cordova and Ionic Framwork.

Please checkout the GitHub repository here:

Cordova Hooks

Cordova allows developers to create hooks that run to customize Cordova commans like adding/removing platforms, running a build, etc.  Hooks can be written in any language according to their documentation but I personally have only used Node.js for writing hooks.

This hook has a dependency for the the fs.extra NPM Package.  It can be found in the following location.  Dependencies

In your Cordova project, run the following command:

npm install --save fs.extra

For this project, our hook will run when the Android app is prepared.  Therefore, we will create a js file named 020_i18n_app_name.js in the “hooks/after_prepare” folder.

Unlike iOS, this is rather simple.  We just need to copy the necessary resources files into the Android project.  Therefore, this hook checks to see if the Cordova Project is configured for the Android platform and the copies predefined Android Resource files to the appropriate Android platform folder.

#!/usr/bin/env node

var fs = require("fs.extra");

var fsCallback = function (err) {
    if (err) {
        console.error("Failed to create directory or file.");
        throw err;
    }
}

var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);

if (platforms.indexOf('android') > -1) {
    console.log("Adding I18N App Name for Android");

    // Copy over the English Resource Files
    fs.copy('resources/android/values/strings.xml', 'platforms/android/res/values/strings.xml', { replace: true }, fsCallback);

    // Copy over the French Resource Files
    fs.mkdirp('platforms/android/res/values-fr', fsCallback);
    fs.copy('resources/android/values-fr/strings.xml', 'platforms/android/res/values-fr/strings.xml', { replace: true }, fsCallback);

    // Copy over the Spanish Resource Files
    fs.mkdirp('platforms/android/res/values-es', fsCallback);
    fs.copy('resources/android/values-es/strings.xml', 'platforms/android/res/values-es/strings.xml', { replace: true }, fsCallback);

    console.log('Added I18N Resource Files for Android');
} else {
    console.warn('I18N Resource Files were NOT added for Android');
}

Resources Files

For each language that we want to support in the App, you will need to create an Android Resource file called strings.xml in a folder.  Here is a sample for English:

<?xml version='1.0' encoding='utf-8'?>
<resources>
    <string name="app_name">Good Morning</string>
    <string name="launcher_name">@string/app_name</string>
    <string name="activity_name">@string/launcher_name</string>
</resources>

You need to create a values folder for each language.  The default language will have a folder called values; while each other language will use the following syntax:  values-{{language code}}.  IE.  values-fr for French, values-es for Spanish, etc…

I placed these folders and files under a folder called resources/android in my root folder for my project.  The hook will then copy the files to the appropriate location in the Android project.

ResourcesFilesForAndroid

 

Check it out

Since I am using Ionic, I’ll run the following command:

ionic run android

That command is basically a wrapper for the Cordova command.  Notice the output and you will see the hook running and adding the files to the Android project before building and installing the app.

Running command: "C:\Program Files\nodejs\node.exe" C:\Dev\ionicProjects\ionic2SampleI18N\hooks\after_prepare\020_i18n_app_name.js C:\Dev\ionicProjects\ionic2SampleI18N
Adding I18N App Name for Android
Added I18N Resource Files for Android

Finally, the App Name internationalized running on Android:

MobileAppI18N.png

Conclusion

At this time, this process certainly meets my needs.  But this obviously could be considered immature and easily improved on by adding configuration to config.xml that contains the languages and resource locations.  Certainly a project for another day!

Other Resources:

Android: What is AAPT?

Android has a ton of tools.  This is a quick introduction to a couple commands I use in AAPT.

What is AAPT?

AAPT (Anroid Asset Packaging Tool) is a great tool to help you view, create and update your APKs (as well as zip and jar files).

Where is it?

On Windows, check you Android/tools folder.  For my Windows 8, it is located here:

C:\Program Files (x86)\Android\android-sdk\build-tools\23.0.2

Just add it to your path Environment Variable.

Getting your VersionCode, etc…

By running the following commands, you will see lots of important information from App Id, Version Code, Version Number, SDK Info, Permissions, etc…

aapt dump badging my.apk

This is really helpful when delivering the APK to a client.  If a client questions the VersionCode or other information, you can easily verify the app and also explain how the client can verify it.

When running this tool the output will look similar to this:

AAPTDumpBadging

Check your permissions:

It also helps verify what permissions are set in the app.  We recently failed a security audit for our App.  The customer said the Third Party failed our app for too many permissions.  This tool was very helpful in determining the exact permissions our App had and provided the information to our customer.  Turned out the Third Party was wrong and accidentally got the permissions of another app.  Opps!

aapt dump permissions my.apk

AAPTDumpPermissions

Other Resources

 

Securing your HTML Form in ASP.NET MVC

By now, developers should really understand how to build a form and properly secure it.  But this still seems to allude some.  It’s rather embarrassing to fail security assessments for certain secuirty flaws that can be easily avoided.

In this blog, a refresher on the basics will be covered for securing your post as well as writing an extension to add to your MVC Infrastrucutre to be used by all of your team members.

It does not cover data validation.  I am really focusing on the form and the action of that form.  In addition, this is also from the perspective of a business web application that is only accessed via an authenticated user.

Let’s get started…

Poorly Secured Form and Action

Let’s take a simple Edit many developers write everyday and show the numerous flaws with this.  Here is the Razor View:

<h2>Edit</h2>
@using (Html.BeginForm())
{
     ...  Something here with a submit button...
}

Then the controller action would look something similar to this:

public ActionResult Edit(YourModel yourModel)
{
     if (ModelState.IsValid)
     {
          SaveYourModel(yourModel);
          return RedirectToAction("Index");
     }
     return View(client);
}

There are numerous concerns with the above form.

  1. When changing sensitive data, it should only happen via the proper HTTP Action.  So setup your ActionMethodSelectorAttributes properly.
  2. What about Cross-Site Request Forgery?  The above easily allows a hacker to submit data so prevent that as best as possible.
  3. Check the referrer.  Make sure the referrer is your site.
  4. Who is the originator?  Usually, this is the site that served the form.  So check the refferer.
  5. Next, who can change this data.  If only authenticated users, then which ones?

Crash course on ActionMethodSelectorAttribute

What is an ActionMethodSelectorAttribute?  It is an attribute on your controller’s action that is used to influence the selection of an action method.  This is easy to see the benefit of using them.

You can control the routing in MVC to actions decorated with HTTPGet.

[HttpGet()]
public ActionResult Edit(int id)
{
     YourModel yourModel = GetYourModel(id)
     return View(yourModel);
}

Or control the routing for inserting, updating and deleting of data using HTTPPost.

[HttpPost()]
public ActionResult Edit(YourModel yourModel)
{
     if (ModelState.IsValid)
     {
          SaveYourModel(yourModel);
          return RedirectToAction("Index");
     }
     return View(client);
}

When a user navigates to the Edit page for from a link, double clicking a row in a grid, or by any other means, that action should be called via a HTTPGet; therefore the first Action is called due to the HTTPGet attribute on that method.  Once on that page, the user then modifies the data and clicks a submit button in a form performing a POST thus calling the second Action decorated with HTTPPost.

For a complete list of action methods, click the following link for ActionMethodSelectorAttributes.

When do you want to use an ActionMethodSelectorAttribute?  In my opinion, pretty much on every Action in your controller.

Rules to live by:

1.  If you are selecting data to display in your Action method, then your Action should be decorated with the HTTPGet Attribute.

2.  If you are creating, updating or deleting data via your Action method, then your Action should be decorated with the HTTPPost Attribute.

Oh, and by the way, using HTTPPost helps prevent some attacks via CSRF (see next section).  Without that ActionMethodSelectorAttribute, it’s easy for a hacker to create links that a user can click and unknowingly modify their data.  

Without the HTTPPost a well crafted link (obviously depending on your model and your action etc…) can be used to update sensitive info.  Even worse, if your id is just an identity column in SQL Server and if you did not properly secure your form, a hacker could call this link over and over again for each identity id in your database, thus updating your data to what ever he wants.

http://localhost:2572/InsecureDOR/EditSubmit?ClientId=3&FirstName=Maverick&MiddleInitial=A&LastName=Smith

Pretty scary if your site really contains sensitive information like account information, employee data or critical business processes that if disrupted by a hacker causes serious damage to your company’s reputation.

So use HTTPPost and you will prevent the above hacks via get from working.

Cross-Site Request Forgery (CSRF)

Cross-Site Request Forgery (CSRF) is the #8 security flaw on the OWASP Top 10 for 2013. Follow the link for great information about CSRF.  For nitty grittey detail, read “Part 5: Cross-Site Request Forgery (CSRF), 1 Nov 2010 in Troy Hunt’s OWASP Top 10 book. It’s free. This will explain in great detail how an attacker can take advantage of your site. Luckily for us, we don’t have to implement the “Synchronizer Token Pattern” as Tony explains. Instead, we just need to add the following in our form:

@Html.AntiForgeryToken()

Then on the Controller’s Action, the following ActionFilter must be added.

[HttpPost()]
[ValidateAntiForgeryToken()]
public ActionResult Edit(YourModel yourModel)

This handles most CSRF attacks.

Note:  The user must accept cookies.  This only works with POST Requests.  It does not work with GET Requests.

Without a valideAntiForgeryToken, the server will threw exceptions like the following:

AntiForgeryException

AntiForgeryExceptionMissing

Can this be circumvented?  Why, yes….  But, a hacker has to actually get the AntiForgeryToken, then craft a POST using the correct form values.  Gettign the AntiForgeryToken is possible if your site  is vulnerable to XSS or your users are on older browser’s that allow cross-domain access.  Therefore, dropping support for older browsers in web applications is critical when the data is sensitve.  But that might be easier said than done.

The next step is to check the referrer.

Checking the Referrer

The next issue that I see with the above code is that the post could originate from another site.   There are expections, but for most business web application, a post originates from your site.

In order to check the referrer, you need to write a Attribute that inherits from AuthorizeAttribute:

public class IsPostedFromThisSiteAttribute : AuthorizeAttribute
{
  public override void OnAuthorization(AuthorizationContext filterContext)  {
    if (filterContext.HttpContext != null)
    {
      if (filterContext.HttpContext.Request.UrlReferrer == null)
        throw new System.Web.HttpException("IsPostedFromThisSite has invalid post - Missing UrlReferrer!"); 
       if (filterContext.HttpContext.Request.UrlReferrer.Host != filterContext.HttpContext.Request.Url.Host)
          throw new System.Web.HttpException("IsPostedFromThisSite has invalid post - Form was not submitted from this site!");
    }
    base.OnAuthorization(filterContext);
 }
}

Now, use this Attribute on your posts by applying it to the Action:

 [AcceptVerbs(HttpVerbs.Post)]
 [IsPostedFromThisSite]
 public ActionResult MyAction()

Checking the Origin

See the Origin on the following site:

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

Authenticated or Authorized

Next check the user to see if the user is authenticated and authorized to perform the action.

Finally

Build an HTML Extension to make this even easier to follow in your Business Application.  It is so easy to do…

Conclusion

These techniques help tremendously when securing your site, protecting your data and for passing security assessments.  So don’t forget to use them in all your forms and protect your reputation, your companies reputation and your bottom line.

More coming soon…

Security Assessment 101: Failed because of my cookies???

What really?  My security assessment failed because of my cookies.  But I only use a couple of cookies to store certain user preferences.  Those cookies are there only for user convince.  Guess what?  That third-party that ran the security assessment doesn’t care.  All they care about is that you have cookies and that you are not securing your cookies properly.

You can easily pass your security assessment by opening Web.Config and setting the http Only setting to true and also turning on SSL for your cookies (assuming you only have SSL);

<httpCookies httpOnlyCookies=”true” requireSSL=”true” />

But you do need to understand the ramifications of these settings.

If your JavaScript is accessing your cookies then setting httpOnlyCookies to true will break your code.  HttpOnly cookies help mitigate XSS and prevents cookies from being accessed vias client-side scripting.  Therefore, depending on how your code is implemented may mean you have some refactoring to do.

Finally, my sites normally run using SSL only.  Therefore, I set requireSSL to true.  This only allows the cookie to be sent back over a connection using SSL/TLS.  This is especially important with the Session Id cookie.  You certainly do not want that to be passed over HTTP since that could be stolen and used to hack your site.

 

 

 

 

Security Assessment 101: Failed due to Login Enumeration

Wait a second?  Really, I can’t tell my user that they locked out the account.  Yep!!!  For sites containing highly sensitive information like employee information, financial information, etc…  you will fail a security assessment because you are telling a hacker the account is locked out.

Why is that?

The concern is a hacker attempted to login with an account many times.  The hacker gets the “The account is locked out due to 5 failed attempts”.  Now the hacker knows he has a good account name.  One more piece of information that can help that hacker figure out how to get in.  Once the hacker gets a good user name, he can keep trying to hack the account each time it is reset.  Or, he might just use a little social engineering and call your help desk.  Using the URL and account name, the hacker might be able to convince your help desk to change the password without even verifying other information on the account.  Then the hacker has a good account with a good password.  Now your hacked but don’t even know it until it is way too late.  It could be weeks before the real user tries to login and figures out he can’t and then calls the help desk.  By then the hacker could have downloaded anything that user has access to, created another user account, etc…

It is best to avoid showing messages like these to the user:

  • The password is invalid.
  • The account is locked out.

Best Practice

Always show the same response for a failed login:

  • The username and password is invalid.  Please try again.

When a user calls the help desk for a password reset:

  • The help desk must verify information about the user.
  • The help desk should be able to see past history and be able to ask the user when they successfully logged in last time.
  • The help desk should be able to see as much information about any failed login attempts like IP Address, number of failed attempts, etc…  If the failed attempts are out of China but your users are only in a few locations in the United States, well you might have a problem…
  • The help desk should reset the password and send a password reset email to the email account on file.

So solving this problem is not just about coding a secure login page but also letting your help desk understand social engineering and hacking.

 

KendoUI: Understanding ToDataSourceResult

Using server filtering is rather easy with Kendo UI MVC, unless your new to it.  Then that first couple hours is pretty frustrating untill you find the right article, information and samples.  I have very few gripes with Telerik and Kendo UI but they do have a problem with the Kendo UI Demos.  They do not include enough sample code from controllers and web services.  So hopefully this will help out those newbies to KendoUI.

When would I use this?

Server-side Filtering, Paging, and Sorting with the Grid or ListView.

How to use it?

When would I use this?  Server-side Filtering with the Grid or ListView.

First thing you want to do is add the following the following using statement to you Controller or API Controller:

using Kendo.Mvc.Extensions;

Now, you can easily take advantage of ToDataSourceResult extension method to convert any IQueryable or IEnumerable to a DataSourceResult object.  It will help you page, filter, sort or group your data using the information provided by the DataSourceRequestObject.

Your AJAX action will take one parameter:  DataSourceRequest.

public ActionResult GetAllOrders([DataSourceRequest] DataSourceRequest request)

Now in the method, you just call ToDataSourceResult on your IQueryable or IEnumerator.  Pretty simple, although you have to be careful when dealing with large volumes of data o make sure your implementation does not return all the data before applying filter, sorting, and paging.

How is ToDataSourceResult being implemented under the hood by Telerik?  C# Extension Methods.  If you need a refresher, check it out here:

If you want to see the implementation, then use JustDecompile and run it against Kendo.MVC.dll.

Which Kendo UI Widgets

This is meant to be used with the following controls:

  • Grid
  • ListView

Other controls like ComboBox and AutoComplete expect just a simple array and will not work with DataSourceResult.

Does this only work with a ORM?

No, it does not.  Note:  Any IQueryable or IEnumerable so LINQ, List, Dictionary, etc…

Let’s dive into a simple example

In my sample, I have a Domain POCO Class called Order.

public class Order
{
 public int Id { get; set; }
 public string LastName { get; set; }

 public decimal TotalAmount { get; set; }

 public decimal TotalAmountUsd { get; set; }

 public string OrderCurrencyCode { get; set; }

 public string OrderCurrencyCultureCode { get; set; }

 public DateTime OrderDate { get; set; }
}

Then I have a Domain Class that contains a list of Orders.  This has data stubbed out for now.

public class Orders
{
   private readonly List orders = new List();
   private int nextId = -1;

   public Orders()
   {
     Add(new Order() { LastName = "Federer", TotalAmount = 1023.23m, TotalAmountUsd = 400.23m, OrderCurrencyCode = "SEK", OrderCurrencyCultureCode = "sv-SE", OrderDate = DateTime.UtcNow.AddDays(-1) });
     // Add lots of data here........
     Add(new Order() { LastName = "Aikemo", TotalAmount = 1023.23m, TotalAmountUsd = 400.23m, OrderCurrencyCode = "JPY", OrderCurrencyCultureCode = "ja-JP", OrderDate = DateTime.UtcNow.AddDays(-8) });
 }

 public Order Add(Order item)
 {
   if (item == null)
   {
     throw new ArgumentNullException("item");
   }
   item.Id = nextId++;
   orders.Add(item);
   return item;
 }

 public List GetAll()
 {
  return orders;
 }
}

Then, I have a ViewModel which looks just like my Order class.
public class OrderViewModel
{
 public int Id { get; set; }
 public string LastName { get; set; }

 public decimal TotalAmount { get; set; }

 public decimal TotalAmountUsd { get; set; }

 public string OrderCurrencyCode { get; set; }

 public string OrderCurrencyCultureCode { get; set; }

 public DateTime OrderDate { get; set; }
}

In the controller, I have the following Action (Note:  My controller is importing  Kendo.Mvc.Extensions):

[HttpPost]
public ActionResult GetAllOrders([DataSourceRequest] DataSourceRequest request)
 {
   Orders orders = new Orders();
   List orderList = orders.GetAll();
   DataSourceResult result = orderList.ToDataSourceResult(request, 
     order => new OrderViewModel 
     { 
       Id = order.Id, LastName = order.LastName,
       OrderCurrencyCode = order.OrderCurrencyCode, OrderCurrencyCultureCode = order.OrderCurrencyCultureCode,
       TotalAmount = order.TotalAmount, TotalAmountUsd = order.TotalAmountUsd,
       OrderDate = order.OrderDate
     }
   );

   return Json(result);
 }

The call to ToDataSourceResult is taking the request information and using that to filter, sort, etc the results and transform them into the ViewModel.  Pretty simple and straightforward.

Finally, in your Razor view you can call your AJAX method which will easily page, filter, sort, etc…

@(Html.Kendo().Grid()
 .Name("grid")
 .HtmlAttributes(new { style = "width:700px" })
 .Columns(columns =>
 {
 columns.Bound(p => p.Id).Title("Order Id");
 columns.Bound(p => p.LastName).Title("Customer");
 columns.Bound(p => p.TotalAmount).Title("Total Amount");
 columns.Bound(p => p.TotalAmountUsd).Title("Total Amount (USD)");
 columns.Bound(p => p.OrderDate).Title("Ordered On");
 })
 .Pageable()
 .Sortable()
 .Scrollable()
 .Filterable()
 .DataSource(dataSource => dataSource
 .Ajax()
 .PageSize(5)
 .Read(read => read.Action("GetAllOrders", "Orders"))
 )
)

Now the user can sort, page, filter, …

Grid Filtering

Grid Filtering

KendoUI Resources

Here are a couple helpful resources from Telerik:

 

Conclusion

This is pretty simple once you get the basics down so good luck coding up your solutions with it.

KendoUI: Formatting Dates, Numbers, Currency and Custom Formats

Ever need to format text in JavaScript?  Ok, dumb question.  Everyone has needed that functionality.  Well, if you use KendoUI, Telerik provides a pretty awesome framework for this.  There is a toString method which is documented here.

This method takes three parameters:

  • value –> the Date or Number to be formatted.
  • format –> string to format.
    • n –>  Format as a Number.  If you include a number after the n, then this will denote the number of decimal places.
    • p –> Format as a Percent
    • c –> format as the Currency including the symbol
    • date format like ‘yyyy/MM/dd’
    • Custom Formatter like ’00##’
  • culture –> the name of the culture which should be used to format the value.  If this parameter is not supplied, then the default culture is used

Now, this is pretty AWESOME.  Lets say you need to display a value in multiple currencies and formatted for each currency.

In your page, you need to register each KendoUI culture script.  For this example, let’s reference the following:

<script src="http://cdn.kendostatic.com/2013.2.716/js/cultures/kendo.culture.de-DE.min.js"></script>
<script src="http://cdn.kendostatic.com/2013.2.716/js/cultures/kendo.culture.sv-SE.min.js"></script>
<script src="http://cdn.kendostatic.com/2013.2.716/js/cultures/kendo.culture.en-US.min.js"></script>

You also need a reference to kendo.core.js.

Now, that you are referencing the cultures you need,  it is pretty easy to format your dates and string in JavaScript.

For instance:

kendo.toString(1234.23, ‘c’, ‘de-DE’)  –>   1.234,23 €

kendo.toString(1234.23, ‘c’, ‘sv-SE’)  –> 1.234,23 kr

kendo.toString(1234.23, ‘c’, ‘en-US’)  –> $1,234.23

This is pretty slick.  You can format the currency based on a culture which comes in very handy in some business application where you might need to display multiple currencies on the same page.

Other places to use this:

  • In a ClientTemplate on a column on a Grid so you could format one column for Swiss Franc then have another column for US Dollars.
  • For formatting date time when displaying multiple dates for more than one culture
  • Allowing the user to pick a culture and dynamically update the formats of the numbers, dates, etc without reposting the page.

 

 

 

 

 

Security Assessment 101: Skip HTTP and just use HTTPS

So you built this awesome business web app.  You sold it to your customer and it’s now in production.  You’re using SSL which is even configured for best practices.  See my previous post on securing SSL.  But what happens when a user goes to your web application.  It probably redirects them to HTTPS so the user can login over SSL.

Why do that???

That is the question to ask yourself.  Why redirect users from HTTP to HTTPS to login.  Why not ALWAYS use SSL???  I really do not believe you need HTTP or Port 80 turned on at all for business web applications.  Here are my assumptions with Business Web Application:

  • Most interactions with your site is behind the login page.  By most, I really mean like 99%.
  • The data is sensitive, company proprietary, etc…
  • You have employee information, financial information, etc…

So in this scenario, there is no real reason to have HTTP bindings setup in IIS for your site.  Turn port 80 off on the firewall and only allow Port 443.  Don’t even give the hacker a chance to see the traffic over HTTP or an avenue to hack your server over port 80.

But what about the customer???

They won’t know to use HTTPS…  For me this is pretty easy answer.  When sending the welcome package to your customer, explain to them why you did this and tell them the URL is only accessible over HTTPS.  I have been doing this for years and yes we have had a few calls to the help desk.  But VERY, VERY few calls.