Impersonation and 401

M

M Stellinga

I'm trying to write an application that updates the actuals of assignments of
various resources in MS Project 2007 through the SOAP/PSI interface.

The statusing changexml function seems to do what I require, but only for
the currently logged in user.
After some investigation it appears that I'll to use impersonation to get
this to function properly.
I've been trying to get impersonation to work, but so far, no luck.
Neither my own code, nor the impersonationConsoleApp from the SDK appear to
be able to impersonate anybody.

I've added myself as administrator to the machine, and granted myself direct
access to the shared service provider using the sharepoint central admin site
and the stsadm command-line tool.
That not helping, I added <identity impersonatie="true"> to the system.web
section of the sharedservices site.

I have a Windows 2008 Server with IIS 7 and Project 2007.
My Project Web Access site is running at http://w2k8-01/pwa
My Shared Services site is running at http://w2k8-01:56737/sharedservices1
Now, if I understand this correctly, to make a call using impersonation, one
sends a SOAP request to
http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx (in the example, or
http://w2k8-01:56737/SharedServices1/PSI/Statusing.asmx for my own code)
This SOAP request has an pjAuth header from the PSContextInfo containing:
- the GUID of the account to impersonate
- the GUID of the Project Web Access site
and a ForwardedFrom header containing:
- "/_vti_bin/PSI/Resource.asmx"
The sharedservices site validates my credentials, then calls the Project Web
Access site (http://w2k8-01/pwa/_vti_bin/PSI/Resource.asmx) with the
credentials in pjAuth.
Unfortunately, all I get is a 401 response.

Can anybody help me with this?
 
M

M Stellinga

This is the code from the ImpersonationConsoleApp from the Project SDK that
I've been trying to use as a baseline (I only edited the PSI_RESOURCE_SSP,
PROJECT_SERVER_URI, and PWA_SITE_GUID). The output when running this is below
it.

--------------------------------------------------------------------------------------------------
// During impersonation, use URLs for the PSI Web services in the Shared
Service Provider.
// The Shared Service Provider URLs go directly to the PSI, not
through Project Web Access.
private const string PSI_RESOURCE_SSP =
"http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx";

// Before impersonation, use the PSI through Project Web Access.
private const string PROJECT_SERVER_URI = "http://w2k8-01/pwa";
private const string RESOURCE_SERVICE_PATH =
"/_vti_bin/psi/resource.asmx";

// GUID of the Project Web Access site in SharePoint. **Change to
your value**
private const string PWA_SITE_GUID =
"12d3f676-aeb2-4a39-9a1e-ba85e66dcc6c";

static ResourceDerived resProxyBySSP;

static void Main(string[] args)
{
Console.WriteLine("Enter a valid Project Server user account,
such as");
Console.WriteLine(@"domain\username or
aspnetsqlmembershipprovider:username:");

string userAccount = Console.ReadLine();

try
{
resProxyBySSP = new ResourceDerived();

resProxyBySSP.Url = PSI_RESOURCE_SSP;
resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.
Guid userGuid = GetResourceUid(userAccount);
Console.WriteLine("User GUID to impersonate: " +
userGuid.ToString());

// You can also hard-code the user's Guid. Get the user's
Guid from the Published
// database or from the System Identification Data section
on the Manage User page
// in Project Web Access. For example:
// Guid userGuid = new
Guid("0154dd59-13fc-4f50-908e-5f24fa6ef785");

// To use the following code, the application must run on
the Project Server computer
// where Windows SharePoint Services is installed.
//
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// You can hard-code the siteId. Get the siteID in one of
the following two ways:
// a. Open the SharePoint ContentDB for the SSP. Open the
Webs table and
// get the SiteId where the FullUrl value is the name
of the
// Project Web Access instance, for example,
ProjectServerName.
// b. Open the Manage Project Web Access Sites page in
the SSP Admin site,
// click the drop-down list for the site and then
click Edit. The siteID
// is the GUID of the id option in the URL, for example:
//
http://ServerName:19466/ssp/admin/_...=Edit&id=44c4ae03-16c2-4618-bf9a-12643006c5be
//
// To use the following code, the application must run on
the Project Web
// Access computer. Set references to the
Microsoft.SharePoint and
// Microsoft.SharePoint.Search assemblies on the same
computer.
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// Otherwise, hard-code the site ID.
Guid siteId = new Guid(PWA_SITE_GUID);

resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.

bool isWindowsUser = true;
if (userAccount.Contains("aspnetsqlmembershipprovider"))
isWindowsUser = false;

ResourceDerived.SetImpersonationContext(isWindowsUser,
userAccount,
userGuid, Guid.Empty, siteId, "1033");

// To get the GUID of the user we are impersonating,
// call GetCurrentUserUid in the Resource Web service.
Guid impersonatedUserGuid = resProxyBySSP.GetCurrentUserUid();

Console.WriteLine(string.Format("\nImpersonating
'{0}':\n\tResourceProxy.Url:\n\t{1}",
userAccount, resProxyBySSP.Url));

Console.Write("\nImpersonated user GUID: ");
Console.WriteLine(impersonatedUserGuid.ToString());
}
catch (SoapException ex)
{
ExceptionHandlers.HandleSoapException(ex);
}
catch (WebException ex)
{
ExceptionHandlers.HandleWebException(ex);
}
catch (Exception ex)
{
ExceptionHandlers.HandleException(ex);
}
finally
{
ExceptionHandlers.ResetConsole();
}
Console.Write("Press any key...");
Console.ReadKey();
}


/// <summary>
/// Returns the GUID for a Project Server account name.
/// </summary>
/// <param name="ntAccount"></param>
/// <returns></returns>
private static Guid GetResourceUid(String accountName)
{
Resource resProxyByPWA = new Resource();
resProxyByPWA.Credentials = CredentialCache.DefaultCredentials;
// Before impersonation, use the Project Web Access URL.
resProxyByPWA.Url = PROJECT_SERVER_URI + RESOURCE_SERVICE_PATH;

ResourceDataSet rds = new ResourceDataSet();

// Filter for the account name, which can be a Windows or
Project Server account.
PSLibrary.Filter filter = new PSLibrary.Filter();
filter.FilterTableName = rds.Resources.TableName;

PSLibrary.Filter.Field accountField =
new PSLibrary.Filter.Field(rds.Resources.TableName,
rds.Resources.WRES_ACCOUNTColumn.ColumnName);
filter.Fields.Add(accountField);

PSLibrary.Filter.FieldOperator op =
new PSLibrary.Filter.FieldOperator(
PSLibrary.Filter.FieldOperationType.Equal,
rds.Resources.WRES_ACCOUNTColumn.ColumnName, accountName);
filter.Criteria = op;

Console.WriteLine("\nNot
impersonating:\n\tResourceProxy.Url:\n\t" + resProxyByPWA.Url);
rds =
(ResourceDataSet)(resProxyByPWA.ReadResources(filter.GetXml(), false));

// Return the account GUID
return (Guid)rds.Resources.Rows[0]["RES_UID"];
}
}

--------------------------------------------------------------------------------------------------

And here is the code from resourceDerived to set the impersonation headers:
--------------------------------------------------------------------------------------------------
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest webRequest = base.GetWebRequest(uri);
if (contextString != String.Empty)
{
webRequest.UseDefaultCredentials = true;

bool isImpersonating =

(System.Security.Principal.WindowsIdentity.GetCurrent(true) != null);
webRequest.Credentials = CredentialCache.DefaultCredentials;

webRequest.Headers.Add("PjAuth", contextString);
webRequest.Headers.Add("ForwardedFrom",
"/_vti_bin/psi/resource.asmx");

webRequest.PreAuthenticate = true;
}
return webRequest;
}
--------------------------------------------------------------------------------------------------

Because I can't use my development tools under a different
user name, I'm logged in as myself on the domain (Artsoft\Martijn).
I've given this account administrator priviliges on the machine where
project is installed (w2k8-01), in Project Web Access and for the Shared
Service Provider.
Then I've tried impersonation several users that were entered as resources
in Project:
W2k8-01\Piet
W2k8-01\Administrator
AspNetSqlMembershipProvider:piet
The result, for all of these is as follows:

Enter a valid Project Server user account, such as
domain\username or aspnetsqlmembershipprovider:username:
W2k8-01\Piet

Not impersonating:
ResourceProxy.Url:
http://w2k8-01/pwa/_vti_bin/psi/resource.asmx
User GUID to impersonate: 4c0c3396-5506-4bec-977a-c56e4822076b
Web Exception: The request failed with HTTP status 401: Unauthorized.

Log on, or check that Project Server is running.
Press any key...
 
S

Stephen Sanderlin

Does the user you are running the console app as have administrator
permissions in Project Server?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com



This is the code from the ImpersonationConsoleApp from the Project SDK that
I've been trying to use as a baseline (I only edited the PSI_RESOURCE_SSP,
PROJECT_SERVER_URI, and PWA_SITE_GUID). The output when running this is below
it.

--------------------------------------------------------------------------------------------------
// During impersonation, use URLs for the PSI Web services in the Shared
Service Provider.
// The Shared Service Provider URLs go directly to the PSI, not
through Project Web Access.
private const string PSI_RESOURCE_SSP =
"http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx";

// Before impersonation, use the PSI through Project Web Access.
private const string PROJECT_SERVER_URI = "http://w2k8-01/pwa";
private const string RESOURCE_SERVICE_PATH =
"/_vti_bin/psi/resource.asmx";

// GUID of the Project Web Access site in SharePoint. **Change to
your value**
private const string PWA_SITE_GUID =
"12d3f676-aeb2-4a39-9a1e-ba85e66dcc6c";

static ResourceDerived resProxyBySSP;

static void Main(string[] args)
{
Console.WriteLine("Enter a valid Project Server user account,
such as");
Console.WriteLine(@"domain\username or
aspnetsqlmembershipprovider:username:");

string userAccount = Console.ReadLine();

try
{
resProxyBySSP = new ResourceDerived();

resProxyBySSP.Url = PSI_RESOURCE_SSP;
resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.
Guid userGuid = GetResourceUid(userAccount);
Console.WriteLine("User GUID to impersonate: " +
userGuid.ToString());

// You can also hard-code the user's Guid. Get the user's
Guid from the Published
// database or from the System Identification Data section
on the Manage User page
// in Project Web Access. For example:
// Guid userGuid = new
Guid("0154dd59-13fc-4f50-908e-5f24fa6ef785");

// To use the following code, the application must run on
the Project Server computer
// where Windows SharePoint Services is installed.
//
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// You can hard-code the siteId. Get the siteID in one of
the following two ways:
// a. Open the SharePoint ContentDB for the SSP. Open the
Webs table and
// get the SiteId where the FullUrl value is the name
of the
// Project Web Access instance, for example,
ProjectServerName.
// b. Open the Manage Project Web Access Sites page in
the SSP Admin site,
// click the drop-down list for the site and then
click Edit. The siteID
// is the GUID of the id option in the URL, for example:
//
http://ServerName:19466/ssp/admin/_...=Edit&id=44c4ae03-16c2-4618-bf9a-12643006c5be
//
// To use the following code, the application must run on
the Project Web
// Access computer. Set references to the
Microsoft.SharePoint and
// Microsoft.SharePoint.Search assemblies on the same
computer.
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// Otherwise, hard-code the site ID.
Guid siteId = new Guid(PWA_SITE_GUID);

resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.

bool isWindowsUser = true;
if (userAccount.Contains("aspnetsqlmembershipprovider"))
isWindowsUser = false;

ResourceDerived.SetImpersonationContext(isWindowsUser,
userAccount,
userGuid, Guid.Empty, siteId, "1033");

// To get the GUID of the user we are impersonating,
// call GetCurrentUserUid in the Resource Web service.
Guid impersonatedUserGuid = resProxyBySSP.GetCurrentUserUid();

Console.WriteLine(string.Format("\nImpersonating
'{0}':\n\tResourceProxy.Url:\n\t{1}",
userAccount, resProxyBySSP.Url));

Console.Write("\nImpersonated user GUID: ");
Console.WriteLine(impersonatedUserGuid.ToString());
}
catch (SoapException ex)
{
ExceptionHandlers.HandleSoapException(ex);
}
catch (WebException ex)
{
ExceptionHandlers.HandleWebException(ex);
}
catch (Exception ex)
{
ExceptionHandlers.HandleException(ex);
}
finally
{
ExceptionHandlers.ResetConsole();
}
Console.Write("Press any key...");
Console.ReadKey();
}


/// <summary>
/// Returns the GUID for a Project Server account name.
/// </summary>
/// <param name="ntAccount"></param>
/// <returns></returns>
private static Guid GetResourceUid(String accountName)
{
Resource resProxyByPWA = new Resource();
resProxyByPWA.Credentials = CredentialCache.DefaultCredentials;
// Before impersonation, use the Project Web Access URL.
resProxyByPWA.Url = PROJECT_SERVER_URI + RESOURCE_SERVICE_PATH;

ResourceDataSet rds = new ResourceDataSet();

// Filter for the account name, which can be a Windows or
Project Server account.
PSLibrary.Filter filter = new PSLibrary.Filter();
filter.FilterTableName = rds.Resources.TableName;

PSLibrary.Filter.Field accountField =
new PSLibrary.Filter.Field(rds.Resources.TableName,
rds.Resources.WRES_ACCOUNTColumn.ColumnName);
filter.Fields.Add(accountField);

PSLibrary.Filter.FieldOperator op =
new PSLibrary.Filter.FieldOperator(
PSLibrary.Filter.FieldOperationType.Equal,
rds.Resources.WRES_ACCOUNTColumn.ColumnName, accountName);
filter.Criteria = op;

Console.WriteLine("\nNot
impersonating:\n\tResourceProxy.Url:\n\t" + resProxyByPWA.Url);
rds =
(ResourceDataSet)(resProxyByPWA.ReadResources(filter.GetXml(), false));

// Return the account GUID
return (Guid)rds.Resources.Rows[0]["RES_UID"];
}
}

--------------------------------------------------------------------------------------------------

And here is the code from resourceDerived to set the impersonation headers:
--------------------------------------------------------------------------------------------------
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest webRequest = base.GetWebRequest(uri);
if (contextString != String.Empty)
{
webRequest.UseDefaultCredentials = true;

bool isImpersonating =

(System.Security.Principal.WindowsIdentity.GetCurrent(true) != null);
webRequest.Credentials = CredentialCache.DefaultCredentials;

webRequest.Headers.Add("PjAuth", contextString);
webRequest.Headers.Add("ForwardedFrom",
"/_vti_bin/psi/resource.asmx");

webRequest.PreAuthenticate = true;
}
return webRequest;
}
--------------------------------------------------------------------------------------------------

Because I can't use my development tools under a different
user name, I'm logged in as myself on the domain (Artsoft\Martijn).
I've given this account administrator priviliges on the machine where
project is installed (w2k8-01), in Project Web Access and for the Shared
Service Provider.
Then I've tried impersonation several users that were entered as resources
in Project:
W2k8-01\Piet
W2k8-01\Administrator
AspNetSqlMembershipProvider:piet
The result, for all of these is as follows:

Enter a valid Project Server user account, such as
domain\username or aspnetsqlmembershipprovider:username:
W2k8-01\Piet

Not impersonating:
ResourceProxy.Url:
http://w2k8-01/pwa/_vti_bin/psi/resource.asmx
User GUID to impersonate: 4c0c3396-5506-4bec-977a-c56e4822076b
Web Exception: The request failed with HTTP status 401: Unauthorized.

Log on, or check that Project Server is running.
Press any key...

:

Can you please post your code?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com
 
M

M Stellinga

That's my own domain account (artsoft\Martijn) and yes, it has both
Administrator rights in the Project Server, on the machine Project Server is
running on, and for the shared service provider (through the web access of
the sharepoint administration center and by using the stsadm application).
Just to be on the safe side I even gave myself owner rights on the database.

I also tried to run the Console app from the machine itself (w2k8-01) as the
administrator (the account that installed everything), but that yielded the
same 401 reply.

Stephen Sanderlin said:
Does the user you are running the console app as have administrator
permissions in Project Server?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com



This is the code from the ImpersonationConsoleApp from the Project SDK that
I've been trying to use as a baseline (I only edited the PSI_RESOURCE_SSP,
PROJECT_SERVER_URI, and PWA_SITE_GUID). The output when running this is below
it.

--------------------------------------------------------------------------------------------------
// During impersonation, use URLs for the PSI Web services in the Shared
Service Provider.
// The Shared Service Provider URLs go directly to the PSI, not
through Project Web Access.
private const string PSI_RESOURCE_SSP =
"http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx";

// Before impersonation, use the PSI through Project Web Access.
private const string PROJECT_SERVER_URI = "http://w2k8-01/pwa";
private const string RESOURCE_SERVICE_PATH =
"/_vti_bin/psi/resource.asmx";

// GUID of the Project Web Access site in SharePoint. **Change to
your value**
private const string PWA_SITE_GUID =
"12d3f676-aeb2-4a39-9a1e-ba85e66dcc6c";

static ResourceDerived resProxyBySSP;

static void Main(string[] args)
{
Console.WriteLine("Enter a valid Project Server user account,
such as");
Console.WriteLine(@"domain\username or
aspnetsqlmembershipprovider:username:");

string userAccount = Console.ReadLine();

try
{
resProxyBySSP = new ResourceDerived();

resProxyBySSP.Url = PSI_RESOURCE_SSP;
resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.
Guid userGuid = GetResourceUid(userAccount);
Console.WriteLine("User GUID to impersonate: " +
userGuid.ToString());

// You can also hard-code the user's Guid. Get the user's
Guid from the Published
// database or from the System Identification Data section
on the Manage User page
// in Project Web Access. For example:
// Guid userGuid = new
Guid("0154dd59-13fc-4f50-908e-5f24fa6ef785");

// To use the following code, the application must run on
the Project Server computer
// where Windows SharePoint Services is installed.
//
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// You can hard-code the siteId. Get the siteID in one of
the following two ways:
// a. Open the SharePoint ContentDB for the SSP. Open the
Webs table and
// get the SiteId where the FullUrl value is the name
of the
// Project Web Access instance, for example,
ProjectServerName.
// b. Open the Manage Project Web Access Sites page in
the SSP Admin site,
// click the drop-down list for the site and then
click Edit. The siteID
// is the GUID of the id option in the URL, for example:
//
http://ServerName:19466/ssp/admin/_...=Edit&id=44c4ae03-16c2-4618-bf9a-12643006c5be
//
// To use the following code, the application must run on
the Project Web
// Access computer. Set references to the
Microsoft.SharePoint and
// Microsoft.SharePoint.Search assemblies on the same
computer.
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// Otherwise, hard-code the site ID.
Guid siteId = new Guid(PWA_SITE_GUID);

resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.

bool isWindowsUser = true;
if (userAccount.Contains("aspnetsqlmembershipprovider"))
isWindowsUser = false;

ResourceDerived.SetImpersonationContext(isWindowsUser,
userAccount,
userGuid, Guid.Empty, siteId, "1033");

// To get the GUID of the user we are impersonating,
// call GetCurrentUserUid in the Resource Web service.
Guid impersonatedUserGuid = resProxyBySSP.GetCurrentUserUid();

Console.WriteLine(string.Format("\nImpersonating
'{0}':\n\tResourceProxy.Url:\n\t{1}",
userAccount, resProxyBySSP.Url));

Console.Write("\nImpersonated user GUID: ");
Console.WriteLine(impersonatedUserGuid.ToString());
}
catch (SoapException ex)
{
ExceptionHandlers.HandleSoapException(ex);
}
catch (WebException ex)
{
ExceptionHandlers.HandleWebException(ex);
}
catch (Exception ex)
{
ExceptionHandlers.HandleException(ex);
}
finally
{
ExceptionHandlers.ResetConsole();
}
Console.Write("Press any key...");
Console.ReadKey();
}


/// <summary>
/// Returns the GUID for a Project Server account name.
/// </summary>
/// <param name="ntAccount"></param>
/// <returns></returns>
private static Guid GetResourceUid(String accountName)
{
Resource resProxyByPWA = new Resource();
resProxyByPWA.Credentials = CredentialCache.DefaultCredentials;
// Before impersonation, use the Project Web Access URL.
resProxyByPWA.Url = PROJECT_SERVER_URI + RESOURCE_SERVICE_PATH;

ResourceDataSet rds = new ResourceDataSet();

// Filter for the account name, which can be a Windows or
Project Server account.
PSLibrary.Filter filter = new PSLibrary.Filter();
filter.FilterTableName = rds.Resources.TableName;

PSLibrary.Filter.Field accountField =
new PSLibrary.Filter.Field(rds.Resources.TableName,
rds.Resources.WRES_ACCOUNTColumn.ColumnName);
filter.Fields.Add(accountField);

PSLibrary.Filter.FieldOperator op =
new PSLibrary.Filter.FieldOperator(
PSLibrary.Filter.FieldOperationType.Equal,
rds.Resources.WRES_ACCOUNTColumn.ColumnName, accountName);
filter.Criteria = op;

Console.WriteLine("\nNot
impersonating:\n\tResourceProxy.Url:\n\t" + resProxyByPWA.Url);
rds =
(ResourceDataSet)(resProxyByPWA.ReadResources(filter.GetXml(), false));

// Return the account GUID
return (Guid)rds.Resources.Rows[0]["RES_UID"];
}
}

--------------------------------------------------------------------------------------------------

And here is the code from resourceDerived to set the impersonation headers:
--------------------------------------------------------------------------------------------------
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest webRequest = base.GetWebRequest(uri);
if (contextString != String.Empty)
{
webRequest.UseDefaultCredentials = true;

bool isImpersonating =

(System.Security.Principal.WindowsIdentity.GetCurrent(true) != null);
webRequest.Credentials = CredentialCache.DefaultCredentials;

webRequest.Headers.Add("PjAuth", contextString);
webRequest.Headers.Add("ForwardedFrom",
"/_vti_bin/psi/resource.asmx");

webRequest.PreAuthenticate = true;
}
return webRequest;
}
--------------------------------------------------------------------------------------------------

Because I can't use my development tools under a different
user name, I'm logged in as myself on the domain (Artsoft\Martijn).
I've given this account administrator priviliges on the machine where
project is installed (w2k8-01), in Project Web Access and for the Shared
Service Provider.
Then I've tried impersonation several users that were entered as resources
in Project:
W2k8-01\Piet
W2k8-01\Administrator
AspNetSqlMembershipProvider:piet
The result, for all of these is as follows:

Enter a valid Project Server user account, such as
domain\username or aspnetsqlmembershipprovider:username:
W2k8-01\Piet

Not impersonating:
ResourceProxy.Url:
http://w2k8-01/pwa/_vti_bin/psi/resource.asmx
User GUID to impersonate: 4c0c3396-5506-4bec-977a-c56e4822076b
Web Exception: The request failed with HTTP status 401: Unauthorized.

Log on, or check that Project Server is running.
Press any key...

:

Can you please post your code?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com
I'm trying to write an application that updates the actuals of assignments of
various resources in MS Project 2007 through the SOAP/PSI interface.

The statusing changexml function seems to do what I require, but only for
the currently logged in user.
After some investigation it appears that I'll to use impersonation to get
this to function properly.
I've been trying to get impersonation to work, but so far, no luck.
Neither my own code, nor the impersonationConsoleApp from the SDK appear to
be able to impersonate anybody.

I've added myself as administrator to the machine, and granted myself direct
access to the shared service provider using the sharepoint central admin site
and the stsadm command-line tool.
That not helping, I added <identity impersonatie="true"> to the system.web
section of the sharedservices site.

I have a Windows 2008 Server with IIS 7 and Project 2007.
My Project Web Access site is running at http://w2k8-01/pwa
My Shared Services site is running at http://w2k8-01:56737/sharedservices1
Now, if I understand this correctly, to make a call using impersonation, one
sends a SOAP request to
http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx (in the example, or
http://w2k8-01:56737/SharedServices1/PSI/Statusing.asmx for my own code)
This SOAP request has an pjAuth header from the PSContextInfo containing:
- the GUID of the account to impersonate
- the GUID of the Project Web Access site
and a ForwardedFrom header containing:
- "/_vti_bin/PSI/Resource.asmx"
The sharedservices site validates my credentials, then calls the Project Web
Access site (http://w2k8-01/pwa/_vti_bin/PSI/Resource.asmx) with the
 
S

Stephen Sanderlin

Try installing Fiddler2 and take look at the NTLM authentication
handshake... is the account that your code is trying to authenticate as
your user account, or some other account?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com



That's my own domain account (artsoft\Martijn) and yes, it has both
Administrator rights in the Project Server, on the machine Project Server is
running on, and for the shared service provider (through the web access of
the sharepoint administration center and by using the stsadm application).
Just to be on the safe side I even gave myself owner rights on the database.

I also tried to run the Console app from the machine itself (w2k8-01) as the
administrator (the account that installed everything), but that yielded the
same 401 reply.

:

Does the user you are running the console app as have administrator
permissions in Project Server?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com



This is the code from the ImpersonationConsoleApp from the Project SDK that
I've been trying to use as a baseline (I only edited the PSI_RESOURCE_SSP,
PROJECT_SERVER_URI, and PWA_SITE_GUID). The output when running this is below
it.

--------------------------------------------------------------------------------------------------
// During impersonation, use URLs for the PSI Web services in the Shared
Service Provider.
// The Shared Service Provider URLs go directly to the PSI, not
through Project Web Access.
private const string PSI_RESOURCE_SSP =
"http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx";

// Before impersonation, use the PSI through Project Web Access.
private const string PROJECT_SERVER_URI = "http://w2k8-01/pwa";
private const string RESOURCE_SERVICE_PATH =
"/_vti_bin/psi/resource.asmx";

// GUID of the Project Web Access site in SharePoint. **Change to
your value**
private const string PWA_SITE_GUID =
"12d3f676-aeb2-4a39-9a1e-ba85e66dcc6c";

static ResourceDerived resProxyBySSP;

static void Main(string[] args)
{
Console.WriteLine("Enter a valid Project Server user account,
such as");
Console.WriteLine(@"domain\username or
aspnetsqlmembershipprovider:username:");

string userAccount = Console.ReadLine();

try
{
resProxyBySSP = new ResourceDerived();

resProxyBySSP.Url = PSI_RESOURCE_SSP;
resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.
Guid userGuid = GetResourceUid(userAccount);
Console.WriteLine("User GUID to impersonate: " +
userGuid.ToString());

// You can also hard-code the user's Guid. Get the user's
Guid from the Published
// database or from the System Identification Data section
on the Manage User page
// in Project Web Access. For example:
// Guid userGuid = new
Guid("0154dd59-13fc-4f50-908e-5f24fa6ef785");

// To use the following code, the application must run on
the Project Server computer
// where Windows SharePoint Services is installed.
//
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// You can hard-code the siteId. Get the siteID in one of
the following two ways:
// a. Open the SharePoint ContentDB for the SSP. Open the
Webs table and
// get the SiteId where the FullUrl value is the name
of the
// Project Web Access instance, for example,
ProjectServerName.
// b. Open the Manage Project Web Access Sites page in
the SSP Admin site,
// click the drop-down list for the site and then
click Edit. The siteID
// is the GUID of the id option in the URL, for example:
//
http://ServerName:19466/ssp/admin/_...=Edit&id=44c4ae03-16c2-4618-bf9a-12643006c5be
//
// To use the following code, the application must run on
the Project Web
// Access computer. Set references to the
Microsoft.SharePoint and
// Microsoft.SharePoint.Search assemblies on the same
computer.
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// Otherwise, hard-code the site ID.
Guid siteId = new Guid(PWA_SITE_GUID);

resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.

bool isWindowsUser = true;
if (userAccount.Contains("aspnetsqlmembershipprovider"))
isWindowsUser = false;

ResourceDerived.SetImpersonationContext(isWindowsUser,
userAccount,
userGuid, Guid.Empty, siteId, "1033");

// To get the GUID of the user we are impersonating,
// call GetCurrentUserUid in the Resource Web service.
Guid impersonatedUserGuid = resProxyBySSP.GetCurrentUserUid();

Console.WriteLine(string.Format("\nImpersonating
'{0}':\n\tResourceProxy.Url:\n\t{1}",
userAccount, resProxyBySSP.Url));

Console.Write("\nImpersonated user GUID: ");
Console.WriteLine(impersonatedUserGuid.ToString());
}
catch (SoapException ex)
{
ExceptionHandlers.HandleSoapException(ex);
}
catch (WebException ex)
{
ExceptionHandlers.HandleWebException(ex);
}
catch (Exception ex)
{
ExceptionHandlers.HandleException(ex);
}
finally
{
ExceptionHandlers.ResetConsole();
}
Console.Write("Press any key...");
Console.ReadKey();
}


/// <summary>
/// Returns the GUID for a Project Server account name.
/// </summary>
/// <param name="ntAccount"></param>
/// <returns></returns>
private static Guid GetResourceUid(String accountName)
{
Resource resProxyByPWA = new Resource();
resProxyByPWA.Credentials = CredentialCache.DefaultCredentials;
// Before impersonation, use the Project Web Access URL.
resProxyByPWA.Url = PROJECT_SERVER_URI + RESOURCE_SERVICE_PATH;

ResourceDataSet rds = new ResourceDataSet();

// Filter for the account name, which can be a Windows or
Project Server account.
PSLibrary.Filter filter = new PSLibrary.Filter();
filter.FilterTableName = rds.Resources.TableName;

PSLibrary.Filter.Field accountField =
new PSLibrary.Filter.Field(rds.Resources.TableName,
rds.Resources.WRES_ACCOUNTColumn.ColumnName);
filter.Fields.Add(accountField);

PSLibrary.Filter.FieldOperator op =
new PSLibrary.Filter.FieldOperator(
PSLibrary.Filter.FieldOperationType.Equal,
rds.Resources.WRES_ACCOUNTColumn.ColumnName, accountName);
filter.Criteria = op;

Console.WriteLine("\nNot
impersonating:\n\tResourceProxy.Url:\n\t" + resProxyByPWA.Url);
rds =
(ResourceDataSet)(resProxyByPWA.ReadResources(filter.GetXml(), false));

// Return the account GUID
return (Guid)rds.Resources.Rows[0]["RES_UID"];
}
}

--------------------------------------------------------------------------------------------------

And here is the code from resourceDerived to set the impersonation headers:
--------------------------------------------------------------------------------------------------
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest webRequest = base.GetWebRequest(uri);
if (contextString != String.Empty)
{
webRequest.UseDefaultCredentials = true;

bool isImpersonating =

(System.Security.Principal.WindowsIdentity.GetCurrent(true) != null);
webRequest.Credentials = CredentialCache.DefaultCredentials;

webRequest.Headers.Add("PjAuth", contextString);
webRequest.Headers.Add("ForwardedFrom",
"/_vti_bin/psi/resource.asmx");

webRequest.PreAuthenticate = true;
}
return webRequest;
}
--------------------------------------------------------------------------------------------------

Because I can't use my development tools under a different
user name, I'm logged in as myself on the domain (Artsoft\Martijn).
I've given this account administrator priviliges on the machine where
project is installed (w2k8-01), in Project Web Access and for the Shared
Service Provider.
Then I've tried impersonation several users that were entered as resources
in Project:
W2k8-01\Piet
W2k8-01\Administrator
AspNetSqlMembershipProvider:piet
The result, for all of these is as follows:

Enter a valid Project Server user account, such as
domain\username or aspnetsqlmembershipprovider:username:
W2k8-01\Piet

Not impersonating:
ResourceProxy.Url:
http://w2k8-01/pwa/_vti_bin/psi/resource.asmx
User GUID to impersonate: 4c0c3396-5506-4bec-977a-c56e4822076b
Web Exception: The request failed with HTTP status 401: Unauthorized.

Log on, or check that Project Server is running.
Press any key...

:


Can you please post your code?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com





I'm trying to write an application that updates the actuals of assignments of
various resources in MS Project 2007 through the SOAP/PSI interface.

The statusing changexml function seems to do what I require, but only for
the currently logged in user.
After some investigation it appears that I'll to use impersonation to get
this to function properly.
I've been trying to get impersonation to work, but so far, no luck.
Neither my own code, nor the impersonationConsoleApp from the SDK appear to
be able to impersonate anybody.

I've added myself as administrator to the machine, and granted myself direct
access to the shared service provider using the sharepoint central admin site
and the stsadm command-line tool.
That not helping, I added <identity impersonatie="true"> to the system.web
section of the sharedservices site.

I have a Windows 2008 Server with IIS 7 and Project 2007.
My Project Web Access site is running at http://w2k8-01/pwa
My Shared Services site is running at http://w2k8-01:56737/sharedservices1
Now, if I understand this correctly, to make a call using impersonation, one
sends a SOAP request to
http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx (in the example, or
http://w2k8-01:56737/SharedServices1/PSI/Statusing.asmx for my own code)
This SOAP request has an pjAuth header from the PSContextInfo containing:
- the GUID of the account to impersonate
- the GUID of the Project Web Access site
and a ForwardedFrom header containing:
- "/_vti_bin/PSI/Resource.asmx"
The sharedservices site validates my credentials, then calls the Project Web
Access site (http://w2k8-01/pwa/_vti_bin/PSI/Resource.asmx) with the
 
M

M Stellinga

I checked and I see the handshake happening (request goes one way,
www-authenticate requests goes the other way, new request with NTLM header
goes back).

I found some information about logging failed requests in IIS and did that
too. I can't attach the resulting xml-trace-file, but I'll paste some of the
data of the second request (the one with NTLM header).
The headers seem to be there for impersonation and NTLM authentication:
14. i GENERAL_REQUEST_HEADERS Headers="Content-Length: 348
Content-Type: text/xml; charset=utf-8
Authorization: NTLM
TlRMTVNTUAADAAAAGAAYAHYAAAAYABgAjgAAAAwADABIAAAADgAOAFQAAAAUABQAYgAABBAAEACmAAAANYKI4gUBKAoAAAAPQQBFAE4ATwBWAEEATQBhAHIAdABpAGoAbgBBAFMALQBQAEEATgBEAE8AUgBBADzUp57Gn1xNAAAAAAAAAAAAAAAAAAAAAKmOzEtPhomoTraHzW/yOhAJz2yaTTDTFmBARfl55ApH2nOAiFqOlbU=
Expect: 100-continue
Host: w2k8-01:56737
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client
Protocol 2.0.50727.3082)
PjAuth:
un%3d%22w2k8-01%5cAdministrator%22+ug%3d%224c0c3396-5506-4bec-977a-c56e4822076b%22+tg%3d%2200000000-0000-0000-0000-000000000000%22+sg%3d%2212d3f676-aeb2-4a39-9a1e-ba85e66dcc6c%22+lc%3d%221033%22+wu%3d%22true%22+uz%3d%220%22+v%3d%220%22+
ForwardedFrom: /_vti_bin/psi/resource.asmx
SOAPAction:
"http://schemas.microsoft.com/office/project/server/webservices/Resource/GetCurrentUserUid"
"

I see myself being set as the NTLM authenticated user:
39. i USER_SET AuthType="NTLM", UserName="ARTSOFT\Martijn",
SupportsIsInRole="false"

After this, the isapi module is called and this returns a 401:
61. i GENERAL_ISAPI_HANDLER 13:05:34.188
62. i GENERAL_READ_ENTITY_START 13:05:34.188
63. i GENERAL_READ_ENTITY_END BytesReceived="348", ErrorCode="The operation
completed successfully.
(0x0)" 13:05:34.188
64. — GENERAL_REQUEST_ENTITY Buffer="<?xml version="1.0"
encoding="utf-8"?><soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetCurrentUserUid
xmlns="http://schemas.microsoft.com/office/project/server/webservices/Resource/" /></soap:Body></soap:Envelope>" 13:05:34.188
65. — NOTIFY_MODULE_START ModuleName="IsapiModule",
Notification="EXECUTE_REQUEST_HANDLER", fIsPostNotification="false",
fIsCompletion="true" 13:05:34.188
66. i ISAPI_START 13:05:34.188
67. i CALL_ISAPI_EXTENSION
DllName="C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"
13:05:34.188
68. i AspNetStart Data1="POST", Data2="/SharedServices1/PSI/Resource.asmx",
Data3=""
69. i AspNetReqQueued 13:05:34.188
70. i AspNetReqDequeued 13:05:34.188
71. — AspNetGetAppDomainEnter 13:05:34.188
72. — AspNetGetAppDomainLeave 13:05:34.188
73. — AspNetAppDomainEnter
Data1="/LM/W3SVC/1720207907/ROOT/SharedServices1-1-128897980034113203"
13:05:34.188
74. — AspNetStartHandler Data1="System.Web.HttpApplication", Data2="Start"
13:05:34.188
75. — AspNetPipelineEnter
Data1="System.Web.Security.WindowsAuthenticationModule" 13:05:34.188
76. — AspNetPipelineLeave
Data1="System.Web.Security.WindowsAuthenticationModule" 13:05:34.188
77. — AspNetPipelineEnter
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.188
78. — AspNetPipelineLeave
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.188
79. — AspNetPipelineEnter
Data1="System.Web.Security.DefaultAuthenticationModule" 13:05:34.188
80. — AspNetPipelineLeave
Data1="System.Web.Security.DefaultAuthenticationModule" 13:05:34.188
81. — AspNetPipelineEnter Data1="System.ServiceModel.Activation.HttpModule"
13:05:34.188
82. — AspNetPipelineLeave Data1="System.ServiceModel.Activation.HttpModule"
13:05:34.188
83. — AspNetPipelineEnter Data1="System.Web.Security.UrlAuthorizationModule"
13:05:34.188
84. — AspNetPipelineLeave Data1="System.Web.Security.UrlAuthorizationModule"
13:05:34.188
85. — AspNetPipelineEnter
Data1="System.Web.Security.FileAuthorizationModule" 13:05:34.188
86. — AspNetPipelineLeave
Data1="System.Web.Security.FileAuthorizationModule" 13:05:34.188
87. — AspNetPipelineEnter Data1="System.Web.Caching.OutputCacheModule"
13:05:34.188
88. — AspNetPipelineLeave Data1="System.Web.Caching.OutputCacheModule"
13:05:34.188
89. — AspNetMapHandlerEnter 13:05:34.188
90. — AspNetMapHandlerLeave 13:05:34.188
91. — AspNetPipelineEnter Data1="System.Web.SessionState.SessionStateModule"
13:05:34.188
92. i AspNetSessionDataBegin 13:05:34.188
93. i AspNetSessionDataEnd 13:05:34.188
94. — AspNetPipelineLeave Data1="System.Web.SessionState.SessionStateModule"
13:05:34.188
95. — AspNetPipelineEnter Data1="System.Web.Profile.ProfileModule"
13:05:34.188
96. — AspNetPipelineLeave Data1="System.Web.Profile.ProfileModule"
13:05:34.188
97. i AspNetHttpHandlerEnter 13:05:34.188
98. i AspNetHttpHandlerLeave 13:05:34.563
99. — AspNetPipelineEnter Data1="System.Web.SessionState.SessionStateModule"
13:05:34.563
100. — AspNetPipelineLeave
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
101. — AspNetPipelineEnter Data1="System.Web.Caching.OutputCacheModule"
13:05:34.563
102. — AspNetPipelineLeave Data1="System.Web.Caching.OutputCacheModule"
13:05:34.563
103. — AspNetPipelineEnter
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
104. — AspNetPipelineLeave
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
105. — AspNetPipelineEnter
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.563
106. — AspNetPipelineLeave
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.563
107. — AspNetPipelineEnter Data1="System.Web.Profile.ProfileModule"
13:05:34.563
108. — AspNetPipelineLeave Data1="System.Web.Profile.ProfileModule"
13:05:34.563
109. — AspNetEndHandler 13:05:34.563
110. r MODULE_SET_RESPONSE_ERROR_STATUS
Warning ModuleName="IsapiModule", Notification="EXECUTE_REQUEST_HANDLER",
HttpStatus="401", HttpReason="Unauthorized", HttpSubStatus="5",
ErrorCode="The operation completed successfully.
(0x0)", ConfigExceptionInfo="" 13:05:34.563
111. r MODULE_SET_RESPONSE_ERROR_STATUS
Warning ModuleName="IsapiModule", Notification="EXECUTE_REQUEST_HANDLER",
HttpStatus="401", HttpReason="Unauthorized", HttpSubStatus="5",
ErrorCode="The operation completed successfully.
(0x0)", ConfigExceptionInfo="" 13:05:34.563
....

Stephen Sanderlin said:
Try installing Fiddler2 and take look at the NTLM authentication
handshake... is the account that your code is trying to authenticate as
your user account, or some other account?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com



That's my own domain account (artsoft\Martijn) and yes, it has both
Administrator rights in the Project Server, on the machine Project Server is
running on, and for the shared service provider (through the web access of
the sharepoint administration center and by using the stsadm application).
Just to be on the safe side I even gave myself owner rights on the database.

I also tried to run the Console app from the machine itself (w2k8-01) as the
administrator (the account that installed everything), but that yielded the
same 401 reply.

:

Does the user you are running the console app as have administrator
permissions in Project Server?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com
This is the code from the ImpersonationConsoleApp from the Project SDK that
I've been trying to use as a baseline (I only edited the PSI_RESOURCE_SSP,
PROJECT_SERVER_URI, and PWA_SITE_GUID). The output when running this is below
it.

--------------------------------------------------------------------------------------------------
// During impersonation, use URLs for the PSI Web services in the Shared
Service Provider.
// The Shared Service Provider URLs go directly to the PSI, not
through Project Web Access.
private const string PSI_RESOURCE_SSP =
"http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx";

// Before impersonation, use the PSI through Project Web Access.
private const string PROJECT_SERVER_URI = "http://w2k8-01/pwa";
private const string RESOURCE_SERVICE_PATH =
"/_vti_bin/psi/resource.asmx";

// GUID of the Project Web Access site in SharePoint. **Change to
your value**
private const string PWA_SITE_GUID =
"12d3f676-aeb2-4a39-9a1e-ba85e66dcc6c";

static ResourceDerived resProxyBySSP;

static void Main(string[] args)
{
Console.WriteLine("Enter a valid Project Server user account,
such as");
Console.WriteLine(@"domain\username or
aspnetsqlmembershipprovider:username:");

string userAccount = Console.ReadLine();

try
{
resProxyBySSP = new ResourceDerived();

resProxyBySSP.Url = PSI_RESOURCE_SSP;
resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.
Guid userGuid = GetResourceUid(userAccount);
Console.WriteLine("User GUID to impersonate: " +
userGuid.ToString());

// You can also hard-code the user's Guid. Get the user's
Guid from the Published
// database or from the System Identification Data section
on the Manage User page
// in Project Web Access. For example:
// Guid userGuid = new
Guid("0154dd59-13fc-4f50-908e-5f24fa6ef785");

// To use the following code, the application must run on
the Project Server computer
// where Windows SharePoint Services is installed.
//
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// You can hard-code the siteId. Get the siteID in one of
the following two ways:
// a. Open the SharePoint ContentDB for the SSP. Open the
Webs table and
// get the SiteId where the FullUrl value is the name
of the
// Project Web Access instance, for example,
ProjectServerName.
// b. Open the Manage Project Web Access Sites page in
the SSP Admin site,
// click the drop-down list for the site and then
click Edit. The siteID
// is the GUID of the id option in the URL, for example:
//
http://ServerName:19466/ssp/admin/_...=Edit&id=44c4ae03-16c2-4618-bf9a-12643006c5be
//
// To use the following code, the application must run on
the Project Web
// Access computer. Set references to the
Microsoft.SharePoint and
// Microsoft.SharePoint.Search assemblies on the same
computer.
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// Otherwise, hard-code the site ID.
Guid siteId = new Guid(PWA_SITE_GUID);

resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.

bool isWindowsUser = true;
if (userAccount.Contains("aspnetsqlmembershipprovider"))
isWindowsUser = false;

ResourceDerived.SetImpersonationContext(isWindowsUser,
userAccount,
userGuid, Guid.Empty, siteId, "1033");

// To get the GUID of the user we are impersonating,
// call GetCurrentUserUid in the Resource Web service.
Guid impersonatedUserGuid = resProxyBySSP.GetCurrentUserUid();

Console.WriteLine(string.Format("\nImpersonating
'{0}':\n\tResourceProxy.Url:\n\t{1}",
userAccount, resProxyBySSP.Url));

Console.Write("\nImpersonated user GUID: ");
Console.WriteLine(impersonatedUserGuid.ToString());
}
catch (SoapException ex)
{
ExceptionHandlers.HandleSoapException(ex);
}
catch (WebException ex)
{
ExceptionHandlers.HandleWebException(ex);
}
catch (Exception ex)
{
ExceptionHandlers.HandleException(ex);
}
finally
{
ExceptionHandlers.ResetConsole();
}
Console.Write("Press any key...");
Console.ReadKey();
}


/// <summary>
/// Returns the GUID for a Project Server account name.
/// </summary>
/// <param name="ntAccount"></param>
/// <returns></returns>
private static Guid GetResourceUid(String accountName)
{
Resource resProxyByPWA = new Resource();
resProxyByPWA.Credentials = CredentialCache.DefaultCredentials;
// Before impersonation, use the Project Web Access URL.
resProxyByPWA.Url = PROJECT_SERVER_URI + RESOURCE_SERVICE_PATH;

ResourceDataSet rds = new ResourceDataSet();

// Filter for the account name, which can be a Windows or
Project Server account.
PSLibrary.Filter filter = new PSLibrary.Filter();
filter.FilterTableName = rds.Resources.TableName;

PSLibrary.Filter.Field accountField =
new PSLibrary.Filter.Field(rds.Resources.TableName,
rds.Resources.WRES_ACCOUNTColumn.ColumnName);
filter.Fields.Add(accountField);

PSLibrary.Filter.FieldOperator op =
new PSLibrary.Filter.FieldOperator(
PSLibrary.Filter.FieldOperationType.Equal,
rds.Resources.WRES_ACCOUNTColumn.ColumnName, accountName);
filter.Criteria = op;

Console.WriteLine("\nNot
impersonating:\n\tResourceProxy.Url:\n\t" + resProxyByPWA.Url);
rds =
(ResourceDataSet)(resProxyByPWA.ReadResources(filter.GetXml(), false));

// Return the account GUID
return (Guid)rds.Resources.Rows[0]["RES_UID"];
}
}

--------------------------------------------------------------------------------------------------

And here is the code from resourceDerived to set the impersonation headers:
--------------------------------------------------------------------------------------------------
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest webRequest = base.GetWebRequest(uri);
if (contextString != String.Empty)
{
webRequest.UseDefaultCredentials = true;

bool isImpersonating =

(System.Security.Principal.WindowsIdentity.GetCurrent(true) != null);
webRequest.Credentials = CredentialCache.DefaultCredentials;

webRequest.Headers.Add("PjAuth", contextString);
webRequest.Headers.Add("ForwardedFrom",
"/_vti_bin/psi/resource.asmx");

webRequest.PreAuthenticate = true;
}
return webRequest;
}
--------------------------------------------------------------------------------------------------

Because I can't use my development tools under a different
user name, I'm logged in as myself on the domain (Artsoft\Martijn).
I've given this account administrator priviliges on the machine where
project is installed (w2k8-01), in Project Web Access and for the Shared
Service Provider.
Then I've tried impersonation several users that were entered as resources
in Project:
W2k8-01\Piet
W2k8-01\Administrator
AspNetSqlMembershipProvider:piet
The result, for all of these is as follows:

Enter a valid Project Server user account, such as
domain\username or aspnetsqlmembershipprovider:username:
W2k8-01\Piet

Not impersonating:
ResourceProxy.Url:
http://w2k8-01/pwa/_vti_bin/psi/resource.asmx
User GUID to impersonate: 4c0c3396-5506-4bec-977a-c56e4822076b
Web Exception: The request failed with HTTP status 401: Unauthorized.

Log on, or check that Project Server is running.
Press any key...

:
Can you please post your code?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com
 
S

Stephen Sanderlin

This doesn't make any sense.

But, we now have something to go on... 401.5 is an ISAPI error. In this
case, it seems to be saying that the user account you are running as
does not have sufficient permissions inside SharePoint/PS to perform the
requested operation... but, that doesn't make sense, as your account is
an Administrator in Project Server (and accordingly should be a Web
Administrator for the SharePoint side of PWA). This, plus being a local
admin (which by default makes you a Farm admin) and you giving that
account access to the SSP means that you should have everything you
need.

What patchlevel are your WSS, MOSS (if installed), and PS07 installs
using? Do you have any kind of security lockdown configured on the
server?

Do you have UAC disabled? If not, have you tried disabling it and
attempting a repro?

Given your machine name, I'll assume you're using 2008... Can you please
look in IIS Manager and check the following:
1) Make sure that the application pools for your SP sites (including
Office Server Web Services) are using Classic rather than Integrated
mode
2) Make sure that the application pools for your SP sites (including
Office Server Web Services) are using v2.0 netfx

What happens if, when logged in as artsoft\martijn, you try to browse
(using IE) to http://w2k8-01/pwa/_vti_bin/psi/resource.asmx and
http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx? Are you able to
authenticate?

Can you try to repro the error after turning up the verbosity for the
Application and ULS logs to their maximum in Central Admin? Maybe
something in one of those logs will give us a clue as to what component
is unhappy or what permissions are missing.

One more thought for this post... have you tried rebooting and/or
clearing the SharePoint cache? Sometimes one or both of these in
combination will fix weird problems like this.

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read our blog at: http://www.projectserverhelp.com

Learn | Connect | Grow @ The Microsoft Project Conference
Phoenix, AZ ® September 14-17, 2009



I checked and I see the handshake happening (request goes one way,
www-authenticate requests goes the other way, new request with NTLM header
goes back).

I found some information about logging failed requests in IIS and did that
too. I can't attach the resulting xml-trace-file, but I'll paste some of the
data of the second request (the one with NTLM header).
The headers seem to be there for impersonation and NTLM authentication:
14. i GENERAL_REQUEST_HEADERS Headers="Content-Length: 348
Content-Type: text/xml; charset=utf-8
Authorization: NTLM
TlRMTVNTUAADAAAAGAAYAHYAAAAYABgAjgAAAAwADABIAAAADgAOAFQAAAAUABQAYgAABBAAEACmAAAANYKI4gUBKAoAAAAPQQBFAE4ATwBWAEEATQBhAHIAdABpAGoAbgBBAFMALQBQAEEATgBEAE8AUgBBADzUp57Gn1xNAAAAAAAAAAAAAAAAAAAAAKmOzEtPhomoTraHzW/yOhAJz2yaTTDTFmBARfl55ApH2nOAiFqOlbU=
Expect: 100-continue
Host: w2k8-01:56737
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client
Protocol 2.0.50727.3082)
PjAuth:
un%3d%22w2k8-01%5cAdministrator%22+ug%3d%224c0c3396-5506-4bec-977a-c56e4822076b%22+tg%3d%2200000000-0000-0000-0000-000000000000%22+sg%3d%2212d3f676-aeb2-4a39-9a1e-ba85e66dcc6c%22+lc%3d%221033%22+wu%3d%22true%22+uz%3d%220%22+v%3d%220%22+
ForwardedFrom: /_vti_bin/psi/resource.asmx
SOAPAction:
"http://schemas.microsoft.com/office/project/server/webservices/Resource/GetCurrentUserUid"
"

I see myself being set as the NTLM authenticated user:
39. i USER_SET AuthType="NTLM", UserName="ARTSOFT\Martijn",
SupportsIsInRole="false"

After this, the isapi module is called and this returns a 401:
61. i GENERAL_ISAPI_HANDLER 13:05:34.188
62. i GENERAL_READ_ENTITY_START 13:05:34.188
63. i GENERAL_READ_ENTITY_END BytesReceived="348", ErrorCode="The operation
completed successfully.
(0x0)" 13:05:34.188
64. — GENERAL_REQUEST_ENTITY Buffer="<?xml version="1.0"
encoding="utf-8"?><soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetCurrentUserUid
xmlns="http://schemas.microsoft.com/office/project/server/webservices/Resource/" /></soap:Body></soap:Envelope>" 13:05:34.188
65. — NOTIFY_MODULE_START ModuleName="IsapiModule",
Notification="EXECUTE_REQUEST_HANDLER", fIsPostNotification="false",
fIsCompletion="true" 13:05:34.188
66. i ISAPI_START 13:05:34.188
67. i CALL_ISAPI_EXTENSION
DllName="C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"
13:05:34.188
68. i AspNetStart Data1="POST", Data2="/SharedServices1/PSI/Resource.asmx",
Data3=""
69. i AspNetReqQueued 13:05:34.188
70. i AspNetReqDequeued 13:05:34.188
71. — AspNetGetAppDomainEnter 13:05:34.188
72. — AspNetGetAppDomainLeave 13:05:34.188
73. — AspNetAppDomainEnter
Data1="/LM/W3SVC/1720207907/ROOT/SharedServices1-1-128897980034113203"
13:05:34.188
74. — AspNetStartHandler Data1="System.Web.HttpApplication", Data2="Start"
13:05:34.188
75. — AspNetPipelineEnter
Data1="System.Web.Security.WindowsAuthenticationModule" 13:05:34.188
76. — AspNetPipelineLeave
Data1="System.Web.Security.WindowsAuthenticationModule" 13:05:34.188
77. — AspNetPipelineEnter
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.188
78. — AspNetPipelineLeave
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.188
79. — AspNetPipelineEnter
Data1="System.Web.Security.DefaultAuthenticationModule" 13:05:34.188
80. — AspNetPipelineLeave
Data1="System.Web.Security.DefaultAuthenticationModule" 13:05:34.188
81. — AspNetPipelineEnter Data1="System.ServiceModel.Activation.HttpModule"
13:05:34.188
82. — AspNetPipelineLeave Data1="System.ServiceModel.Activation.HttpModule"
13:05:34.188
83. — AspNetPipelineEnter Data1="System.Web.Security.UrlAuthorizationModule"
13:05:34.188
84. — AspNetPipelineLeave Data1="System.Web.Security.UrlAuthorizationModule"
13:05:34.188
85. — AspNetPipelineEnter
Data1="System.Web.Security.FileAuthorizationModule" 13:05:34.188
86. — AspNetPipelineLeave
Data1="System.Web.Security.FileAuthorizationModule" 13:05:34.188
87. — AspNetPipelineEnter Data1="System.Web.Caching.OutputCacheModule"
13:05:34.188
88. — AspNetPipelineLeave Data1="System.Web.Caching.OutputCacheModule"
13:05:34.188
89. — AspNetMapHandlerEnter 13:05:34.188
90. — AspNetMapHandlerLeave 13:05:34.188
91. — AspNetPipelineEnter Data1="System.Web.SessionState.SessionStateModule"
13:05:34.188
92. i AspNetSessionDataBegin 13:05:34.188
93. i AspNetSessionDataEnd 13:05:34.188
94. — AspNetPipelineLeave Data1="System.Web.SessionState.SessionStateModule"
13:05:34.188
95. — AspNetPipelineEnter Data1="System.Web.Profile.ProfileModule"
13:05:34.188
96. — AspNetPipelineLeave Data1="System.Web.Profile.ProfileModule"
13:05:34.188
97. i AspNetHttpHandlerEnter 13:05:34.188
98. i AspNetHttpHandlerLeave 13:05:34.563
99. — AspNetPipelineEnter Data1="System.Web.SessionState.SessionStateModule"
13:05:34.563
100. — AspNetPipelineLeave
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
101. — AspNetPipelineEnter Data1="System.Web.Caching.OutputCacheModule"
13:05:34.563
102. — AspNetPipelineLeave Data1="System.Web.Caching.OutputCacheModule"
13:05:34.563
103. — AspNetPipelineEnter
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
104. — AspNetPipelineLeave
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
105. — AspNetPipelineEnter
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.563
106. — AspNetPipelineLeave
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.563
107. — AspNetPipelineEnter Data1="System.Web.Profile.ProfileModule"
13:05:34.563
108. — AspNetPipelineLeave Data1="System.Web.Profile.ProfileModule"
13:05:34.563
109. — AspNetEndHandler 13:05:34.563
110. r MODULE_SET_RESPONSE_ERROR_STATUS
Warning ModuleName="IsapiModule", Notification="EXECUTE_REQUEST_HANDLER",
HttpStatus="401", HttpReason="Unauthorized", HttpSubStatus="5",
ErrorCode="The operation completed successfully.
(0x0)", ConfigExceptionInfo="" 13:05:34.563
111. r MODULE_SET_RESPONSE_ERROR_STATUS
Warning ModuleName="IsapiModule", Notification="EXECUTE_REQUEST_HANDLER",
HttpStatus="401", HttpReason="Unauthorized", HttpSubStatus="5",
ErrorCode="The operation completed successfully.
(0x0)", ConfigExceptionInfo="" 13:05:34.563
...

:

Try installing Fiddler2 and take look at the NTLM authentication
handshake... is the account that your code is trying to authenticate as
your user account, or some other account?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com



That's my own domain account (artsoft\Martijn) and yes, it has both
Administrator rights in the Project Server, on the machine Project Server is
running on, and for the shared service provider (through the web access of
the sharepoint administration center and by using the stsadm application).
Just to be on the safe side I even gave myself owner rights on the database.

I also tried to run the Console app from the machine itself (w2k8-01) as the
administrator (the account that installed everything), but that yielded the
same 401 reply.

:


Does the user you are running the console app as have administrator
permissions in Project Server?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com





This is the code from the ImpersonationConsoleApp from the Project SDK that
I've been trying to use as a baseline (I only edited the PSI_RESOURCE_SSP,
PROJECT_SERVER_URI, and PWA_SITE_GUID). The output when running this is below
it.

--------------------------------------------------------------------------------------------------
// During impersonation, use URLs for the PSI Web services in the Shared
Service Provider.
// The Shared Service Provider URLs go directly to the PSI, not
through Project Web Access.
private const string PSI_RESOURCE_SSP =
"http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx";

// Before impersonation, use the PSI through Project Web Access.
private const string PROJECT_SERVER_URI = "http://w2k8-01/pwa";
private const string RESOURCE_SERVICE_PATH =
"/_vti_bin/psi/resource.asmx";

// GUID of the Project Web Access site in SharePoint. **Change to
your value**
private const string PWA_SITE_GUID =
"12d3f676-aeb2-4a39-9a1e-ba85e66dcc6c";

static ResourceDerived resProxyBySSP;

static void Main(string[] args)
{
Console.WriteLine("Enter a valid Project Server user account,
such as");
Console.WriteLine(@"domain\username or
aspnetsqlmembershipprovider:username:");

string userAccount = Console.ReadLine();

try
{
resProxyBySSP = new ResourceDerived();

resProxyBySSP.Url = PSI_RESOURCE_SSP;
resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.
Guid userGuid = GetResourceUid(userAccount);
Console.WriteLine("User GUID to impersonate: " +
userGuid.ToString());

// You can also hard-code the user's Guid. Get the user's
Guid from the Published
// database or from the System Identification Data section
on the Manage User page
// in Project Web Access. For example:
// Guid userGuid = new
Guid("0154dd59-13fc-4f50-908e-5f24fa6ef785");

// To use the following code, the application must run on
the Project Server computer
// where Windows SharePoint Services is installed.
//
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// You can hard-code the siteId. Get the siteID in one of
the following two ways:
// a. Open the SharePoint ContentDB for the SSP. Open the
Webs table and
// get the SiteId where the FullUrl value is the name
of the
// Project Web Access instance, for example,
ProjectServerName.
// b. Open the Manage Project Web Access Sites page in
the SSP Admin site,
// click the drop-down list for the site and then
click Edit. The siteID
// is the GUID of the id option in the URL, for example:
//
http://ServerName:19466/ssp/admin/_...=Edit&id=44c4ae03-16c2-4618-bf9a-12643006c5be
//
// To use the following code, the application must run on
the Project Web
// Access computer. Set references to the
Microsoft.SharePoint and
// Microsoft.SharePoint.Search assemblies on the same
computer.
// Microsoft.SharePoint.SPSite site = new
SPSite(PROJECT_SERVER_URI);
// Guid siteId = site.ID;

// Otherwise, hard-code the site ID.
Guid siteId = new Guid(PWA_SITE_GUID);

resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.

bool isWindowsUser = true;
if (userAccount.Contains("aspnetsqlmembershipprovider"))
isWindowsUser = false;

ResourceDerived.SetImpersonationContext(isWindowsUser,
userAccount,
userGuid, Guid.Empty, siteId, "1033");

// To get the GUID of the user we are impersonating,
// call GetCurrentUserUid in the Resource Web service.
Guid impersonatedUserGuid = resProxyBySSP.GetCurrentUserUid();

Console.WriteLine(string.Format("\nImpersonating
'{0}':\n\tResourceProxy.Url:\n\t{1}",
userAccount, resProxyBySSP.Url));

Console.Write("\nImpersonated user GUID: ");
Console.WriteLine(impersonatedUserGuid.ToString());
}
catch (SoapException ex)
{
ExceptionHandlers.HandleSoapException(ex);
}
catch (WebException ex)
{
ExceptionHandlers.HandleWebException(ex);
}
catch (Exception ex)
{
ExceptionHandlers.HandleException(ex);
}
finally
{
ExceptionHandlers.ResetConsole();
}
Console.Write("Press any key...");
Console.ReadKey();
}


/// <summary>
/// Returns the GUID for a Project Server account name.
/// </summary>
/// <param name="ntAccount"></param>
/// <returns></returns>
private static Guid GetResourceUid(String accountName)
{
Resource resProxyByPWA = new Resource();
resProxyByPWA.Credentials = CredentialCache.DefaultCredentials;
// Before impersonation, use the Project Web Access URL.
resProxyByPWA.Url = PROJECT_SERVER_URI + RESOURCE_SERVICE_PATH;

ResourceDataSet rds = new ResourceDataSet();

// Filter for the account name, which can be a Windows or
Project Server account.
PSLibrary.Filter filter = new PSLibrary.Filter();
filter.FilterTableName = rds.Resources.TableName;

PSLibrary.Filter.Field accountField =
new PSLibrary.Filter.Field(rds.Resources.TableName,
rds.Resources.WRES_ACCOUNTColumn.ColumnName);
filter.Fields.Add(accountField);

PSLibrary.Filter.FieldOperator op =
new PSLibrary.Filter.FieldOperator(
PSLibrary.Filter.FieldOperationType.Equal,
rds.Resources.WRES_ACCOUNTColumn.ColumnName, accountName);
filter.Criteria = op;

Console.WriteLine("\nNot
impersonating:\n\tResourceProxy.Url:\n\t" + resProxyByPWA.Url);
rds =
(ResourceDataSet)(resProxyByPWA.ReadResources(filter.GetXml(), false));

// Return the account GUID
return (Guid)rds.Resources.Rows[0]["RES_UID"];
}
}

--------------------------------------------------------------------------------------------------

And here is the code from resourceDerived to set the impersonation headers:
--------------------------------------------------------------------------------------------------
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest webRequest = base.GetWebRequest(uri);
if (contextString != String.Empty)
{
webRequest.UseDefaultCredentials = true;

bool isImpersonating =

(System.Security.Principal.WindowsIdentity.GetCurrent(true) != null);
webRequest.Credentials = CredentialCache.DefaultCredentials;

webRequest.Headers.Add("PjAuth", contextString);
webRequest.Headers.Add("ForwardedFrom",
"/_vti_bin/psi/resource.asmx");

webRequest.PreAuthenticate = true;
}
return webRequest;
}
--------------------------------------------------------------------------------------------------

Because I can't use my development tools under a different
user name, I'm logged in as myself on the domain (Artsoft\Martijn).
I've given this account administrator priviliges on the machine where
project is installed (w2k8-01), in Project Web Access and for the Shared
Service Provider.
Then I've tried impersonation several users that were entered as resources
in Project:
W2k8-01\Piet
W2k8-01\Administrator
AspNetSqlMembershipProvider:piet
The result, for all of these is as follows:

Enter a valid Project Server user account, such as
domain\username or aspnetsqlmembershipprovider:username:
W2k8-01\Piet

Not impersonating:
ResourceProxy.Url:
http://w2k8-01/pwa/_vti_bin/psi/resource.asmx
User GUID to impersonate: 4c0c3396-5506-4bec-977a-c56e4822076b
Web Exception: The request failed with HTTP status 401: Unauthorized.

Log on, or check that Project Server is running.
Press any key...

:



Can you please post your code?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com
 
M

M Stellinga

I tried the things listed in the post below and still no dice.
I've installed all available Service Packs and hotfixes through Microsoft
update, so I don't think it's a patch problem. The Project server is at
version 12.0.0.6421 (SP2 I think).

I was able to test the Project SDK application and my own code on a EPM2007
installation of one of our customers, which worked flawlessly.
Whatever the problem is, it's clearly in the configuration of my test server
W2k8-01.

Since my code works, I have some more breathing space, so I've asked our
system administrators to reinstall the machine (with a copy of the posts in
this thread). Since they have more experience with Windows and IIS than I
have, I hope they'll be able to get it to work.

I'd like to thank you for all the help so far, and I might post again if I
still can't get things to work on a freshly installed machine.

Regards,
Martijn

Stephen Sanderlin said:
This doesn't make any sense.

But, we now have something to go on... 401.5 is an ISAPI error. In this
case, it seems to be saying that the user account you are running as
does not have sufficient permissions inside SharePoint/PS to perform the
requested operation... but, that doesn't make sense, as your account is
an Administrator in Project Server (and accordingly should be a Web
Administrator for the SharePoint side of PWA). This, plus being a local
admin (which by default makes you a Farm admin) and you giving that
account access to the SSP means that you should have everything you
need.

What patchlevel are your WSS, MOSS (if installed), and PS07 installs
using? Do you have any kind of security lockdown configured on the
server?

Do you have UAC disabled? If not, have you tried disabling it and
attempting a repro?

Given your machine name, I'll assume you're using 2008... Can you please
look in IIS Manager and check the following:
1) Make sure that the application pools for your SP sites (including
Office Server Web Services) are using Classic rather than Integrated
mode
2) Make sure that the application pools for your SP sites (including
Office Server Web Services) are using v2.0 netfx

What happens if, when logged in as artsoft\martijn, you try to browse
(using IE) to http://w2k8-01/pwa/_vti_bin/psi/resource.asmx and
http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx? Are you able to
authenticate?

Can you try to repro the error after turning up the verbosity for the
Application and ULS logs to their maximum in Central Admin? Maybe
something in one of those logs will give us a clue as to what component
is unhappy or what permissions are missing.

One more thought for this post... have you tried rebooting and/or
clearing the SharePoint cache? Sometimes one or both of these in
combination will fix weird problems like this.

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read our blog at: http://www.projectserverhelp.com

Learn | Connect | Grow @ The Microsoft Project Conference
Phoenix, AZ ® September 14-17, 2009



I checked and I see the handshake happening (request goes one way,
www-authenticate requests goes the other way, new request with NTLM header
goes back).

I found some information about logging failed requests in IIS and did that
too. I can't attach the resulting xml-trace-file, but I'll paste some of the
data of the second request (the one with NTLM header).
The headers seem to be there for impersonation and NTLM authentication:
14. i GENERAL_REQUEST_HEADERS Headers="Content-Length: 348
Content-Type: text/xml; charset=utf-8
Authorization: NTLM
TlRMTVNTUAADAAAAGAAYAHYAAAAYABgAjgAAAAwADABIAAAADgAOAFQAAAAUABQAYgAABBAAEACmAAAANYKI4gUBKAoAAAAPQQBFAE4ATwBWAEEATQBhAHIAdABpAGoAbgBBAFMALQBQAEEATgBEAE8AUgBBADzUp57Gn1xNAAAAAAAAAAAAAAAAAAAAAKmOzEtPhomoTraHzW/yOhAJz2yaTTDTFmBARfl55ApH2nOAiFqOlbU=
Expect: 100-continue
Host: w2k8-01:56737
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client
Protocol 2.0.50727.3082)
PjAuth:
un%3d%22w2k8-01%5cAdministrator%22+ug%3d%224c0c3396-5506-4bec-977a-c56e4822076b%22+tg%3d%2200000000-0000-0000-0000-000000000000%22+sg%3d%2212d3f676-aeb2-4a39-9a1e-ba85e66dcc6c%22+lc%3d%221033%22+wu%3d%22true%22+uz%3d%220%22+v%3d%220%22+
ForwardedFrom: /_vti_bin/psi/resource.asmx
SOAPAction:
"http://schemas.microsoft.com/office/project/server/webservices/Resource/GetCurrentUserUid"
"

I see myself being set as the NTLM authenticated user:
39. i USER_SET AuthType="NTLM", UserName="ARTSOFT\Martijn",
SupportsIsInRole="false"

After this, the isapi module is called and this returns a 401:
61. i GENERAL_ISAPI_HANDLER 13:05:34.188
62. i GENERAL_READ_ENTITY_START 13:05:34.188
63. i GENERAL_READ_ENTITY_END BytesReceived="348", ErrorCode="The operation
completed successfully.
(0x0)" 13:05:34.188
64. — GENERAL_REQUEST_ENTITY Buffer="<?xml version="1.0"
encoding="utf-8"?><soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetCurrentUserUid
xmlns="http://schemas.microsoft.com/office/project/server/webservices/Resource/" /></soap:Body></soap:Envelope>" 13:05:34.188
65. — NOTIFY_MODULE_START ModuleName="IsapiModule",
Notification="EXECUTE_REQUEST_HANDLER", fIsPostNotification="false",
fIsCompletion="true" 13:05:34.188
66. i ISAPI_START 13:05:34.188
67. i CALL_ISAPI_EXTENSION
DllName="C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"
13:05:34.188
68. i AspNetStart Data1="POST", Data2="/SharedServices1/PSI/Resource.asmx",
Data3=""
69. i AspNetReqQueued 13:05:34.188
70. i AspNetReqDequeued 13:05:34.188
71. — AspNetGetAppDomainEnter 13:05:34.188
72. — AspNetGetAppDomainLeave 13:05:34.188
73. — AspNetAppDomainEnter
Data1="/LM/W3SVC/1720207907/ROOT/SharedServices1-1-128897980034113203"
13:05:34.188
74. — AspNetStartHandler Data1="System.Web.HttpApplication", Data2="Start"
13:05:34.188
75. — AspNetPipelineEnter
Data1="System.Web.Security.WindowsAuthenticationModule" 13:05:34.188
76. — AspNetPipelineLeave
Data1="System.Web.Security.WindowsAuthenticationModule" 13:05:34.188
77. — AspNetPipelineEnter
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.188
78. — AspNetPipelineLeave
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.188
79. — AspNetPipelineEnter
Data1="System.Web.Security.DefaultAuthenticationModule" 13:05:34.188
80. — AspNetPipelineLeave
Data1="System.Web.Security.DefaultAuthenticationModule" 13:05:34.188
81. — AspNetPipelineEnter Data1="System.ServiceModel.Activation.HttpModule"
13:05:34.188
82. — AspNetPipelineLeave Data1="System.ServiceModel.Activation.HttpModule"
13:05:34.188
83. — AspNetPipelineEnter Data1="System.Web.Security.UrlAuthorizationModule"
13:05:34.188
84. — AspNetPipelineLeave Data1="System.Web.Security.UrlAuthorizationModule"
13:05:34.188
85. — AspNetPipelineEnter
Data1="System.Web.Security.FileAuthorizationModule" 13:05:34.188
86. — AspNetPipelineLeave
Data1="System.Web.Security.FileAuthorizationModule" 13:05:34.188
87. — AspNetPipelineEnter Data1="System.Web.Caching.OutputCacheModule"
13:05:34.188
88. — AspNetPipelineLeave Data1="System.Web.Caching.OutputCacheModule"
13:05:34.188
89. — AspNetMapHandlerEnter 13:05:34.188
90. — AspNetMapHandlerLeave 13:05:34.188
91. — AspNetPipelineEnter Data1="System.Web.SessionState.SessionStateModule"
13:05:34.188
92. i AspNetSessionDataBegin 13:05:34.188
93. i AspNetSessionDataEnd 13:05:34.188
94. — AspNetPipelineLeave Data1="System.Web.SessionState.SessionStateModule"
13:05:34.188
95. — AspNetPipelineEnter Data1="System.Web.Profile.ProfileModule"
13:05:34.188
96. — AspNetPipelineLeave Data1="System.Web.Profile.ProfileModule"
13:05:34.188
97. i AspNetHttpHandlerEnter 13:05:34.188
98. i AspNetHttpHandlerLeave 13:05:34.563
99. — AspNetPipelineEnter Data1="System.Web.SessionState.SessionStateModule"
13:05:34.563
100. — AspNetPipelineLeave
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
101. — AspNetPipelineEnter Data1="System.Web.Caching.OutputCacheModule"
13:05:34.563
102. — AspNetPipelineLeave Data1="System.Web.Caching.OutputCacheModule"
13:05:34.563
103. — AspNetPipelineEnter
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
104. — AspNetPipelineLeave
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
105. — AspNetPipelineEnter
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.563
106. — AspNetPipelineLeave
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.563
107. — AspNetPipelineEnter Data1="System.Web.Profile.ProfileModule"
13:05:34.563
108. — AspNetPipelineLeave Data1="System.Web.Profile.ProfileModule"
13:05:34.563
109. — AspNetEndHandler 13:05:34.563
110. r MODULE_SET_RESPONSE_ERROR_STATUS
Warning ModuleName="IsapiModule", Notification="EXECUTE_REQUEST_HANDLER",
HttpStatus="401", HttpReason="Unauthorized", HttpSubStatus="5",
ErrorCode="The operation completed successfully.
(0x0)", ConfigExceptionInfo="" 13:05:34.563
111. r MODULE_SET_RESPONSE_ERROR_STATUS
Warning ModuleName="IsapiModule", Notification="EXECUTE_REQUEST_HANDLER",
HttpStatus="401", HttpReason="Unauthorized", HttpSubStatus="5",
ErrorCode="The operation completed successfully.
(0x0)", ConfigExceptionInfo="" 13:05:34.563
...

:

Try installing Fiddler2 and take look at the NTLM authentication
handshake... is the account that your code is trying to authenticate as
your user account, or some other account?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com
That's my own domain account (artsoft\Martijn) and yes, it has both
Administrator rights in the Project Server, on the machine Project Server is
running on, and for the shared service provider (through the web access of
the sharepoint administration center and by using the stsadm application).
Just to be on the safe side I even gave myself owner rights on the database.

I also tried to run the Console app from the machine itself (w2k8-01) as the
administrator (the account that installed everything), but that yielded the
same 401 reply.

:
Does the user you are running the console app as have administrator
permissions in Project Server?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com
This is the code from the ImpersonationConsoleApp from the Project SDK that
I've been trying to use as a baseline (I only edited the PSI_RESOURCE_SSP,
PROJECT_SERVER_URI, and PWA_SITE_GUID). The output when running this is below
it.

--------------------------------------------------------------------------------------------------
// During impersonation, use URLs for the PSI Web services in the Shared
Service Provider.
// The Shared Service Provider URLs go directly to the PSI, not
through Project Web Access.
private const string PSI_RESOURCE_SSP =
"http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx";

// Before impersonation, use the PSI through Project Web Access.
private const string PROJECT_SERVER_URI = "http://w2k8-01/pwa";
private const string RESOURCE_SERVICE_PATH =
"/_vti_bin/psi/resource.asmx";

// GUID of the Project Web Access site in SharePoint. **Change to
your value**
private const string PWA_SITE_GUID =
"12d3f676-aeb2-4a39-9a1e-ba85e66dcc6c";

static ResourceDerived resProxyBySSP;

static void Main(string[] args)
{
Console.WriteLine("Enter a valid Project Server user account,
such as");
Console.WriteLine(@"domain\username or
aspnetsqlmembershipprovider:username:");

string userAccount = Console.ReadLine();

try
{
resProxyBySSP = new ResourceDerived();

resProxyBySSP.Url = PSI_RESOURCE_SSP;
resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.
Guid userGuid = GetResourceUid(userAccount);
Console.WriteLine("User GUID to impersonate: " +
userGuid.ToString());

// You can also hard-code the user's Guid. Get the user's
Guid from the Published
// database or from the System Identification Data section
 
S

Stephen Sanderlin [MVP]

Martijn,

No problem at all. I'm happy to help. I'm sorry that you weren't able to
get your test server working, but if you do figure out what the problem
was, please post the resolution!

Steve

--
Stephen Sanderlin, Project MVP
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read our blog at: http://www.projectserverhelp.com

Learn | Connect | Grow @ The Microsoft Project Conference
Phoenix, AZ R September 14-17, 2009



I tried the things listed in the post below and still no dice.
I've installed all available Service Packs and hotfixes through Microsoft
update, so I don't think it's a patch problem. The Project server is at
version 12.0.0.6421 (SP2 I think).

I was able to test the Project SDK application and my own code on a EPM2007
installation of one of our customers, which worked flawlessly.
Whatever the problem is, it's clearly in the configuration of my test server
W2k8-01.

Since my code works, I have some more breathing space, so I've asked our
system administrators to reinstall the machine (with a copy of the posts in
this thread). Since they have more experience with Windows and IIS than I
have, I hope they'll be able to get it to work.

I'd like to thank you for all the help so far, and I might post again if I
still can't get things to work on a freshly installed machine.

Regards,
Martijn

:

This doesn't make any sense.

But, we now have something to go on... 401.5 is an ISAPI error. In this
case, it seems to be saying that the user account you are running as
does not have sufficient permissions inside SharePoint/PS to perform the
requested operation... but, that doesn't make sense, as your account is
an Administrator in Project Server (and accordingly should be a Web
Administrator for the SharePoint side of PWA). This, plus being a local
admin (which by default makes you a Farm admin) and you giving that
account access to the SSP means that you should have everything you
need.

What patchlevel are your WSS, MOSS (if installed), and PS07 installs
using? Do you have any kind of security lockdown configured on the
server?

Do you have UAC disabled? If not, have you tried disabling it and
attempting a repro?

Given your machine name, I'll assume you're using 2008... Can you please
look in IIS Manager and check the following:
1) Make sure that the application pools for your SP sites (including
Office Server Web Services) are using Classic rather than Integrated
mode
2) Make sure that the application pools for your SP sites (including
Office Server Web Services) are using v2.0 netfx

What happens if, when logged in as artsoft\martijn, you try to browse
(using IE) to http://w2k8-01/pwa/_vti_bin/psi/resource.asmx and
http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx? Are you able to
authenticate?

Can you try to repro the error after turning up the verbosity for the
Application and ULS logs to their maximum in Central Admin? Maybe
something in one of those logs will give us a clue as to what component
is unhappy or what permissions are missing.

One more thought for this post... have you tried rebooting and/or
clearing the SharePoint cache? Sometimes one or both of these in
combination will fix weird problems like this.

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read our blog at: http://www.projectserverhelp.com

Learn | Connect | Grow @ The Microsoft Project Conference
Phoenix, AZ R September 14-17, 2009



I checked and I see the handshake happening (request goes one way,
www-authenticate requests goes the other way, new request with NTLM header
goes back).

I found some information about logging failed requests in IIS and did that
too. I can't attach the resulting xml-trace-file, but I'll paste some of the
data of the second request (the one with NTLM header).
The headers seem to be there for impersonation and NTLM authentication:
14. i GENERAL_REQUEST_HEADERS Headers="Content-Length: 348
Content-Type: text/xml; charset=utf-8
Authorization: NTLM
TlRMTVNTUAADAAAAGAAYAHYAAAAYABgAjgAAAAwADABIAAAADgAOAFQAAAAUABQAYgAABBAAEACmAAAANYKI4gUBKAoAAAAPQQBFAE4ATwBWAEEATQBhAHIAdABpAGoAbgBBAFMALQBQAEEATgBEAE8AUgBBADzUp57Gn1xNAAAAAAAAAAAAAAAAAAAAAKmOzEtPhomoTraHzW/yOhAJz2yaTTDTFmBARfl55ApH2nOAiFqOlbU=
Expect: 100-continue
Host: w2k8-01:56737
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client
Protocol 2.0.50727.3082)
PjAuth:
un%3d%22w2k8-01%5cAdministrator%22+ug%3d%224c0c3396-5506-4bec-977a-c56e4822076b%22+tg%3d%2200000000-0000-0000-0000-000000000000%22+sg%3d%2212d3f676-aeb2-4a39-9a1e-ba85e66dcc6c%22+lc%3d%221033%22+wu%3d%22true%22+uz%3d%220%22+v%3d%220%22+
ForwardedFrom: /_vti_bin/psi/resource.asmx
SOAPAction:
"http://schemas.microsoft.com/office/project/server/webservices/Resource/GetCurrentUserUid"
"

I see myself being set as the NTLM authenticated user:
39. i USER_SET AuthType="NTLM", UserName="ARTSOFT\Martijn",
SupportsIsInRole="false"

After this, the isapi module is called and this returns a 401:
61. i GENERAL_ISAPI_HANDLER 13:05:34.188
62. i GENERAL_READ_ENTITY_START 13:05:34.188
63. i GENERAL_READ_ENTITY_END BytesReceived="348", ErrorCode="The operation
completed successfully.
(0x0)" 13:05:34.188
64. - GENERAL_REQUEST_ENTITY Buffer="<?xml version="1.0"
encoding="utf-8"?><soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetCurrentUserUid
xmlns="http://schemas.microsoft.com/office/project/server/webservices/Resource/" /></soap:Body></soap:Envelope>" 13:05:34.188
65. - NOTIFY_MODULE_START ModuleName="IsapiModule",
Notification="EXECUTE_REQUEST_HANDLER", fIsPostNotification="false",
fIsCompletion="true" 13:05:34.188
66. i ISAPI_START 13:05:34.188
67. i CALL_ISAPI_EXTENSION
DllName="C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"
13:05:34.188
68. i AspNetStart Data1="POST", Data2="/SharedServices1/PSI/Resource.asmx",
Data3=""
69. i AspNetReqQueued 13:05:34.188
70. i AspNetReqDequeued 13:05:34.188
71. - AspNetGetAppDomainEnter 13:05:34.188
72. - AspNetGetAppDomainLeave 13:05:34.188
73. - AspNetAppDomainEnter
Data1="/LM/W3SVC/1720207907/ROOT/SharedServices1-1-128897980034113203"
13:05:34.188
74. - AspNetStartHandler Data1="System.Web.HttpApplication", Data2="Start"
13:05:34.188
75. - AspNetPipelineEnter
Data1="System.Web.Security.WindowsAuthenticationModule" 13:05:34.188
76. - AspNetPipelineLeave
Data1="System.Web.Security.WindowsAuthenticationModule" 13:05:34.188
77. - AspNetPipelineEnter
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.188
78. - AspNetPipelineLeave
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.188
79. - AspNetPipelineEnter
Data1="System.Web.Security.DefaultAuthenticationModule" 13:05:34.188
80. - AspNetPipelineLeave
Data1="System.Web.Security.DefaultAuthenticationModule" 13:05:34.188
81. - AspNetPipelineEnter Data1="System.ServiceModel.Activation.HttpModule"
13:05:34.188
82. - AspNetPipelineLeave Data1="System.ServiceModel.Activation.HttpModule"
13:05:34.188
83. - AspNetPipelineEnter Data1="System.Web.Security.UrlAuthorizationModule"
13:05:34.188
84. - AspNetPipelineLeave Data1="System.Web.Security.UrlAuthorizationModule"
13:05:34.188
85. - AspNetPipelineEnter
Data1="System.Web.Security.FileAuthorizationModule" 13:05:34.188
86. - AspNetPipelineLeave
Data1="System.Web.Security.FileAuthorizationModule" 13:05:34.188
87. - AspNetPipelineEnter Data1="System.Web.Caching.OutputCacheModule"
13:05:34.188
88. - AspNetPipelineLeave Data1="System.Web.Caching.OutputCacheModule"
13:05:34.188
89. - AspNetMapHandlerEnter 13:05:34.188
90. - AspNetMapHandlerLeave 13:05:34.188
91. - AspNetPipelineEnter Data1="System.Web.SessionState.SessionStateModule"
13:05:34.188
92. i AspNetSessionDataBegin 13:05:34.188
93. i AspNetSessionDataEnd 13:05:34.188
94. - AspNetPipelineLeave Data1="System.Web.SessionState.SessionStateModule"
13:05:34.188
95. - AspNetPipelineEnter Data1="System.Web.Profile.ProfileModule"
13:05:34.188
96. - AspNetPipelineLeave Data1="System.Web.Profile.ProfileModule"
13:05:34.188
97. i AspNetHttpHandlerEnter 13:05:34.188
98. i AspNetHttpHandlerLeave 13:05:34.563
99. - AspNetPipelineEnter Data1="System.Web.SessionState.SessionStateModule"
13:05:34.563
100. - AspNetPipelineLeave
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
101. - AspNetPipelineEnter Data1="System.Web.Caching.OutputCacheModule"
13:05:34.563
102. - AspNetPipelineLeave Data1="System.Web.Caching.OutputCacheModule"
13:05:34.563
103. - AspNetPipelineEnter
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
104. - AspNetPipelineLeave
Data1="System.Web.SessionState.SessionStateModule" 13:05:34.563
105. - AspNetPipelineEnter
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.563
106. - AspNetPipelineLeave
Data1="System.Web.Security.PassportAuthenticationModule" 13:05:34.563
107. - AspNetPipelineEnter Data1="System.Web.Profile.ProfileModule"
13:05:34.563
108. - AspNetPipelineLeave Data1="System.Web.Profile.ProfileModule"
13:05:34.563
109. - AspNetEndHandler 13:05:34.563
110. r MODULE_SET_RESPONSE_ERROR_STATUS
Warning ModuleName="IsapiModule", Notification="EXECUTE_REQUEST_HANDLER",
HttpStatus="401", HttpReason="Unauthorized", HttpSubStatus="5",
ErrorCode="The operation completed successfully.
(0x0)", ConfigExceptionInfo="" 13:05:34.563
111. r MODULE_SET_RESPONSE_ERROR_STATUS
Warning ModuleName="IsapiModule", Notification="EXECUTE_REQUEST_HANDLER",
HttpStatus="401", HttpReason="Unauthorized", HttpSubStatus="5",
ErrorCode="The operation completed successfully.
(0x0)", ConfigExceptionInfo="" 13:05:34.563
...

:


Try installing Fiddler2 and take look at the NTLM authentication
handshake... is the account that your code is trying to authenticate as
your user account, or some other account?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com





That's my own domain account (artsoft\Martijn) and yes, it has both
Administrator rights in the Project Server, on the machine Project Server is
running on, and for the shared service provider (through the web access of
the sharepoint administration center and by using the stsadm application).
Just to be on the safe side I even gave myself owner rights on the database.

I also tried to run the Console app from the machine itself (w2k8-01) as the
administrator (the account that installed everything), but that yielded the
same 401 reply.

:



Does the user you are running the console app as have administrator
permissions in Project Server?

--
Stephen Sanderlin
VP of Technology
MSProjectExperts

For Project Server Consulting: http://www.msprojectexperts.com
For Project Server Training: http://www.projectservertraining.com

Read my blog at: http://www.projectserverhelp.com
Join the community at: http://forums.epmfaq.com






This is the code from the ImpersonationConsoleApp from the Project SDK that
I've been trying to use as a baseline (I only edited the PSI_RESOURCE_SSP,
PROJECT_SERVER_URI, and PWA_SITE_GUID). The output when running this is below
it.

--------------------------------------------------------------------------------------------------
// During impersonation, use URLs for the PSI Web services in the Shared
Service Provider.
// The Shared Service Provider URLs go directly to the PSI, not
through Project Web Access.
private const string PSI_RESOURCE_SSP =
"http://w2k8-01:56737/SharedServices1/PSI/Resource.asmx";

// Before impersonation, use the PSI through Project Web Access.
private const string PROJECT_SERVER_URI = "http://w2k8-01/pwa";
private const string RESOURCE_SERVICE_PATH =
"/_vti_bin/psi/resource.asmx";

// GUID of the Project Web Access site in SharePoint. **Change to
your value**
private const string PWA_SITE_GUID =
"12d3f676-aeb2-4a39-9a1e-ba85e66dcc6c";

static ResourceDerived resProxyBySSP;

static void Main(string[] args)
{
Console.WriteLine("Enter a valid Project Server user account,
such as");
Console.WriteLine(@"domain\username or
aspnetsqlmembershipprovider:username:");

string userAccount = Console.ReadLine();

try
{
resProxyBySSP = new ResourceDerived();

resProxyBySSP.Url = PSI_RESOURCE_SSP;
resProxyBySSP.Credentials =
System.Net.CredentialCache.DefaultCredentials;

// Get the GUID of the user to impersonate.
Guid userGuid = GetResourceUid(userAccount);
Console.WriteLine("User GUID to impersonate: " +
userGuid.ToString());

// You can also hard-code the user's Guid. Get the user's
Guid from the Published
// database or from the System Identification Data section
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top