Showing posts with label Security. Show all posts
Showing posts with label Security. Show all posts

Thursday, 9 June 2022

Integrating Google Cloud reCAPTCHA Enterprise in PHP

Google Cloud reCAPTCHA Enterprise is the successor (?) to reCAPTCHA v3. 

The code snippets Google supplies for integrating reCATPCHA Enterprise in PHP are frustratingly uncohesive and neither a working demo or complete code sample exists (as far as I can find at the time of writing). 

Moreover, the code snippets that are provided were incomplete for my implementation and the number of moving parts (Cloud projects, keys and credentials) is nothing short of overwhelming. 

Given the above, I struggled for some time just get everything working--which is where I'm up to now. So a disclaimer for those of you readers who are proficient PHP developers and who possess a deeper understanding of the Google Cloud Platform, please use this as a starting point only. There may be a better (more refined) approach. 

In terms of the official documentation and the code snippets I refer to above and will discuss in this post, start here: https://cloud.google.com/recaptcha-enterprise/docs/choose-key-type

I should also note I'm working in a basic web hosting environment with PHP installed. It's not a Google environment--think more budget web host ;)

Setup

Before you can get started, you'll need to login to the Google Cloud Platform, create a new project if you don't have a suitable already, and create a reCAPTCHA Enterprise key. Save the key somewhere and take note of your Cloud project ID while you're there as we'll need that later. You'll find your project ID on the relevant dashboard card. 

Incidentally, you can follow the link to reCAPTCHA Enterprise in the documentation to get to where you need to be in the Google Cloud Platform (or just navigate to Menu > Security > reCAPTCHA Enterprise). 

Once that's done, you may want to hop into Menu > APIs and services. If the reCAPTCHA Enterprise API isn't already enabled, find it in the library and enable it. While you're here, you'll also want to create credentials. This is where things are still a bit blurry for me but I created both an API key and a service account. The API key isn't used in my final code and it's possibly not necessary. I'm just used to API keys, I guess! 

The service account basically receives a name and ID and is then assigned the reCAPTCHA Agent role (locate reCAPTCAHA Enterprise in the list of products and services and then select the reCAPTCHA Agent role). 

Once the service account exists, I chose to create a key ("Manage keys"). Google will warn you about the risks of downloading service account keys and suggests using Workload Identity Federation--I don't yet know what this is so do you own homework here. I created a new key (ADD KEY > Create new key) as a .json file--you'll be prompted to download/save this file and I'd suggest storing a copy in a safe place as I have yet to find a way to download this same file again in future. 

Code

With that setup done, we now move into the code. The code runs clients side and server side and is comprised of your HTML page (including a form), a couple of scripts in the HEAD tag and some attributes on the form button. And of course the PHP code. 

Be sure to add your reCAPTCHA Enterprise key to both the script tag in the head and the data-sitekey attribute on your button. It's also required in the call to create_assessment() in the PHP code. 

I'll point out that, in my case, I want to trigger a score-based reCAPTCHA assessment when a user submits a form--no sooner and not unecessarily. I'm therefore using the relevant Google examples here, combined into a single, cohesive file. 

The HTML and script source is taken from this page: https://cloud.google.com/recaptcha-enterprise/docs/instrument-web-pages 


Note the PHP code is slightly modified to include the putenv call, which references the JSON key file we created earlier. You'll also want to drop in your Google Cloud Platform project ID in the call to create_assessment(). 

<html>
<head>
	<script src="https://www.google.com/recaptcha/enterprise.js?render=your_recaptcha_key"></script>
	<script>
	   function onSubmit(token) {
		 document.getElementById("demo-form").submit();
	   }
	</script>
</head>
<body>
<form id="demo-form" method="post">
<input type="text" />
<button class="g-recaptcha"
data-sitekey="your_recaptcha_key"
data-callback='onSubmit'
data-action='submit'>Submit</button>
</form>
</body>
</html>

<?php

require 'google-re/vendor/autoload.php';

use Google\Cloud\RecaptchaEnterprise\V1\RecaptchaEnterpriseServiceClient;
use Google\Cloud\RecaptchaEnterprise\V1\Event;
use Google\Cloud\RecaptchaEnterprise\V1\Assessment;
use Google\Cloud\RecaptchaEnterprise\V1\TokenProperties\InvalidReason;

/**
* Create an assessment to analyze the risk of a UI action.
* @param string $siteKey The key ID for the reCAPTCHA key (See https://cloud.google.com/recaptcha-enterprise/docs/create-key)
* @param string $token The user's response token for which you want to receive a reCAPTCHA score. (See https://cloud.google.com/recaptcha-enterprise/docs/create-assessment#retrieve_token)
* @param string $project Your Google Cloud project ID
*/
function create_assessment(
  string $siteKey,
  string $token,
  string $project
): void {
	
  // *** I added this line ***
  putenv('GOOGLE_APPLICATION_CREDENTIALS=your-service-account-key-file.json');
    
  // TODO: To avoid memory issues, move this client generation outside
  // of this example, and cache it (recommended) or call client.close()
  // before exiting this method.
  $client = new RecaptchaEnterpriseServiceClient();

  $projectName = $client->projectName($project);

  $event = (new Event())
	  ->setSiteKey($siteKey)
	  ->setToken($token);

  $assessment = (new Assessment())
	  ->setEvent($event);

  try {
	  $response = $client->createAssessment(
		  $projectName,
		  $assessment
	  );

	  // You can use the score only if the assessment is valid,
	  // In case of failures like re-submitting the same token, getValid() will return false
	  if ($response->getTokenProperties()->getValid() == false) {
		  printf('The CreateAssessment() call failed because the token was invalid for the following reason: ');
		  printf(InvalidReason::name($response->getTokenProperties()->getInvalidReason()));
	  } else {
		  printf('The score for the protection action is:');
		  printf($response->getRiskAnalysis()->getScore());

		  // Optional: You can use the following methods to get more data about the token
		  // Action name provided at token generation.
		  // printf($response->getTokenProperties()->getAction() . PHP_EOL);
		  // The timestamp corresponding to the generation of the token.
		  // printf($response->getTokenProperties()->getCreateTime()->getSeconds() . PHP_EOL);
		  // The hostname of the page on which the token was generated.
		  // printf($response->getTokenProperties()->getHostname() . PHP_EOL);
	  }
  } catch (exception $e) {
	  printf('CreateAssessment() call failed with the following error: ');
	  printf($e);
  }
}

   create_assessment(
      'YOUR_RECAPTCHA_SITE_KEY',
      $_POST['g-recaptcha-response'], // Safety first! Do you trust this code?
      'YOUR_GOOGLE_CLOUD_PROJECT_ID'
    );
?>

Drop all of the above in a file named whatever.php and upload it to your web server. Before any of this will run on your server, you'll need to attend to some dependencies. 

Upload your .json key file alongside your .php file (or put it somewhere else on the server and amend the putenv path in the PHP code). This file may warrant additional protections. 

With that sorted, you need to fetch all of the Google Cloud files the PHP above depends on. You'll likely want to do this using Composer (which needs to be installed on your desktop) and you can then run this command in a command window: 

composer require google/cloud-recaptcha-enterprise

I'll note I'm only fetching the reCAPTCHA Enterprise bits here--not the entire Google Cloud file set. You do you. 

I saved all of the Google files in a directory named google-re, which you'll see referenced in the first line our PHP. Adjust as required. 

A final note for the FileZilla users out there: when uploading the Google dependencies in particular, you may encounter a horrible runtime exception ("Fail to push limit") if you don't configure the FileZilla transfer type as Binary (Transfer > Transfer type > Binary). Refer to the answer to this question for more information: https://groups.google.com/g/protobuf/c/8_S93nJWxUE?pli=1

Run It

And now you should be able to request your page, submit the button. All being well, you'll encounter no exceptions and receive a nice meessage like "The score for the protection action is:0.89999997615814". Use that and other, related assessment information to act accordingly.  

I hope that helps someone!


Thursday, 31 August 2017

How to access KeePass passwords from Chrome

Installing KeePassHttp with a browser extension isn’t difficult. Here are the simple steps:

  1. If your portable KeePass 2.x directory doesn’t have a “Plugins” directory, create it.
  2. Download the KeePassHttp.plgx file from GitHub (you’ll find a link to this file under the heading Non-Windows / Manual Windows Installation)—there’s no need to build, install Chocolately, etc. Save the .plgx file to your KeePass Plugins directory and restart KeePass if running.
  3. Add to the chromelPass extension to Chrome and click the button to connect. In KeePass, you’ll be prompted to name the key request which comes from the Chrome extension—I called mine chromelPass.
  4. Generate unique passwords to replace the single password you use everywhere.

Sunday, 16 April 2017

How to specify credentials to restart or shutdown a remote host with ‘net use’

I recently wanted to shutdown a server on my local network (notably a workgroup) using the Windows shutdown command but encountered an access denied error (or no feedback whatsoever).

I needed to use the administrator credentials of the remote server but shutdown.exe doesn’t accept credentials.

Using ‘net use’ to connect to the IPC$ share on remote host, you can set then call shutdown in that security context:

net use \\hostname\IPC$ mypassword /User:administrator
shutdown /r /t 60 /m \\hostname /f

In the net use command above, replace hostname with the name of your remote host (or maybe an IP address), replace mypassword with the password for the account you’re using, and replace administrator with the name of the local account on the remote host you wish to use (which presumably has the necessary rights to restart or shutdown the server).

In the shutdown command above, replace hostname with the name of your remote host, as per the net use command.

Note: Read the shutdown /? usage. The /r flag will restart the host; change /r to /s if you want to shutdown instead. Other parameters can also be specified. I also typically set the timeout (/t) flag to 0 (zero).

I call both commands back-to-back in a Windows Command Prompt, without running the console as Admin.

See below for a few more tips, links, and PowerShell alternatives.

If you’re used to operating as a domain user you may be asking why any of this is even necessary. It’s necessary in a workgroup context because the remote host has no idea who I am if I just tell it to shutdown from some other computer on the local IP network. It may be possible to an account on one host the necessary privileges on another host but I don’t know for certain and, in my limited experience, this can get hard and weird very quickly!

I used to run a domain controller on my small local network (just for fun) and all of my servers were members of a domain, which made security easy. I got rid of the DC as DHCP and other services were migrated to my internet router and to streamline things. In all regards, having one less server to manage, power, and so on is great. I’ll run a virtualised AD when I need to, e.g. for development purposes).

In addition to a media centre, I also still run a physical file server, primarily for backups. My basic process is to power on the file server once a week to backup the media centre, my laptop, etc and then shut it down again (so the kids don’t fiddle and to keep the noise down).

The backup process is otherwise seamless—the backup services on the file server and clients just pick up where they left off and run to completion without any human interaction (I use CrashPlan and would highly recommend it). I only need to power on the file server and then shut it down.

To shut down, I’d previously connect to the file server via Remote Desktop and then shut down. But that’s too hard. I can tell from the backup client on my laptop when a backup is complete so I just want to quickly shutdown the file server and go to bed.

In a domain environment, I could make sure my domain account was a member of the Administrators group on the file server and then call shutdown.exe from a command prompt on my laptop; without the DC, I need to explicitly provide shutdown.exe with the necessary credentials before actually calling shutdown.exe.

A few other notes: the file server is running Windows Server 2012 and my laptop is running Windows 8.1.

In recent versions of Windows (i.e. 2012+), I’ve read that UAC may interfere with things. You may want to turn it off but can simply add or configure this registry key (I didn’t have to):

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
Value: LocalAccountTokenFilterPolicy
Data: 1 (to disable) or 0 (to enables filtering)
Type: REG_DWORD (32-bit)

You may need to restart after making this change.

Thank to https://helgeklein.com/blog/2011/08/access-denied-trying-to-connect-to-administrative-shares-on-windows-7/ for this one. See also this Microsoft help article (ID 951016) “Description of User Account Control and remote restrictions in Windows Vista”

Others suggested File and Printer sharing must be allowed in the Windows Firewall.

I believe PowerShell offers similar restart (and stop) commands. I haven’t tried them and can’t say whether they work with the techniques described here but I believe both accept a –credential parameter.

See these references:

https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.management/restart-computer

https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.management/stop-computer

Wednesday, 12 January 2011

How to change the service accounts used by TFS 2010

As with many Microsoft products running with specific service accounts, TFS offers an easy way to change the service account it uses or update the account password.

You can do this manually by mucking with application pool identities and database permissions but there's a much easier way using the TFS Administration Console.

Assuming you have the right permissions, fire up the console and click into the Application Tier node; in the Application Tier Summary you'll find two links: Change Account and Reapply Account.

tfs_change_account

Change Account allows you to change the service account used by the system while Reapply Account allows you to change the password for the currently configured account. You can easily switch from Network Service to a local or domain account (or vice versa) but be sure to grant any local/domain account the Log on as service permission.

If you found this post helpful, please support my advertisers.

Thursday, 28 October 2010

Free Antivirus for Windows Server 2008

I've been a long time home user of Avast! antivirus. It's a great product that doesn't bog down my machine. Unfortunately the free home edition won't install on Windows Server 2008 R2 and I run a single-boot W2k8 environment because of my Hyper-V love affair.

Don't get me wrong, I normally despise AV and security in any form… the guys I work with are probably fed up with me always shouting "security != productivity" when the bloody proxy policy has once again broken something or prevented me doing my job. But, every now and then, I feel incline to download evil things and God forbid those things include a virus of some kind—a quick scan would then come in handy…

ClamWin to the rescue! Don't know about the name but it doesn't include a real-time scanner which meets my requirements. So far so good… evil things downloaded and appear to be virus free!

Friday, 3 September 2010

Forefront Identity Manager Service fails to start after reboot

Update [28/09/2010]: Spence recently released a follow-up article to the Rational Guide… in which he discusses an additional change for those of us using SQL Server aliases. Check out the section entitled "Using a SQL Server Named Instance" and scoot down to the local DTC configuration steps. I haven't tried this yet myself but it sounds promising.

Update [27/10/2010]: I see Spence has updated the above-mentioned article to include a section about this problem which validates the solution presented here.

After following Spence Harbar's Rational Guide to implementing SharePoint Server 2010 User Profile Synchronization, I was able to not only get the UPS service started but I was also able to run a sync on my first attempt. I probably got lucky ;-)

The one small hiccup I had along the way was getting the Forefront Identity Manager Service to start following a reboot; the service simply refused to start automatically despite being configured by SharePoint/FIM to do so. Interestingly, both the User Profile Service and the User Profile Synchronization Service items listed in Central Admin's Services on Server page listed the services as running. Starting the FIM Service manually from the Windows Services snapin succeeded (I didn't try directly through CA) but felt hacky and annoying.

What to do? Since the Synchronization Service was starting successfully and I could manually start the service after logging in, I assume this has to be some kind of dependency issue between the services themselves or SQL Server (some of the event log error message listed below definitely take issue with SQL).

Update 29/09/2010: After examining the sequence of event log entries relating to MSSQLSERVER and FIM, I can clearly see SQL is NOT ready to accept client connections by the time the FIM services kick in. I should point out my test environment is running as a single-server farm (AD, SQL, IIS, SharePoint, etc) so I'd definitely pay attention to Spence's follow-up article I note above in the 28/09 update.

My solution was to therefore set both services to start automatically at boot time after a delay by reconfiguring the startup type of BOTH services and Automatic (Delayed Start) in the Windows Services snapin:

FIM-Delayed-Start

Interestingly, I found the FIM Service starts before the FIM Sync Service, fwiw. I also still have one error remaining stating The Forefront Identity Manager Service cannot connect to the SQL Database Server but it doesn't prevent the services from starting or a sync from running.

So is this an inappropriate change to make? I can't say, especially with everyone and their dog saying "let SharePoint manage these services, don't start 'em manually!" In a single-server environment, I'll suggest it is acceptable. I know for certain both services now start automatically after a minute or so (once all other services set to just Automatic have started) and I can still run a profile sync; the following errors are also no longer present:

Log Name:      Application
Source:        Forefront Identity Manager
Date:          3/09/2010 12:37:17 PM
Event ID:      3
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      dev-sps2010-01.dev.mediawhole.com
Description:
.Net SqlClient Data Provider: System.Data.SqlClient.SqlException: Cannot open database "Sync DB" requested by the login. The login failed.
Login failed for user 'DEV\SVC_SPFARM'.
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK)
   at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, Int64 timerExpire, SqlConnection owningObject)
   at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(String host, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, Int64 timerStart)
   at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance)
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)
   at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at Microsoft.ResourceManagement.Data.DatabaseConnection.Open(SqlConnection connection)

Log Name:      Application
Source:        Forefront Identity Manager
Date:          3/09/2010 12:37:17 PM
Event ID:      3
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      dev-sps2010-01.dev.mediawhole.com
Description:
.Net SqlClient Data Provider: System.Data.SqlClient.SqlException: Cannot open database "Sync DB" requested by the login. The login failed.
Login failed for user 'DEV\SVC_SPFARM'.
   at Microsoft.ResourceManagement.Data.Exception.DataAccessExceptionManager.ThrowException(SqlException innerException)
   at Microsoft.ResourceManagement.Data.DatabaseConnection.Open(SqlConnection connection)
   at Microsoft.ResourceManagement.Data.DatabaseConnection.Open(DataStore store)

Log Name:      Application
Source:        Microsoft.ResourceManagement.ServiceHealthSource
Date:          3/09/2010 12:37:17 PM
Event ID:      26
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      dev-sps2010-01.dev.mediawhole.com
Description:
The Forefront Identity Manager Service was not able to initialize a timer necessary for supporting the execution of workflows.

Upon startup, the Forefront Identity Manager Service must initialize and set a timer to support workflow execution.  If this timer fails to get created, workflows will not run successfully and there is no recovery other than to stop and start the Forefront Identity Manager Service.

Restart the Forefront Identity Manager Service.

Log Name:      Application
Source:        Microsoft.ResourceManagement.ServiceHealthSource
Date:          3/09/2010 12:37:17 PM
Event ID:      2
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      dev-sps2010-01.dev.mediawhole.com
Description:
The Forefront Identity Manager Service could not bind to its endpoints.  This failure prevents clients from communicating with the Web services.

A most likely cause for the failure is another service, possibly another instance of Forefront Identity Manager Service, has already bound to the endpoint.  Another, less likely cause, is that the account under which the service runs does not have permission to bind to endpoints.

Ensure that no other processes have bound to that endpoint and that the service account has permission to bind endpoints.  Further, check the application configuration file to ensure the Forefront Identity Manager Service is binding to the correct endpoints.

Log Name:      Application
Source:        Forefront Identity Manager
Date:          3/09/2010 12:37:17 PM
Event ID:      3
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      dev-sps2010-01.dev.mediawhole.com
Description:
.Net SqlClient Data Provider: System.Data.SqlClient.SqlException: Cannot open database "Sync DB" requested by the login. The login failed.
Login failed for user 'DEV\SVC_SPFARM'.
   at Microsoft.ResourceManagement.Data.Exception.DataAccessExceptionManager.ThrowException(SqlException innerException)
   at Microsoft.ResourceManagement.Data.DatabaseConnection.Open(SqlConnection connection)
   at Microsoft.ResourceManagement.Data.DatabaseConnection.Open(DataStore store)
   at Microsoft.ResourceManagement.Data.TransactionAndConnectionScope..ctor(Boolean createTransaction, IsolationLevel isolationLevel, DataStore dataStore)
   at Microsoft.ResourceManagement.Data.TransactionAndConnectionScope..ctor(Boolean createTransaction)
   at Microsoft.ResourceManagement.Data.DataAccess.RegisterService(String hostName)
   at Microsoft.ResourceManagement.Workflow.Hosting.HostActivator.RegisterService(String hostName)
   at Microsoft.ResourceManagement.Workflow.Hosting.HostActivator.Initialize()
   at Microsoft.ResourceManagement.WebServices.ResourceManagementServiceHostFactory.CreateServiceHost(String constructorString, Uri[] baseAddresses)
   at Microsoft.ResourceManagement.WindowsHostService.OnStart(String[] args)

Log Name:      Application
Source:        Microsoft Resource Management Service
Date:          3/09/2010 12:37:17 PM
Event ID:      0
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      dev-sps2010-01.dev.mediawhole.com
Description:
Service cannot be started. System.Data.SqlClient.SqlException: Cannot open database "Sync DB" requested by the login. The login failed.
Login failed for user 'DEV\SVC_SPFARM'.
   at Microsoft.ResourceManagement.WindowsHostService.OnStart(String[] args)
   at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object state)

If you found this post helpful, please support my advertisers.

Troubleshooting user profile sync via FIM

Your initial foray into SharePoint 2010 user profile sync will likely lead you to the FIM client and, if you're anything like me, your mind will boggle at what FIM is, why it has to be involved at all, and where to start when things to horribly wrong.

I won't attempt to enlighten you on the first two subjects but I do want to point out some interesting and non-intuitive FIM user interface screens you may not be aware of and that will help you determine if your UPS setup is on the right path. By the way, you can run the FIM client as soon as the two FIM services are running on your machine (in other words, as soon as UPS has been provisioned but before you run a sync).

If you've got the UPS service in a running state, the next thing you'll likely want to do is run your first (or 50th) sync; in addition to the dodgy status screen within Central Admin itself, you can fire up the FIM client to watch from the bushes (the Operations view) as SharePoint, FIM, SQL Server, and AD do their magic dance. A successful run includes ten operations in my dev environment and I've previously posted a screen shot of this if you're interested.

If you look carefully, the operations view will reveal the user name involved with each operation and list some partition info as well. To dive in deeper, click the Management Agents button in the top menu; in my case, I'm presented with three MAs (if you've got more because you've been struggling with connections, you may be in trouble):

  • The first MA named ILMMA connects to the database I specified when setting up UPS ("Sync DB")
  • The second MA named MOSS-{GUID} connects to the ProfileImportExportService web service
  • The final MA named MOSSAD-{name of my connection as configured in CA} connects to Active Directory

FIM MAsBy viewing the properties for each MA (right-click on an MA and select Properties from the context menu or use the Actions pane to the right of the window) I can also examine specific properties to determine exactly what domain name FIM is configured to use and the accounts used to interact with AD, SQL Server, and the web service:

ILMMA-Properties MOSSAD-ConnectionName-Properties MOSSAD-ConnectionName-Directory-Partitions

The attentive reader will note there's a lot of farm account action going on here and that's because both FIM services are configured to log on as the farm account and my understanding is they have to be because of the way the relevant timer job(s), which are also run as the farm account, interact with these services (says Spence). I'll also point out my svc_spups account is the account to which I've granted Replicating Directory Changes in AD.

If you found this post helpful, please support my advertisers.

Thursday, 2 September 2010

Testing database connectivity

Developer that I am, I've gone so far as to write throwaway console apps to test connectivity to a database server as a different user; hopefully I'll never have to do that again after learning about this really cool trick:

  • Create a new text file and change the extension to .udl
  • Double-click it
  • Select a provider, configure the options to connect and hit Test Connection (note the Use a specific user name and password option means SQL authentication; entering an AD account here will fail).
  • Start a console window as another user and execute the .udl file to connect as someone else using integrated security if necessary
  • Having ruled a security issue in or out, fix the problem!

UDL-database-connection 

A massive shout out to Todd Klindt for sharing this in one of his recent netcasts!!!

Ps. "OK" through to persist the connection details in the form of a connection string to your text file. Kinda helpful!

If you found this post helpful, please support my advertisers.

Wednesday, 1 September 2010

Where to find the FIM Client (miisclient.exe)

Note to self and anyone else who cares… you'll find the FIM client (aka miisclient) at the following location:

C:\Program Files\Microsoft Office Servers\14.0\Synchronization Service\UIShell\miisclient.exe

Use it to debug SharePoint 2010 user profile synchronisation.

Thursday, 22 July 2010

SharePoint 403 Forbidden and /bin directory read access

We've run a post-deployment script in our SharePoint environment for many years now to address a 403 Forbidden error that otherwise plagues us; the script grants the Authenticated Users account read access on the web application's bin directory and web.config file (for both the authenticated and anonymous sites).

Someone deemed this necessary back in the day and, until recently, I always assumed it was just some quirk with our crusty environment. That was until I came across the same problem at another client site where custom code (in a SharePoint solution) was being deployed.

With that as motivation, I decided to figure out why we do what we do and determined a .NET 2.0 security update from July 2007 introduced the problem:

The performance of the server may decrease and adding users or uploading files may fail with the error message "403 Forbidden error" after you install a Microsoft .NET Framework 2.0 hotfix.

The security update links to a SharePoint 2007 hotfix:

In SharePoint Server 2007, the performance of the server may decrease, and you cannot upload files or add users. Additionally, you may receive the following error message:

403 Forbidden error

This issue occurs after you install a Microsoft .NET Framework version 2.0 hotfix that is build 2.0.50727.832 or a later build.

In the www.westernaustralia.com context, the problem normally crops up when an anonymous user requests a page that runs custom code; with my second client, the problem occurred in the authenticated site when a content editor with full permission over the site collection attempted to access a SharePoint list. The 403 response seemed to be intermittent but I suspect it was application recycles correcting the problem for a short while. As a user with local admin rights on the WFE, I wasn't seeing the problem myself.

Apparently uninstalling the update may be an option but I wonder if it's been incorporated into .NET 3.5 so that may not be possible in this day and age.

Anyway, the consensus around this problem is that it's caused when a request from an authenticated user without local admin rights results in a failed read of the /bin directory by the impersonating w3wp.exe process (as evidenced by filemon.exe). The solution is to ensure the Authenticated Users group has read access to the /bin directory below C:\inetpub\wwwroot\wss\VirtualDirectories\{your app}

Notably, we've found this permission needs to be reapplied as part of every deployment and often find permissions have reset after touching the Authentication providers settings in Central Admin.

Monday, 4 January 2010

Enable ICMP echo (ping) in Windows Server 2008 R2

Windows Server 2008 won’t respond to ping requests out of the box—they’re blocked by default in the Windows Firewall ruleset. In the pre-R2 days, I used a simple command to enable ping in my development environments but apparently netsh firewall has been deprecated:

netsh firewall set icmpsetting 8

The replacement is—wait for it—netsh advfirewall firewall, like so:

netsh advfirewall firewall add rule name=”ICMP Allow incoming V4 echo request” protocol=icmpv4:8,any dir=in action=allow

Richard Siddaway has a PowerShell equivalent (presumably, I haven’t tried it myself but should have, I know… tsk, tsk).

 
 

Wednesday, 24 June 2009

The MOSS setup account must be a member of db_owner role of the content database

One of the first things I normally do after creating a new web application and site collection is backup the content database using stsadm -o backup. If you're running in a least privilege scenario, however, there's an extra step required to configure access to the content database.

Whenever I'm working interactively with MOSS in an administrative capacity, I'm logged in as the MOSS setup account. This is the account used to install MOSS and create the farm; it’s also a member of the local admin and WSS_ADMIN_WPG groups, a member of the Farm Administrators group, and I've even got it configured as the primary site collection administrator for my content databases. In general, this account gives me the permissions I need to do everything I need to do while keeping my MOSS install functional.

Despite the wealth of permissions granted to this account, I was surprised when I tried running the stsadm -o backup command and came up against this error:

Cannot open database "WSS_Content_APP" requested by the login. The login failed.
Login failed for user 'domain\moss_setup'.

A similar, dodgier message was echoed in the Application event log.

To work around this, the setup account must be added to the db_owner role of the content database being backed up:

Navigate to the {WSS_Content DB}\Security\Roles\Database Roles\db_owner role and view its properties
Add the Setup account (eg. domain\moss_setup) as a Role Member

I've found no other role will suffice. Note in a least privilege scenario, the setup account should not be a member of the local admin group on the database server.

I'd love to know how to do this automatically whenever a new content database is added although I can understand why MOSS doesn’t do this for me… sort of ;-)

Database not found

While attempting to run the stsadm -o backup command as the MOSS setup user for the first time in a new environment today, I came across an error message in the application event log:

Event Type:    Error
Event Source:    Windows SharePoint Services 3
Event Category:    Database
Event ID:    3760
Description:
SQL Database 'WSS_Content_APP' on SQL Server instance 'MOSSSQL' not found. Additional error information from SQL Server is included below.

Cannot open database "WSS_Content_APP" requested by the login. The login failed.
Login failed for user 'domain\moss_setup'.

I wasn't careful when I first read the message and only read the first line. As MOSSSQL is actually a SQL Server alias to a physical server and this is the first time I've used aliases, I initially wondered if the backup command or stsadm was unable to deal with alias. That's silly, of course, because I've never told MOSS which physical server is underlies the alias and it only knows about the alias.

I'm not sure exactly how MOSS and SQL together track down the WSS_Content_APP database but the crux of this error message lies in the second part as flagged by SQL Server. In my case, the moss_setup account required access to the content database--but that's another blog post.

Friday, 15 May 2009

Blocking SharePoint Designer from Accessing Your Site

In a recent TechEd discussion panel comment, my favourite SharePoint MVP Eric Shupps mentions the ability to block SharePoint Designer from connecting to a SharePoint server and modifying content.

Why is SharePoint Designer a bad thing?

  • It’s free; every man and his dog can download it, potentially install it, and potentially break your sites
  • It can potentially be used against production—which if you follow a regimented deployment process is all wrong as changes can be made any ol’ time
  • It customises (or ghosts, if you prefer) pages thereby severing the link between the artefacts you’ve conscientiously built into a solution package and featurised;  uncustomising these artefacts may not be possible, depending on the changes that were made, or you’ll need another way to fix things up.
  • Artefacts created by SPD are created in the content database and can’t be moved easily between environments (eg. from dev to UAT to prod)
  • It modifies your files and injects stupid attributes that only it cares about
  • It’s buggy and it sucks and crashes and it’s too complicated for business analysts and too wrong for developers and it’s FrontPage rebranded and so on.

Eric’s comment got me digging and I found this new tool on CodePlex that installs a feature allowing admins and content editors to disable access to a site using SPD. Although a site definition can be altered directly to limit access by SPD this won’t affect existing sites, can’t be unlimited at any point in the future using any obvious mechanism, and is all a bit weird.

No SharePoint Designer is implemented as an HTTP Handler so it doesn’t touch the content database or much of anything. It’s still early days but definitely a “watch this space” kind of effort.

An alternative tool uses AD groups to limit access and this approach uses group policy to simply block SPD from running (and this MSDN blog entry is comprehensive if nothing else!).

Resources:

http://www.msteched.com/online/view.aspx?tid=efa154e2-6c06-4a76-ab3c-e9d71ebf0ff2
http://nospd.codeplex.com/
http://support.microsoft.com/default.aspx/kb/940958
http://blogs.msdn.com/sharepointdesigner/archive/2008/11/25/locking-down-sharepoint-designer.aspx

Monday, 16 March 2009

Presenting at the next SharePoint User Group Presentation

Just a reminder I’ll be delivering part two of my two-part presentation on how we do web content management on MOSS 2007 this Tuesday at 12:30pm. We had a great turnout for the first presentation so it will be interesting to see who comes back!! Honestly, it’s amazing how many of you SharePoint/MOSS guys I’ve met through the first presentation and I’m really looking forward to bumping into a few more of you—please come up and say hello!

The blurb on the user group site is a straight copy of the part one blurb so here’s what I’ll be talking about tomorrow:

westernaustralia.com was one of the first public-facing MOSS 2007-based internet sites launched in Australia and is billed as the Western Australia Tourism Commission’s flagship web site. Two years on and thirty MCMS 2002-based tourism sites are now being migrated to the MOSS 2007 platform. In the second segment of this two part presentation, Michael Hanes, the Development Coordinator/Tech Lead at Tourism WA, talks about the backend MOSS environments. In this presentation Michael presents the existing and replacement hardware environments, virtualisation, environment structure, farm configuration, security, site collection structure and variations, performance, tooling, content delivery (Akamai), and content deployment.

Jeremy’s aiming to record the presentation again so, all being well, the part two webcast will be available after the event in case you’re unable to come along.

Here’s part one in case you missed it. See you down there for part two!!

[Update: a vodcast of the presentation is now available here with a PDF of the slides and notes here.]

[Update: the original PowerPoint deck is now available.]

Sunday, 1 March 2009

Opening a Port in the Windows 2008 Firewall

When doing quick and dirty MOSS development in my dev environment, I favour creating new web applications on a non-standard port over using port 80 and host headers. Why? I’ve been working that way for a long time and it’s just easy… no other reason, really!

Because I’m now running on a non-standard port, the Windows 2008 firewall won’t like me anymore. And to tell you the truth, while I like the idea of a strong, configurable firewall baked into the operating system, I’m not up to speed on its intricacies… so the feeling is mutual. Nevertheless, I’ve got to deal with this beast and expose access to my new web site. I bounce back and forth between my virtual server and other machines so having the site accessible is handy.


My previous encounter with this firewall was to enable echo (ping) requests, which I ended up doing through the command line:


netsh firewall set icmpsetting 8 enable


Update
Don't forget to check out my post on enabling PING in Windows Server 2008 R2.

Nice—but today I want to play with the UI.


The Windows Firewall UI is accessible from the Control Panel menu as Windows Firewall and from the Administrative Tools menu as Windows Firewall with Advanced Security. The Control Panel applet is very similar to the regular old Windows Firewall applet (think XP) so choose the Administrative Tools version—it’s got all the goodies.


From that point it’s all about rules and you’ll see Microsoft has taken the liberty of setting up lots and lots of rules for you (paranoid?). You could potentially modify one of these existing rules but while mucking around I noticed some are “predefined” and cannot be changed (in particular, see Inbound Rules/World Wide Web Service (HTTP Traffic-In… there are two of these, one for port 80 and one for port 443 or SSL).

So that’s the background, now here’s how to add a new rule for your new web application:

  1. On the Inbound Rules node, right-click and select New Rule… and the New Inbound Rule Wizard will fire up
  2. On the Rule Type screen, select Port
  3. On the Protocol and Ports screen, ensure TCP is selected and add your port(s) to the Specific local ports list
  4. On the Action screen, ensure Allow the connection is enabled
  5. On the Profile screen, select all or whichever profiles apply to your environment (Private is probably fine)
  6. On the Name screen, supply your new rule with a name and a description for future reference. Finish out the wizard.
Or make life easily repeatable and use the command line:

netsh firewall add portopening protocol=TCP port=30000 name="SharePoint 30000" mode=ENABLE scope=ALL profile=STANDARD


Thursday, 13 November 2008

Fixing the IE7/MOSS/HTTP 413/Client SSL/View State White Screen of Death

Content on the Tourism WA partner sites like Australia's Golden Outback needs to be accessible by content editors over the internet. To facilitate this, we use client certificates over SSL to authenticate users. Each certificate is additionally mapped to an Active Directory account to support granular control over specific assets and provide standard "auditing" (in the MOSS version history sense) of user activity. Users additionally benefit from a single sign-on experience since IE hands off the client certificate in a relatively seamless manner.
In the image below the first box describes how client certifcates are created and provided to the content editors; the second box describes how IE and IIS authenticate the user to MOSS via AD.

This approach looks pretty nice on paper apart from the manual task of creating the client certificate and the potential distribution security. Our external content editor user base is fairly small and well-known, however.

Following the launch of the first partner site using this security model, we came across a painful situation I'll describe here but hope you never encounter in the field. If you have come across this problem, hopefully this post will steer you in the right direction. 

So the problem: 

When attempting to save, check in, or publish a page, IE content editors were presented with a white screen (a page with nothing in it, more specifically) in a relatively short timeframe. The problem appeared to be sporadic and definitely affect some pages but not others.

Inspecting the content editor's machine revealed no hardware or software issues and nothing was logged to the client's event logs. The HTML source was nothing special with the IE Dev Toolbar telling the same story:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=windows-1252"></HEAD>
<BODY></BODY></HTML>

Although some basic IE security and JS settings were tweaked, friendly error messages were already turned off. As our initial user base was regionally-based and we mistakenly believed we couldn't reproduce the problem on the local network, we initially ascribed the problem to a lousy, congested regional network connection. I say we mistakenly believed we couldn't reproduce the problem because we generally use the non-SSL-secured internal site at head office due to an unrelated issue. 

This wasn't a lot to go on and we struggled to diagnose the problem while waiting for the installation of a WAN accellerator upgrade to our own regional office to prove or disprove our theory about the network infrastructure. Meanwhile, our third partner site came online and the content editors logged the same issue; this time, those content editors were sitting in Perth on metropolitain ADSL 2+ wires.

With the installation of a broadband connection at home I decided to see what I could find out outside the corporate environment. I logged into to one of the secure sites and got lucky--I was finally able to reproduce the problem on one of every five or so attempts to save a rather large page. 

With that achievement under my hat I fired up my trusty friend Fiddler 2 and reloaded the site. As I mentioned above, the partner sites are delivered to content editors over an SSL-secured (443) connection; in other words, that means inspecting the HTML request/response data outside the browser would normally be a bit tricky. Luckily Fiddler 2 makes this easy--you simply need to check the Decrypt HTTPS traffic checkbox in the Fiddler settings (under Proxy Settings) and Fiddler will present you with the goods. 

In my case that was step one but step 2 meant I'd also have to hand over a valid client certificate since Fiddler essentially does the man in the middle thing to pull off the SSL decryption bit. Fiddler's documentation is pretty good on this subject so after exporting my existing certificate with a .cer extension I dropped it into My Documents\Fiddler2\ClientCertificate.cer (named exactly as shown). At long last I could not only reproduce the problem but I could even see under the covers of the HTTP protocol!

And it was that simple: hitting the same problem page a few times and Fiddler told me it was all about a lousy HTTP 413 error--all this for a bloody error code IE should have been showing me in the first place. 

Here's the request:

POST /en/ThisPageIsTroubba.aspx HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/x-shockwave-flash, application/x-silverlight, application/x-silverlight-2-b2, */*
Referer: https://edit.problemsite.com/en/ThisPageIsTroubba.aspx
Accept-Language: en-au,en-GB;q=0.5
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Host: edit.problemsite.com
Content-Length: 71069
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: WSS_KeepSessionAuthenticated=443; MSOWebPartPage_AnonymousAccessCookie=443; s_cc=true; s_sq=%5B%5BB%5D%5D
 
HTTP/1.1 413 Request Entity Too Large
Content-Length: 0
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Sun, 02 Nov 2008 10:47:22 GMT
Connection: close

"What is an HTTP 413 error," I asked, just like you may be doing now? It means the server rejected the request because it considered it too big. Weird, considering the request was only just over 71KB but at least we could rule out the network--a good thing because a lot of our future content editors are very much regional.

The w3c tells us the following about HTTP 413:

"The server is refusing to process a request because the request entity is larger than the server is willing or able to process. The server MAY close the connection to prevent the client from continuing the request.
 
If the condition is temporary, the server SHOULD include a Retry- After header field to indicate that it is temporary and after what time the client MAY try again."

I mentioned page weight previously and the title of this posting also ties in viewstate. Why? I've already suggested the white screen problem seemed to affect some pages but not others. While investigating this problem, I noted the viewstate on most of the anonymous partner site pages is very low at a <2KB.

Still with me? 

We're currently running on Windows 2003 and IIS 6.0. When IIS has to deal with client certificates, the server uses the UploadReadAheadSize metabase property during the SSL preload process to determine the maximum buffer size for the incoming request. The default buffer size is 48KB to prevent denial of service attacks and for that reason Microsoft doesn't recommend setting it too high. In our case, the 71KB request was considered too large and IIS wouldn't let it through. Why the save/check-in/publish worked sporadically I can't say, but increasing the value assigned to this property instantly fixed the problem. We increased this setting on every relevant IIS web site using this command:

cscript adsutil.vbs set w3svc/1/uploadreadaheadsize 204800

Note the setting represents bytes, not kilobytes, and the TechNet article on changing this is incorrectly specifies a value of 200.

In theory the HTTP 413 should have come up in the server logs but if it did, we never caught it. 

For more information about the metabase changes, the following blog posts may be of use:

Custom-Built Microsoft Office SharePoint Server 2007 Branded Sites and Webpart Development - info@mediawole.com

Tuesday, 27 November 2007

stsadm restore Results in Access Denied 0x80070005

Restoring a content database using stsadm -o restore usually works pretty well. We use this command to restore content backups from our authoring environment to our local development environments.

Because our authoring environment is administered by one of the operations guys, however, I frequently receive an Access Denied error from stsadm that reads like this:

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

The 12 Hive log file offers up the full stack trace but reveals nothing of any real interest. Bear in mind, I'm logged in to my development server (W2k3) using my AD credentials and I'm a local administrator. An earlier log entry tells me stsadm.exe is dealing with a request from me so I know everything is pretty much okay. Of course it's not and I'm getting the above error.

The solution lies with the fact I'm not listed as a site collection administrator for the old site collection that's being replaced.

Luckily, I can change this quite easily. Fire up the the Central Administration console and browse to the Application Management tab. Select the Site collection administrators link in the SharePoint Site Management section and configure yourself (or the relevant account name) as the Secondary Site Collection Administrator. Unfortunately you can't specify a group as either primary or secondary administrator. As a result I'll also have to do this again before the next restore since I'm not a site collection admin in authoring.

Update: Poolio (see comments) and I have both run into this problem all over again after the source site collection is locked before the backup is kicked off. To work around this, remove the lock:

stsadm -o setsitelock -url [url] -lock none 
 

Thursday, 8 November 2007

How to enable anonymous access for an existing SharePoint web application

It can be a little daunting if you're new to SharePoint and tasked with doing something you've never done before. Can it be done in SharePoint? Will doing it break your site or the entire installation? Is doing it so difficult it's not worth doing? Configuring anonymous access is one of those tasks because you're dealing with SharePoint (and ASP.NET indirectly), your site collection (and potentially your database indirectly), IIS, and occasionally the file system.

At the time of writing there are a number of sites and blog posts out there offering instructions on how to configure anonymous access. Some are extremely detailed--and depending on what you're trying to accomplish, unnecessarily so. Others are a bit vague. For my own sake I therefore thought it might be useful to file this under Things to Remember but I hope it helps you too...

What you'll find below is a detailed step-by-step set of instructions for setting up anonymous access for a fully branded web site like http://www.westernaustralia.com/. The anonymous access site gives internet users the ability to browse the site without having to log in and another site allows content editors to post content updates using their domain accounts.

A bit of background information

In brief, the steps below involve 'extending an existing web application' (that's a SharePoint concept) by creating a sister web app from an existing web app. The extended web app will use the same content database as the original and will be configured to support anonymous access. The top-level site of the database will also be configured to support anonymous access. As a final option, I'll show you how to disable all other types of non-anonymous access.

The following tasks should be completed by a server administrator and assume you have already created a web application the normal way (it might be a good idea to ensure it's working before you begin...)

1. Extend an existing web application

  • Open the Central Administration console and select the Application Management tab.
  • Select Create or extend Web application from the SharePoint Web Application Management section.
  • Select Extend an existing Web application on the next screen.
  • Select an existing web application to extend.
  • Modify the description and configure the port and, optionally, the host header.
  • Set Allow Anonymous to Yes.
  • Set the Load Balanced URL Zone to Internet (you may choose another zone here if you like but Internet generally means anonymous so it's the best option).

Once you've extended a web application, the new (i.e. extended) application seems to disapper from the Central Administration screens: it won't be listed as a web application and it doesn't appear as an option when selecting a web app. You will, however, get a new directory for the extended web app under inetpub\wwwroot\wss\virtualdirectories\ and a new IIS site; you can also remove the extended site from SharePoint if required.

2. Enable anonymous access on the site's corresponding site collection

Although the site collection will be shared by the existing web application and the anonymous web application, the following steps must be completed via the anonymous web application.
  • Browse to the home page of the extended web application
  • Select Site Settings --> Modify All Site Settings from the Site Actions drop-down menu.
  • Under Users and Permissions, select the Advanced permissions link.
  • Select Anonymous Access from the Settings menu.
  • Set Anonymous Access to Entire Web site.

Sites inherit the permissions of their parent by default so if you have any problems with a specific site you can ensure it's set to inherit permission from here as well (browse to the site settings screen for the relevant site first).

If you can’t see the Anonymous Access menu item, either the web app hasn’t been configured for anonymous access (see above or below) or you’re accessing the site via the default zone instead of the internet zone—you must access the site via the internet zone (at the extended URL).

3. Test
  • Browse to the anonymous site in Firefox (or turn off integrated windows authentication if you're using IE); the site should be rendered without the Site Actions menu and other SharePoint controls.
  • Browse to a SharePoint administration screen (eg. /_layouts/settings.aspx) and you should be prompted to supply login credentials.

At this point your site is set up to allow anonymous access but will also prompt you to log in as an administrator if you hit any of the SharePoint screens. This may be desirable but alternatively you may want to lock down external access to your public site; if that's the case, read on...

4. Remove integrated authentication from the anonymous web application (optional)
  • Open the Central Administration console and select the Application Management tab.
  • Select Authentication providers from the Application Security section.
  • Select the Internet zone (this is the zone specified when the anonymous application was extended).
  • Deselect Integrated Windows authentication.
  • Set Enable Client Integration to No.

5. Test

  • Browse to the anonymous site in Firefox (restart any open browser windows if you receive a 401 error immediately after completing step 4). The home page should appear as it did previously.
  • Browse to a SharePoint administration screen (eg. /_layouts/settings.aspx); you should receive a 401 UNAUTHORIZED HTTP error (which, in this case, is appropriate).

6. Troubleshooting

If you run into difficulties (mainly with 401s and 403s popping up where they shouldn't), these ideas may help.

  • Make sure the page you're trying to access is published. It's easy to forget this simple step in all the excitement but if a page (or image, etc) doesn't have at least one published version MOSS won't serve it up
  • Reset IIS--it's quick an easy ;-)
  • Grant the Read & Execute permission to the Authenticated Users group on the anonymous site's web.config and /bin directory (both can be found below Inetpub\wwwroot\wss\VirtualDirectories); do the same again for the authenticated site. Permissions on these files are reset every time the authentication method is changed in SharePoint.
  • Recognise extending a web app creates a new site in IIS and corresponding directory under wwwroot with its own web.config. Ensure the newly-created web.config in the extended site contains everything it needs to; ensure any virtual directories and applications are properly configured
  • Redeploy any solutions, features, etc to make sure everything’s where it needs to be (custom private assemblies in particular)
  • It's possible your custom code is doing something that requires elevated permissions. The Visual Studio debugger will help you locate the culprit. If you can't remove the offending code, you can wrap it using a delegate:

SPSecurity.CodeToRunElevated elevatedAction =
new SPSecurity.CodeToRunElevated(delegate() { /* dodgy stuff */ });
SPSecurity.RunWithElevatedPrivileges(elevatedAction);

  • If necessary, remove the extended web application using the Central Administration console (also remove the IIS site) and start again.