Click here to Skip to main content
Click here to Skip to main content
Articles » Web Development » ASP.NET » Howto » Downloads
 
Add your own
alternative version

ASP.NET - Forms authentication user impersonation

, 13 Nov 2009 CPOL
An ASP.NET class and accompanying control for providing application support users with a 'login as user ...' function the right way.
FormsAuthenticationUserImpersonation_Bin.zip
FormsAuthenticationUserImpersonation.dll
FormsAuthenticationUserImpersonation_Example.zip
App_Code
App_Data
Bin
FormsAuthenticationUserImpersonation.dll
Private
FormsAuthenticationUserImpersonation_Src.zip
FormsAuthenticationUserImpersonation
bin
Release
FormsAuthenticationUserImpersonation.dll
Properties
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace System.Web.Security
{

    /// <summary>
    /// The UserImpersonation class wraps the logic required to support user impersonation.
    /// </summary>
    public class UserImpersonation
    {

        /// <summary>
        /// Starts user impersonation by having the current user being logged in as the user which's username is specified.
        /// </summary>
        /// <param name="userName"></param>
        public static void ImpersonateUser(string userName)
        {
            ImpersonateUser(userName, string.Empty);
        }

        /// <summary>
        /// Starts user impersonation by having the current user being logged in as the user which's username is specified.
        /// When user impersonation is reverted, the user will be redirected to the location passed in returnUrl.
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="returnUrl"></param>
        public static void ImpersonateUser(string userName, string returnUrl)
        {

            // Declare variables
            HttpContext context;
            FormsAuthenticationTicket authTicket;
            HttpCookie authCookie;
            string strSerializedData;

            // Check if a HttpContext is available and a user is currently logged in.
            context = HttpContext.Current;
            if (context == null)
                throw new InvalidOperationException("No HttpContext available. Unable to impersonate user.");
            if (context.User.Identity == null)
                throw new InvalidOperationException("No user is currently authenticated. Unable to impersonate user.");
            if (!context.User.Identity.IsAuthenticated)
                throw new InvalidOperationException("No user is currently authenticated. Unable to impersonate user.");

            // Store impersonation data in authentication ticket.
            strSerializedData = Serialize(context.User.Identity.Name, returnUrl);
            authCookie = FormsAuthentication.GetAuthCookie(userName, false);
            authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            authTicket = new FormsAuthenticationTicket(authTicket.Version, authTicket.Name, authTicket.IssueDate, authTicket.Expiration,
                authTicket.IsPersistent, strSerializedData, authTicket.CookiePath);
            authCookie.Value = FormsAuthentication.Encrypt(authTicket);
            context.Response.Cookies.Add(authCookie);
        }

        /// <summary>
        /// Reverts the user impersonation.
        /// </summary>
        public static void Deimpersonate()
        {
            Deimpersonate(true);
        }

        /// <summary>
        /// Reverts the user impersonation, optionally ignoring the previously set redirect url.
        /// </summary>
        /// <param name="redirect"></param>
        public static void Deimpersonate(bool redirect)
        {

            // Declare variables
            HttpContext context;
            FormsIdentity formsIdentity;
            string strUserName, strReturnUrl;

            // Check if a HttpContext is available and a user is currently logged in.
            context = HttpContext.Current;
            if (context == null)
                throw new InvalidOperationException("No HttpContext available. Unable to complete operation.");

            // Verify that a user is currently logged in.
            if (context.User.Identity == null)
                return;
            if (!context.User.Identity.IsAuthenticated)
                return;

            // Get data from auth ticket
            formsIdentity = (FormsIdentity)context.User.Identity;
            if (string.IsNullOrEmpty(formsIdentity.Ticket.UserData))
                return;
            if (!Deserialize(formsIdentity.Ticket.UserData, out strUserName, out strReturnUrl))
                return;

            // Set new auth cookie and redirect user if asked to do so.
            FormsAuthentication.SetAuthCookie(strUserName, false);
            if(!string.IsNullOrEmpty(strReturnUrl) && redirect)
                context.Response.Redirect(strReturnUrl);
        }

        /// <summary>
        /// Gets the user name of the user orgininally logged in as before impersonation started.
        /// </summary>
        public static string PrevUserName
        {
            get
            {

                // Declare variables
                HttpContext context;
                FormsIdentity formsIdentity;
                string strUserName, strReturnUrl;

                // Check if a HttpContext is available and a user is currently logged in.
                context = HttpContext.Current;
                if (context == null)
                    throw new InvalidOperationException("No HttpContext available. Unable to complete operation.");

                // Verify that a user is currently logged in.
                if (context.User.Identity == null)
                    return string.Empty;
                if (!context.User.Identity.IsAuthenticated)
                    return string.Empty;

                // Get data from auth ticket
                formsIdentity = (FormsIdentity)context.User.Identity;
                if (string.IsNullOrEmpty(formsIdentity.Ticket.UserData))
                    return string.Empty;
                if (!Deserialize(formsIdentity.Ticket.UserData, out strUserName, out strReturnUrl))
                    return string.Empty;

                return strUserName;
            }
        }

        /// <summary>
        /// Returns true if the current user is being impersonated.
        /// </summary>
        public static bool IsImpersonating
        {
            get
            {

                // Declare variables
                HttpContext context;
                FormsIdentity  formsIdentity;
                string strUserName, strReturnUrl;

                // Check if a HttpContext is available and a user is currently logged in.
                context = HttpContext.Current;
                if (context == null)
                    throw new InvalidOperationException("No HttpContext available. Unable to complete operation.");

                // Verify that a user is currently logged in.
                if (context.User.Identity == null)
                    return false;
                if (!context.User.Identity.IsAuthenticated)
                    return false;

                // Get data from auth ticket
                formsIdentity = (FormsIdentity)context.User.Identity;
                if (string.IsNullOrEmpty(formsIdentity.Ticket.UserData))
                    return false;
                return Deserialize(formsIdentity.Ticket.UserData, out strUserName, out strReturnUrl);
            }
        }

        /// <summary>
        /// Combines the username and return url in a single string seperating the values by a :-character.
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        private static string Serialize(string userName, string returnUrl)
        {
            return string.Format("{0}:{1}", userName.Replace(":", "::"), returnUrl.Replace(":", "::"));
        }

        /// <summary>
        /// Reconstructs the username and return url from a serialized state.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="userName"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        private static bool Deserialize(string data, out string userName, out string returnUrl)
        {

            Regex splitRegex;
            string[] pieces;

            // Set default return values
            userName = null;
            returnUrl = null;

            // Attempt to deserialize data
            splitRegex = new Regex("(?<!:):(?!:)");
            pieces = splitRegex.Split(data);
            if (pieces.Length != 2)
                return false;

            // Set the return values
            userName = pieces[0].Replace("::", ":");
            returnUrl = pieces[1].Replace("::", ":");
            return true;
        }
    }

    
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Christ Akkermans

Netherlands Netherlands
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 13 Nov 2009
Article Copyright 2009 by Christ Akkermans
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid