Websites often sends emails to registered users with inivitations to make certain actions. Sometimes we need to send user an URL to the registered area of site. The standart approach is to send a link to the page, users follow it, ASP.NET regirects him to login page where he must enter his credentions to continue. In some applications users receives an URL wich automatically logs user in (for example in LinkedIn). This article is about an ASP.NET module wich automatically logs users in case of special URL signature found in URL.

The approach

How to sign the URL and verify, that the signature is given to the certain user? My approach is to set 2 url params: with user name and with the signature based on machine validation key of web application. If we add the signature to the url string with the user name we can be sure this user has rights to see this page. Of couse this is not 100% secure method but, because the URL can be stolled or sniffered but in many cases such a security is acceptable. The machine key verification key is rather strong and secure for the purpose. The solution in the form of HttpModule is reusable. All we have to do is to handle AuthenticateRequest event and authenticate user in it.

The code

Full source of UrlAutoLogInModule can be downloaded here: UrlAutoLogInModule.zip (2.19 kb)

In the code a HttpModule created

    public class UrlAutoLogInModule : IHttpModule

which simple handles AuthenticateRequest event

        public void Init(HttpApplication context)

        {

            // Handle the authenticate request event

            context.AuthenticateRequest += new EventHandler(AuthenticateRequest);

        }

The module search for the get params with user name and signature

        protected void AuthenticateRequest(object sender, EventArgs e)

        {

            HttpApplication application = (HttpApplication) sender;

            string authToken = application.Request.QueryString[TokenParam];

            string userName = application.Request.QueryString[UserNameParam];

 

            if (string.IsNullOrEmpty(authToken) || string.IsNullOrEmpty(userName))

                return;

Next step is check if such a user is not locked or disabled to prevent locked users log in into website. The user retrievment will also updates the last login time in the database. At this point an assumption that the Membership is used to implement website security.

                MembershipUser muser = Membership.GetUser(userName, true);

                if (!muser.IsApproved || muser.IsLockedOut)

                {

                    return;

                }

The futher logic is very simple. We have to compute hash for the request URL and chek if it equals to the signature in the get params. If verification succeded we add an authentication cookie for the user and initialize System.Threading.Thread.CurrentPrincipal and System.Web.HttpContext.Current.User. You can add some custom logic here if you need to use other than GenericPrincipal implementation of IPrincipal interface. To prevent hackers from finding verification key it will be nice to lock user due to membership settings after several failed login attempts. To do this it is possible to call Membership.VerifyPassword with wrong password. This will update Membership tables and log failed login attempt.

                string currentHash = ComputeHash(GetFullRawUrl(application.Request));

                bool approve = currentHash.Equals(authToken);

                if (approve)

                {

                    // Add auth cookie

                    FormsAuthentication.SetAuthCookie(userName, false);

                    IPrincipal user = new GenericPrincipal(

                        new GenericIdentity(userName), null

                        );

                    System.Threading.Thread.CurrentPrincipal = user;

                    HttpContext.Current.User = user;

                }

                else

                {

                    Membership.ValidateUser(userName, "invalid password");

                }

There is several odds in ComputeHash method wich I want to describe. First it is removes the signature param from the url string because it is impossible to sign URL with signature. Second it uses Request.RawUrl instead of other request properties because I am using UrlRewriter.NET and in that property ASP.NET stores not rewrited URL from user's browser. And finally it gets verification key from machineKey config section and comutes hash of the URL string. The signature algo is same as in MachineKeySection.HasData method wich unfotunetly is declared as internal (I'm wondering why).

How it works

The module needs a registration in the web.config file httpModules section

      <httpModules>

        <add name="UrlAutoLogInModule" type="Yesnobox.Modules.UrlAutoLogInModule, YourAssembly" /> 

If you want to send user a signed URL, you have to call static method wich adds signature and user name to the URL.

emailArgs.TestUrl = Yesnobox.Modules.UrlAutoLogInModule.SignUrl(emailArgs.TestUrl, ud.UserName); 

 

When user follows this url and his signature is valid he automatically logs in and see page without redirecting to the login page. If the signature is wrong and the page can be seen only by logged in user the user will be redirected to the login page by internal ASP.NET logic.

If you care about security much it is possible to add an expiretion date for the signature by simply add expiration date to one of URL param before adding the signature hash.

I created a simple example wich uses the module.  AutoLoginExample.zip (11.12 kb)

Here there is auto login link on the page. If the user followes it he gets authorised. Note that there is no logic to login user in the page onbehind or at any place of the site. There is only a signed url on the page that is doing automatical login.

Submit this story to DotNetKicks

Posted in: ASP.NET  Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Open Flash Chart .NET Library

Open Flash Chart is the chart component I chose to use at Yesnobox.com. I liked it at first sight because it looks really awesome at the client browsers and doesn’t require generating chart images on server.  It was pity, but at the time I decided to use it in Nov 2007, there were no .NET API to use it. Thanks to many examples at the Open Flash Chart website and API written for other programming languages it seemed that it will be simple enough to write another one for .NET. So I decided to write my own library to build data strings and create handy asp.net web control to place on a page.

Online Demo

Before going in details of how it is works you can test the chart and properties at the demo page.

How to start?

To start using Open Flash Chart you have to download the project and link the dll or the source with you current application.

Download Open Flash Chart object and copy swf file to the ~/Flash/ open-flash-chart.swf on your website. (You can set another location in the FlashUrl property of OpenFlashChart web control)

In order to display chart data you have to register small HttpHandler from library under the <system.web><httpHandlers> node in web.config:

</configuration>

<system.web>

  <httpHandlers>

    <add verb="*" path="of.axd" type="OpenFlashChartLib.OpenFlashChartControlHandler, OpenFlashChartLib" />

  </httpHandlers>

</system.web>

</configuration>

Add Register directive before place the control on the page 

<ofc:OpenFlashChart runat="server" ID="ofcTest" Height="350" Width="500" OnDrawChart="ofcTest_DrawChart" />

Call BuildChart()control’s method to rebuild chart data:

protected void Page_Load(object sender, EventArgs e)

{

    ofcTest.BuildChart();

Define the DrawChart handler in the page code behind. At this event you have to create Graph object, initialize it properties and set diagram values.

protected void ofcTest_DrawChart(object sender, OpenFlashChartLib.DrawChartEventArgs e)

{

    // Create graph object and initialize its display preferences

    Graph graph = new Graph();

    e.Graph = graph;

    graph.Title.Text = "";

    graph.Title.Style.Font.Size = new FontUnit(26, UnitType.Pixel);

    graph.XLabelStyle.Color = "#9933CC";

    graph.XLabelStyle.Size = 10;

    graph.YLegend.Text = "Votes";

    graph.YLegend.Size = 12;

    graph.YLegend.Color = "0x736AFF";

    graph.XLegend.Text = "Your question";

    graph.XLegend.Size = 14;

    graph.XLegend.Color = "0x736AFF";

    graph.YTicks.Size = 2;

 

    // Create new data renderer

    DataRenderer<int> ret = new DataRenderer<int>();

    // Create a chart type wich you want to display

    // as GraphTypeRenderer

    string grColor = "E61C1C";

    int alpha = 60;

    string legentText = "Legend";

    int legentTextHeight = 12;

    ret.GraphTypeRenderer = new BarGraphType(alpha, "#" + grColor, legentText, legentTextHeight);

 

    // Initialize XLables for the data set

    graph.XLabels.Values.Add("Answer 1");

    graph.XLabels.Values.Add("Answer 2");

    graph.XLabels.Values.Add("Answer 3");

    graph.XLabels.Values.Add("Answer 4");

    graph.XLabels.Values.Add("Answer 5");

    // Add Values to display

    ret.Values.Add(3);

    ret.Values.Add(3);

    ret.Values.Add(7);

    ret.Values.Add(12);

    ret.Values.Add(1);

    // Add data rendere to the Graph.Values collection

    graph.Values.Add(ret);

 

    graph.Attributes.Add(new KeyValuePair(Tokens.BackgroundColor, "#FFFFFF"));

}

That’s it. Press F5 and see results:


The flash object is automatically embedded by SWFObject script which is linked to the page from library resources.

If the chart is not pie chart we can add other data sets to display as it is done at http://teethgrinder.co.uk/open-flash-chart/gallery-bar-2.php page. All we have to do is to create another DataRenderer object, init it in the GraphTypeRenderer and add values.

To create 2 data sets on one chart use the following code

using System;

using System.Web.UI.WebControls;

using OpenFlashChartLib;

 

namespace WebDemo

{

    public partial class _Default : System.Web.UI.Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            ofcTest.BuildChart();

        }

 

        protected void ofcTest_DrawChart(object sender, OpenFlashChartLib.DrawChartEventArgs e)

        {

            // Create graph object and initialize its display preferences

            Graph graph = new Graph();

            e.Graph = graph;

            graph.Title.Text = "";

            graph.Title.Style.Font.Size = new FontUnit(26, UnitType.Pixel);

            graph.XLabelStyle.Color = "#9933CC";

            graph.XLabelStyle.Size = 10;

            graph.YLegend.Text = "Votes";

            graph.YLegend.Size = 12;

            graph.YLegend.Color = "0x736AFF";

            graph.XLegend.Text = "Your question";

            graph.XLegend.Size = 14;

            graph.XLegend.Color = "0x736AFF";

            graph.YTicks.Size = 2;

 

            // Create new data renderer

            DataRenderer<int> ret = new DataRenderer<int>();

            // Create a chart type wich you want to display

            // as GraphTypeRenderer

            string grColor = "E61C1C";

            int alpha = 60;

            string legentText = "Legend";

            int legentTextHeight = 12;

            ret.GraphTypeRenderer = new BarGraphType(alpha, "#" + grColor, legentText, legentTextHeight);

            // Initialize XLables for the data set

            graph.XLabels.Values.Add("Answer 1");

            graph.XLabels.Values.Add("Answer 2");

            graph.XLabels.Values.Add("Answer 3");

            graph.XLabels.Values.Add("Answer 4");

            graph.XLabels.Values.Add("Answer 5");

            // Add Values to display

            ret.Values.Add(3);

            ret.Values.Add(3);

            ret.Values.Add(7);

            ret.Values.Add(12);

            ret.Values.Add(1);

            // Add rendere to Values collection

            graph.Values.Add(ret);

            graph.YMax = 12;

 

            // if this is not pie chart create another renderer

            if (!graph.PieChart())

            {

                DataRenderer<int> ret2 = new DataRenderer<int>();

                BarGraphType renderer = new GlassGraphType(alpha, "#005231", "", null);

                renderer.Color = "#005231";

                renderer.OulineColor = "#005231";

                ret2.GraphTypeRenderer = renderer;

                ret2.Values.Add(5);

                ret2.Values.Add(12);

                ret2.Values.Add(1);

                ret2.Values.Add(0);

                ret2.Values.Add(8);

                graph.Values.Add(ret2);

            }

            graph.YMax = 12;

            graph.Attributes.Add(new KeyValuePair(Tokens.BackgroundColor, "#FFFFFF"));

 

        }

    }

}

We will get the following pretty chart:


The creation of pie chart does not differ much. The only thing that changes is the is type of GraphTypeRenderer property of the DataRenderer. Use the following code to define Pie chart in the DrawChart event:

// Create new data renderer

DataRenderer<int> ret = new DataRenderer<int>();

// Create a chart type wich you want to display

// as GraphTypeRenderer

string grColor = "E61C1C";

PieGraphType pie = new PieGraphType();

pie.Colors = new List<string>(new string[] { "E61C1C", "462CDE", "3F9735" });

pie.Alpha = 60;

ret.GraphTypeRenderer = pie;

// Initialize XLables for the data set

graph.XLabels.Values.Add("Answer 1");

graph.XLabels.Values.Add("Answer 2");

graph.XLabels.Values.Add("Answer 3");

graph.XLabels.Values.Add("Answer 4");

graph.XLabels.Values.Add("Answer 5");

// Add Values to display

ret.Values.Add(3);

ret.Values.Add(3);

ret.Values.Add(7);

ret.Values.Add(12);

ret.Values.Add(1);

// Add data rendere to the Graph.Values collection

graph.Values.Add(ret);

The result:


Supported features

Now the API supports following chart types:

Chart types:

  • Bar chart
  • Glass chart
  • 3D chart
  • Fade chart
  • Sketch chart
  • Pie chart
  • Line chart (dot line, hollow line)

Ajax panel is also supported. To find out how to use the control there see demo web example.

Download

OpenFlashChartLib project and WebDemo available at CodePlex.

I am not first …

At the moment am writing this article there are two other similar api released. You can find them at Dot NET APIs page of Open Flash Chart Page. The functionality is almost the same except some features I coded here

  • Automatic SWFObject link to the page. The SWFObject is compiled to dll resources and the script include generated automatically.
  • JQuery flash registration. If you are using JQuery it is better to use JQuery flash plug in to embed flash object in the page. It can be set by EmbedScriptType property of OpenFlashChart control.
  • No need to create separate data page or handler you just handle DrawChart event. You can use generic data handler registered in web.config and chart data will be cached between postbacks. Or you can switch this feature off by setting SpecificDataHandler control’s property to any data renderer url.
Related posts: Open Flash Chart 2
Submit this story to DotNetKicks

Posted in: ASP.NET , Controls  Tags:

Currently rated 4.0 by 5 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5