Re: Error casting User.Identity to WindowsIdentity

From: Razak (razak_at_mmsc.com.my)
Date: 07/27/04


Date: Tue, 27 Jul 2004 13:18:10 +0800

Sorry for the lack of information. What I did in my code is like from an
aspx page Save button clck event, I called a shared method AddNew of a
class, declared in PhotoGalleryUtility.vb. In that method, I did the saving
of gallery data into an SQL db. Then I call a private method in the same
class called CreateDir. There is where I put the code to create a folder for
the newly added gallery data. The folder is created inside
webroot/images/galleries/{0} where {0} is the galleryID in the database. I
do not need to do anything in terms of security here. The folder will be
created at the specified location on the server just fine.

Ok, that's the first part. My app also allows gallery deletion, which,
deletes gallery entry in the database, and also the corresponding folder in
the said location.

>From the aspx page listing all available galleries, and every each of them
have their 'X' image button to initiate deletion process. Clicking this
image, will trigger the javascript 'yes/no' confirmation alert box, then
calls the datagrid_ItemCommand event. From there, i call Delete method in
the same class as above. (PhotoGalleryUtility.vb). In that method, I delete
the entry from the db, proceed to deleting the corresponding folder in the
location. The delete code is actually in different private method in the
class (DeleteDir), so here is the method:-

    ' *********************************************************************
    ' DeleteDir Methods (private)
    ' *********************************************************************
    '
    ' Create directory in images folder.
    '
    ' *********************************************************************
    Private Shared Sub DeleteDir(ByVal gallery_id As Integer)
        ' Specify the directory you want to manipulate.
        Dim path As String =
HttpContext.Current.Server.MapPath(String.Format("../{0}/{1}",
ABGGlobals.GalleriesPath, gallery_id))

        ' Determine whether the directory exists.
        If Directory.Exists(path) Then
            Dim imp As New ImpersonateUser
            If imp.LogSelf() Then
                ' Delete the directory.
                Directory.Delete(path, True)
                imp.LogOff()
            Else
                Throw New Exception("Impersonation failed!")
            End If
        Else
            Throw New Exception("Directory does not exist!")
        End If
    End Sub
    '*********************************************************************
OK, here's my ImpersonateUser class, defined in ImpersonateUser.vb:-

'*********************************************************************
Imports System.Security.Principal
Imports System.Runtime.InteropServices

Public Class ImpersonateUser
    Private _impersonationContext As WindowsImpersonationContext
    Private Declare Function LogonUserA Lib "advapi32.dll" (ByVal
lpszUsername As String, _ ......................
    Private Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
.....................
    Private Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
    Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal
handle As IntPtr) As Long

    ' *********************************************************************
    ' LogSelf Methods
    ' *********************************************************************
    '
    ' Log current user.
    '
    ' *********************************************************************
    Public Function LogSelf() As Boolean
        Dim currentWindowsIdentity As WindowsIdentity

        HttpContext.Current.Session("name") = ""
        HttpContext.Current.Session("test") = ""
        currentWindowsIdentity = CType(HttpContext.Current.User.Identity,
WindowsIdentity) <============== The problematic line!
        HttpContext.Current.Session("name") = currentWindowsIdentity.Name()
        HttpContext.Current.Session("test") = "Session OK"
        If currentWindowsIdentity.IsAuthenticated Then
            _impersonationContext = currentWindowsIdentity.Impersonate()
            Return True
        Else
            Return False
        End If
    End Function

    ' *********************************************************************
    ' LogOff Methods
    ' *********************************************************************
    '
    ' Revert impersonation.
    '
    ' *********************************************************************
    Public Sub LogOff()
        _impersonationContext.Undo()
    End Sub
End Class
'*********************************************************************

 I have tried passing the identity object from code behind of the aspx page
to the impersonateuser class so that i can skip the 'currentWindowsIdentity
= CType(HttpContext.Current.User.Identity, WindowsIdentity)' line all
together in the class. But in code behind file, the casting in line X :

   '*********************************************************************
    Private Sub dgrdGalleries_ItemCommand(ByVal source As Object, ByVal e As
System.Web.UI.WebControls.DataGridCommandEventArgs) Handles
dgrdGalleries.ItemCommand
        Dim galleryID As Integer =
Fix(dgrdGalleries.DataKeys(e.Item.ItemIndex))
        Select Case e.CommandName
            Case "Delete"
                lblError.Text = PhotoGalleryUtility.Delete(galleryID,
CType(HttpContext.Current.User.Identity,
System.Security.Principal.WindowsIdentity)) <=== X!!
            Case "Up"
                PhotoGalleryUtility.MoveUp(galleryID)
            Case "Down"
                PhotoGalleryUtility.MoveDown(galleryID)
        End Select
    End Sub
    '*********************************************************************

keep producing the error:-

    Server Error in '/' Application.
    Specified cast is not valid.
    Description: An unhandled exception occurred during the execution of the
current web request. Please review the stack trace for more information
about the error and where it originated in the code.

Exception Details: System.InvalidCastException: Specified cast is not valid.

This a lengthy post, and I'm tired of this casting error and thinking of
giving up this impersonation method... prefer the impersonate as specified
user/pwd/domain method anyway...

----------------------------------------------------------------------------
---- -----------------------------------------------------------------------
---------
"Shan Plourde" <------@---.net> wrote in message
news:%skNc.1235283$Ar.942097@twister01.bloor.is.net.cable.rogers.com...
> Could it be related to where you are placing this in both the .aspx and
> code behind? As more of an apples to apples comparison, did you code
> this within a Page_Load() event handler first in your aspx page, then in
> your code behind? Or, did you place them in different methods
> altogether? If so, first start by ensuring that you have that apples to
> apples comparison.
>
> Otherwise, it is likely that the current user property is not yet set by
> the .NET presentation framework depending on where you are trying to
> access it from within your code behind. That would be my first guess.
> The MSDN may have some tips on when this property is set. You may want
> to look up HttpApplication and see if your code behind logic is getting
> accessed after the appropriate HttpApplication AuthenticateRequest event
> has been fired (or AuthorizeRequest)...
>
> Also, ensure that you have System.Web in your using list in your code
> behind. Hopefully that helps
>
> Shan Plourde
>
> Razak wrote:
>
> >Dale,
> >
> >Maybe we are a bit off from the main question of my post which was why
the
> >statement:-
> >
> > currentWindowsIdentity = CType(HttpContext.Current.User.Identity,
> >System.Security.Principal.WindowsIdentity)
> >
> >in code-behind produces error while
> >
> > currentWindowsIdentity = CType(User.Identity,
> >System.Security.Principal.WindowsIdentity)
> >
> >in aspx page does not.
> >
>
>---------------------------------------------------------------------------
-
>
>---- ----------------------------------------------------------------------
-
> >---------
> >"Dale" <daleDeletepres@msndotcomNot.Net> wrote in message
> >news:erMFM4ZcEHA.4092@TK2MSFTNGP11.phx.gbl...
> >
> >
> >>Duh, I don't know what I was thinking.
> >>
> >>IsInRole is actually a method of the User object - well, actually the
> >>IPrincipal object upon which the User is based.
> >>
> >>Dale
> >>
> >>"Razak" <razak@mmsc.com.my> wrote in message
> >>news:OwUT5cYcEHA.3864@TK2MSFTNGP10.phx.gbl...
> >>
> >>
> >>>Thanks for the tip. I'll try it tomorrow and see how it goes.
> >>>
> >>>
> >>>
>
>>--------------------------------------------------------------------------
> >>--
> >>
>
>>---- ---------------------------------------------------------------------
> >>--
> >>
> >>
> >>>---------
> >>>"Dale" <daleDeletepres@msndotcomNot.Net> wrote in message
> >>>news:ew4F7QYcEHA.2812@tk2msftngp13.phx.gbl...
> >>>
> >>>
> >>>>Remember that by impersonating a specific user, you have to include
> >>>>
> >>>>
> >>>username
> >>>
> >>>
> >>>>and password your code. This is not a good idea except in very
> >>>>
> >>>>
> >>controlled
> >>
> >>
> >>>>environments.
> >>>>
> >>>>Set Anonymous Access off on the virtual folder in IIS, click Basic
> >>>>Authentication off, and click Windows Integrated Authentication on.
> >>>>
> >>>>And, of course, make sure your ACLs are set properly on the files and
> >>>>folders for the users you want to have access.
> >>>>
> >>>>Next, in the <system.web> section of your web.config for your web app,
> >>>>include the following:
> >>>>
> >>>><identity impersonate="true" />
> >>>>
> >>>>Now, your file access will be determined by the windows user from your
> >>>>domain who is logged in.
> >>>>
> >>>>You can also customize the access in code by using the
> >>>>User.Identity.IsInRole("SomeSecurityUserOrGroupName") method -
> >>>>
> >>>>
> >accepting
> >
> >
> >>>or
> >>>
> >>>
> >>>>rejecting the request based on the results.
> >>>>
> >>>>Hope this helps,
> >>>>
> >>>>Dale Preston
> >>>>MCAD, MCSE, MCDBA
> >>>>
> >>>>
> >>>>"Razak" <razak@mmsc.com.my> wrote in message
> >>>>news:#Lyhf0XcEHA.596@TK2MSFTNGP11.phx.gbl...
> >>>>
> >>>>
> >>>>>Sorry for late reply.. I took a day off yesterday.
> >>>>>
> >>>>>I'm new to .NET and want to learn by creating my personal website
> >>>>>
> >>>>>
> >>using
> >>
> >>
> >>>>>ASP.NET and VB.NET. In my application, I have photo galleries where
> >>>>>
> >>>>>
> >I
> >
> >
> >>>can
> >>>
> >>>
> >>>>>upload photos of certain events (galleries) into a folder in the
> >>>>>
> >>>>>
> >>images
> >>
> >>
> >>>>>folder. Every events have their own folder to keep the photos. I
> >>>>>
> >>>>>
> >have
> >
> >
> >>no
> >>
> >>
> >>>>>problem creating folders. But when it comes to deleting them, i got
> >>>>>
> >>>>>
> >>>>'Access
> >>>>
> >>>>
> >>>>>denied' which probably because of security issues. I don't want to
> >>>>>
> >>>>>
> >>>change
> >>>
> >>>
> >>>>>anything on the server side, and resort to using impersonation.
> >>>>>
> >>>>>From the samples given by MS KB at
> >>>>>http://support.microsoft.com/default.aspx?scid=kb;EN-US;306158, i
> >>>>>
> >>>>>
> >have
> >
> >
> >>>no
> >>>
> >>>
> >>>>>problem impersonating as the administrator account (I maintain the
> >>>>>
> >>>>>
> >>>server
> >>>
> >>>
> >>>>in
> >>>>
> >>>>
> >>>>>the office), that is, the fourth example on the link titled
> >>>>>
> >>>>>
> >>'Impersonate
> >>
> >>
> >>>a
> >>>
> >>>
> >>>>>Specific User in Code'. I came across the third example titled
> >>>>>
> >>>>>
> >>>>'Impersonate
> >>>>
> >>>>
> >>>>>the Authenticating User in Code', (the code is given in my original
> >>>>>
> >>>>>
> >>>post)
> >>>
> >>>
> >>>>>and would like to try that method. That's when the error occurs.
> >>>>>
> >>>>>Hope that you understand what I'm trying to say here. It's just the
> >>>>>
> >>>>>
> >>>>purpose
> >>>>
> >>>>
> >>>>>of learning. I believe it should work somehow.
> >>>>>
> >>>>>Thanks.
> >>>>>
> >>>>>
> >>>>>
>
>>--------------------------------------------------------------------------
> >>
> >>
> >>>>--
> >>>>
> >>>>
> >>>>
>
>>---- ---------------------------------------------------------------------
> >>
> >>
> >>>>--
> >>>>
> >>>>
> >>>>>---------
> >>>>>"Dale" <daleDeletepres@msndotcomNot.Net> wrote in message
> >>>>>news:eB2zSZFcEHA.2008@TK2MSFTNGP10.phx.gbl...
> >>>>>
> >>>>>
> >>>>>>I am not sure what you're trying to do with impersonation so it's
> >>>>>>
> >>>>>>
> >>hard
> >>
> >>
> >>>>to
> >>>>
> >>>>
> >>>>>>tell you exactly how to do it but the User object in your web app
> >>>>>>
> >>>>>>
> >is
> >
> >
> >>>>>>equivelent to a System.Security.Principal.IPrincipal object and
> >>>>>>
> >>>>>>
> >not
> >
> >
> >>a
> >>
> >>
> >>>>>>WindowsPrincipal object.
> >>>>>>
> >>>>>>Likewise, the User.Identity is an IIdentity and not a
> >>>>>>
> >>>>>>
> >WindowsIdenity
> >
> >
> >>>>>object.
> >>>>>
> >>>>>
> >>>>>>Can you post more about what you're trying to do?
> >>>>>>
> >>>>>>Dale
> >>>>>>
> >>>>>>
> >>>>>>"Razak" <razak@mmsc.com.my> wrote in message
> >>>>>>news:#OyFf##bEHA.2008@TK2MSFTNGP10.phx.gbl...
> >>>>>>
> >>>>>>
> >>>>>>>Hi,
> >>>>>>>
> >>>>>>>I have a class which basically do Impersonation in my web
> >>>>>>>
> >>>>>>>
> >>>application.
> >>>
> >>>
> >>>>>>From
> >>>>>>
> >>>>>>
> >>>>>>>MS KB sample:-
> >>>>>>>
> >>>>>>>++++++++++++++++++++code starts
> >>>>>>>Dim impersonationContext As
> >>>>>>>System.Security.Principal.WindowsImpersonationContext
> >>>>>>>Dim currentWindowsIdentity As
> >>>>>>>
> >>>>>>>
> >>>>System.Security.Principal.WindowsIdentity
> >>>>
> >>>>
> >>>>>>>currentWindowsIdentity = CType(User.Identity,
> >>>>>>>System.Security.Principal.WindowsIdentity)
> >>>>>>>impersonationContext = currentWindowsIdentity.Impersonate()
> >>>>>>>
> >>>>>>>'Insert your code that runs under the security context of the
> >>>>>>>
> >>>>>>>
> >>>>>>authenticating
> >>>>>>
> >>>>>>
> >>>>>>>user here.
> >>>>>>>
> >>>>>>>impersonationContext.Undo()
> >>>>>>>+++++++++++++++++++++code ends
> >>>>>>>
> >>>>>>>since I need to implement this code in class.vb, I have to
> >>>>>>>
> >>>>>>>
> >change
> >
> >
> >>>the
> >>>
> >>>
> >>>>>>line:-
> >>>>>>
> >>>>>>
> >>>>>>>currentWindowsIdentity = CType(User.Identity,
> >>>>>>>System.Security.Principal.WindowsIdentity)
> >>>>>>>
> >>>>>>>to:-
> >>>>>>>
> >>>>>>>currentWindowsIdentity =
> >>>>>>>
> >>>>>>>
> >CType(HttpContext.Current.User.Identity,
> >
> >
> >>>>>>>System.Security.Principal.WindowsIdentity)
> >>>>>>>
> >>>>>>>But that produces error 'Specified cast is not valid.'. Is there
> >>>>>>>
> >>>>>>>
> >>>>>anything
> >>>>>
> >>>>>
> >>>>>>>that I miss here? Please help!
> >>>>>>>
> >>>>>>>Thank you
> >>>>>>>
> >>>>>>>
>
>>--------------------------------------------------------------------------
> >>
> >>
> >>>>>>--
> >>>>>>
> >>>>>>
> >>>>>>
>
>>---- ---------------------------------------------------------------------
> >>
> >>
> >>>>>>--
> >>>>>>
> >>>>>>
> >>>>>>>---------
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>
> >>>>>>
> >>>>>
> >>>>>
> >>>>
> >>>>
> >>>
> >>>
> >>
> >>
> >
> >
> >
> >
>