PRB: Access Denied Error When Calling LogonUser API

ID: Q223334


The information in this article applies to:
  • Microsoft Visual Basic Learning, Professional, and Enterprise Editions for Windows, versions 5.0, 6.0


SYMPTOMS

When attempting to make a Win32 Application Programmer Interface (API) call LogonUser from within a Visual Basic Component Object Model (COM) component with Active Server Pages (ASP), one of the following errors appears:

'5' - "Access Denied."

'1314' - "A required privilege is not held by the client."


CAUSE

The Internet Information Server (IIS) authenticated user that is making the request to LogonUser does not hold the correct privilege, which causes LogonUser to fail.


RESOLUTION

If your component is in-process, you can create a Microsoft Transaction Server (MTS) package to host your COM component, which will handle the security context switching for you.

For additional information on how to create an empty package and add components to it, please see the following article in the Microsoft Knowledge Base:

Q223406 HOWTO: Create an Empty MTS Package to Add Components for ASP
An alternative resolution is to use the following Win32 APIs:
  • RevertToSelf


  • LogonUser


  • ImpersonateLoggedOnUser


  1. First call RevertToSelf. Calling LogonUser will fail if the thread making the call does not have the correct security context. The SYSTEM account holds the correct privilege to call LogonUser successfully.

    Calling RevertToSelf will cause the thread to execute as the SYSTEM account if the following conditions are true:
    • The web application is running in-process.


    • If the component is under MTS control, it is a library package.




  2. Next call LogonUser specifying the Windows NT account you want the component to run as. LogonUser will return a handle to the security token.


  3. Then call ImpersonateLoggedOnUser passing the security token returned by LogonUser.

    Your component is now impersonating the security context of the Windows NT account you specified.


Important: After you are done with the impersonation, you must again call RevertToSelf.


STATUS

This behavior is by design.


MORE INFORMATION

Sample Code

Visual Basic 6.0 Project (ProgID = LoginAdmin.ImpersonateUser): Code for BAS Module:

Declare Function LogonUser Lib "advapi32.dll" Alias "LogonUserA" (ByVal lpszUsername As String, 
ByVal lpszDomain As String, ByVal lpszPassword As String, ByVal dwLogonType As Long, ByVal 
dwLogonProvider As Long, phToken As Long) As Long

Declare Function ImpersonateLoggedOnUser Lib "advapi32.dll" (ByVal hToken As Long) As Long

Declare Function RevertToSelf Lib "advapi32.dll" () As Long 
Code for Class Module:

Option Explicit

Const LOGON32_LOGON_INTERACTIVE = 2
Const LOGON32_PROVIDER_DEFAULT = 0

Public Sub Logon(ByVal strAdminUser As String, ByVal strAdminPassword As String, ByVal strAdminDomain As String)
  Dim lngTokenHandle, lngLogonType, lngLogonProvider As Long
  Dim blnResult As Boolean
  
  lngLogonType = LOGON32_LOGON_INTERACTIVE
  lngLogonProvider = LOGON32_PROVIDER_DEFAULT
  
  blnResult = RevertToSelf()
  
  blnResult = LogonUser(strAdminUser, strAdminDomain, strAdminPassword, _
                                       lngLogonType, lngLogonProvider, _
                                       lngTokenHandle)
                                                       
  blnResult = ImpersonateLoggedOnUser(lngTokenHandle)
End Sub

Public Sub Logoff()
  Dim blnResult As Boolean
  
  blnResult = RevertToSelf()
End Sub 
Code for ASP:

<%
  Option Explicit
  Dim objLogon

  Set objLogon = Server.CreateObject("LoginAdmin.ImpersonateUser")
  objLogon.Logon "AdminUserid", "AdminPassword", "AdminDomain"

  'Body of code for the page...

  objLogon.Logoff
  Set objLogon = Nothing
%> 
Note that, when you call the Logoff method as coded here, you will revert to the SYSTEM userid, so do this only at the end of page processing.

Additional query words:

Keywords : kbCOMt kbVBp kbVBp500 kbVBp600 kbGrpASP
Version : WINDOWS:5.0,6.0
Platform : WINDOWS
Issue type : kbprb


Last Reviewed: October 13, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.