Tuesday, June 7, 2011

Authenticating Web Services

I find this one to be a bit painful every time I come to it, so it's time to make some notes.

  • You have a web service.
  • You would like to make sure that only people who supply correct credentials can use it.

Here's my approach:

1. Create the Login

In the web server, create a standard windows login and password that will be used for authentication.

2. Create the Security Group

Create a Local Group that the new User is a member of. This group is the name that we will be checking for membership of. That way you can create additional users as required.

3. Set the site up for SSL

This is to ensure that passwords are securely passed.

4. Configure the site's Authentication

Double click the Authentication feature on the site in IIS7. Enable Basic Authentication and Windows Authentication, and disable everything else.

5. Configure the site's Authorization Rules

Double click the Authorization Rules feature on the site in IIS7. Allow All Users and Deny Anonymous Users.

6. Demand the role in your code

In your code, put the PrincipalPermission attribute onto all web methods in order to demand the role that you have created.

In VB.Net, this looks something like this:

<PrincipalPermission(SecurityAction.Demand, Authenticated:=True, Role:="MyRole")> _

7. When calling your service, wrap the client class in another class that provides the correct credentials.

Public Class MyServiceWrapper
Inherits MyServiceNamespace.MyService

Public Sub New()
MyBase.New()

Dim credCache As CredentialCache = New CredentialCache()
Dim netCred As NetworkCredential = New NetworkCredential("MyUserName", "MyPassword")
credCache.Add(New Uri(Url), "Basic", netCred)
Credentials = credCache
End Sub

End Class

8. Try it out - and check for the dreaded 401.1 error

Many times, I've banged my head against the above settings still giving me a 401.1 error. The solution, apparently, is a security issue in Windows which blocks Windows Authentication if the domain name used doesn't match the name of the server (which is about 99.9% of cases).

Here is an article on the problem, but the short answer is to create the DWORD value "DisableLoopbackCheck" in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa and set it to 1.

Monday, September 20, 2010

Telerik's RadProgressArea not displaying

We've had a page with a RadProgressArea control on it for some time now, which hasn't always appeared.

After many hours, I've isolated the problem, and it's a wierd one.

With the page class itself was the variable definition

private string UnnamedComponentString = StaticInitializerClass.UnnamedComponentStringInitializationFunction();

I'm not arguing that the above is good code (it really should be initialized in the constructor or the Page_Init rather than at the point of definition) but, to my great surprise, that line was the culprit.

When I change that line to a pure definition and moved the initialization to Page_Init, the RadProgressArea magically appeared! Go figure.

I tried reproducing this in a standalone website as a proof of concept, and it didn't work... so presumably the initialization itself wasn't the problem, it was the interaction between it and something else. Strange, but good to have solved the mystery at last.

Friday, August 13, 2010

Visual Studio 2010 doesn't play nice with "Windows Form Designer generated code" blocks

I've had some consistent but intriguing further issues with Design Mode for Windows Forms in Visual Studio 2010.

I have a base custom control type.

There are a number of controls that inherit from the base. In most cases, the logic of the inherited class is minimal: just providing some settings that the code in the base uses.

Nonetheless, despite the simplicity of these inherited controls, some of them consistently work fine in design view and some of them cause errors in Visual Studio's UI, which often require me to restart the designer, or even Visual Studio.

I'm hoping I've just found the answer, though.

I noticed that in two of these inherited controls - where one always worked and the other always caused trouble - the working one had a controlname.designer.vb code file, and the failing one had

#Region " Windows Form Designer generated code "


section.

I tried creating a designer file for the failing control, and copied the region into it.

Voila! It started working perfectly, every time!

Looks like Visual Studio 2010 doesn't play nice with "Windows Form Designer generated code" blocks.

Thursday, June 10, 2010

Can't Load Library in Visual Studio 2010 Design Mode for Windows Forms

Having trouble opening a form in the Designed in Visual Studio 2010?

If the form contains controls in another library, and that library is a project file in your solution, but it's complaining that it can't load the library not matter how many times you Clean and Rebuild everything, here's the workaround:

Open the compiler settings for the library that can't be loaded. Change something. Anything - just register a change. You can change it back if you like, as long as Visual Studio 2010 registers that the settings are "dirty".

Then compile everything.

Then open your form.

Yes, it worked for me (reproducably) after spending several hours scratching my head.

No, I have no idea why.

Wednesday, August 26, 2009

Scrunched Permissions

This has been a bad week. On Monday, one of my 3 servers died (hardware error - freezing intermittently). So I spent 24 hours porting all services off it onto my other 2 servers.

Then, overnight, one of those two servers had a major conniption.

I have no idea what the cause was, and I've never seen anything like it. All I know is that the server did a reboot as part of Automatic Windows Updates. And when it came back on, all of the NTFS permissions were borked.

And I mean really borked.

A *lot* of files had mysteriously lost their "Inherit Permissions" setting, so were now sitting there with only the owner allowed to access them.

This server now houses ALL websites, so the net result is that most websites were down as the files weren't readable by the NETWORK SERVICE account (used by ASP) or IUSR_XXXX (used by plain vanilla IIS).

In all, there were a squillion files on the system, and their permission settings were now all over the place. I tried just going to the PERMISSIONS tab of the root folder and setting its permissions, but it then sat there for 2 hours - presumably setting all child folders - but I was getting nervous as I was now waiting a long time for nothing to happen, whilst most sites were down.

The slow but fairly sure solution came in the form of xcacls.exe and xcacls.vbs - tools provided by Microsoft. xcacls.vbs particularly is VERY slow but seems to do the job.

I was able to run the following at the command prompt in order to get the current folder and all subfolders, and all files contained therein, to inherit their parent's permissions:

xcacls.vbs . /f /t /i enable

There's a caveat to that, though, which is that it didn't work on many folders as we didn't have permission - because those folders were owned by a small FTP user and I was logged in as Admin. So some tweaking was required.

I wounder up opening 6 command windows and having 6 instances run at once.

Whenever I met a folder that needed to have its permissions reset at the command prompt without using the Windows UI (which could mean waiting for a very long time), I'd run:

xcacls . /G Administrators:F
xcacls . /G System:F /E
xcacls . /G iusr_XXXXX:R /E
xcacls . /G "NETWORK SERVICE":R /E

Where XXXXX is the name of my server. That cleared the permissions for that folder alone.

What a headache. A *lot* of crawling ahead, but it seems under control now, so I can go and do other work... any work I can find that doesn't involve using any of the sites that are still down :(

Tuesday, May 26, 2009

(Probably not) the last word on Dynamic ASP.Net Controls

Dynamic ASP.Net controls are always a mystery to me.

That is, they always seem to be pretty straightforward but whenever I implement them I find things not going quite according to plan, and then spending a couple of days getting everything right. And then, a year or so later when I next need to implement them, I've forgotten everything and make the same mistakes again. Rinse and repeat.

The most common mistake, although one that I know well about so don't struggle with, is the question of when to create the controls. You need to create them on the Page_Init event so that the controls get into the page lifecycle early enough. This can sometimes lead to headaches as occasionally the decision as to what controls require creation isn't naturally resolved until Page_Load, but then you just need to be resourceful.

The problem that I do have, however, is events. Frequently I create dynamic controls in Page_Init, but when those controls trigger an event, the event doesn't fire.

Now, I'm not 100% sure of the details of the cause and effect link here, but after today's exploratory I can confirm that the fix for this is to ensure that whilst your controls need to be created and added under Page_Init, they should not be initialized until Page_Load.

This may well be a situational issue, but a problem that I've had lately with a button on a subcontrol not firing when added dynamically vanished when I simply split the creation logic from the initialization logic, and moved initialization to Page_Load and under a (if !Page.IsPostBack).

Will continue exploring, but when - in 2 years time - I'm next dabbling with dynamic controls, I hope I remember to read this first :)

Thursday, March 12, 2009

ASP.Net UpdatePanel and overriding Page.Render don't mix

I have a website. Well, I have lots of websites but I have one in particularly that has special needs. It needs to be multi-lingual but at the same point it is set up so that translators can change the translations on the fly.

This last point is a killer and renders the conventional ASP.Net localization mechanism null and void. ASP.Net uses resource files for localization. If a translator changes some text, they won't see the change until you rebuild the files for that language. And when you do that, the entire site gets recycled. For everyone. Ick.

Anyway... long story short. I implemented what seemed like a good idea at the time. Whenever there was a block of text I had my controls simply render out text placeholder. For example, $$TextID:123$$. I was then intercepting the Page.Render event and RegEx matching all of these placeholders, building a list of all text IDs to look up, and then doing a single database call to get the results back, then modifying the output on the way through.

At first, all seemed good, but two issues arose.

The first of them is a /facepalm of my own, which is that the approach only works when no post-processing is required on the text. For example, if I was pulling out text that used a wiki markup and I needed to translate that to HTML, it was going to try to interpret $$TextID:123$$ as wiki markup when the control was rendered, and then wasn't going to apply the markup formatting in the Page.Render unless I built something a bit more intelligent.

Fair enough, but doable. But in the end I'm rolling back the approach entirely because, as it turns out, overring Page.Render really borks up the AJAX UpdatePanel.

Now let's be fair: the UpdatePanel is actually a very blunt instrument - too blunt, really - and should be avoided if a more targetted solution can be obtained. If all you're doing is updating HTML text for example, for heaven's sake use web services consumed by the client - they have so much less overhead that UpdatePanels and don't required an entire page postback just to change one bit of text.

However, sometimes you already have UpdatePanels there and sometimes you just need something quick and dirty.

But...

Try the following code on the Render method and check out the result when it's an UpdatePanel postback.


protected override void Render(HtmlTextWriter writer)
{
using (System.IO.MemoryStream msOur = new System.IO.MemoryStream())
using (System.IO.StreamWriter swOur = new System.IO.StreamWriter(msOur))
{
HtmlTextWriter ourWriter = new HtmlTextWriter(swOur);
base.Render(ourWriter);
ourWriter.Flush();
msOur.Position = 0;

using (System.IO.StreamReader oReader = new System.IO.StreamReader(msOur))
{
string sTxt = oReader.ReadToEnd();
}
}
}


...and check out the value of sTxt

Normally you'll see your page in all its full HTML glory, but in an UpdatePanel postback, you get a completely different kind of markup. Something containing lines like this:

|5|onSubmit||null;|90|onSubmit||if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;|


That's only part of it, but it gives you the idea. Now, here's the important bit: those numbers in the pipelines (|5| and |90| for example) actually contain the LENGTH of the text parameter to follow (the "null;" shortly after the |5| is 5 chars long, for example).

So, if you take your rendered output and change "$$TextID:123$$" to "I am a telephone pole" then your client page is not going to interpret the result correctly any more (unless all of your strings happen to be exactly the same length as the ID placeholders).

On its own, this is not insurmountable, but it's a pain for a number of reasons:


  • If the AJAX team had chosen XML for communicating the UpdatePanel changes to the client, it would have been much easier to overcome this: by simply parsing the XML using the built-in parsers and changing the value of a given length field. Without XML, there's much heavier parsing work required. There may well be good reason why they didn't use XML - I'm not saying it was a wrong decision, I'm just lamenting it...

  • It's also a pity that the formatting that they do - where they take the page's HTML and convert it to this pseudocode - seems to be somehow happening internally WITHIN the default Page.Render method. It would be nice if this conversion happened AFTER the Page.Render method so that we could intercept it. What we want to do is to get an override in between the point when the full HTML is generated and when AJAX strips out all the stuff that it doesn't need to send back to the client and creates pseudo-code out of what it does. But because that seems to happen inside Page.Render, I'm not sure it's possible.

  • Finally, in conjunction with the formatting issue I mentioned at the very beginning, I think I'm going to file this approach in the "not worth it" basket. A nice idea, but I think there are better ways to optimize.



But the lesson that I've learnt today is: never override Page.Render to tweak the output OR never use an AJAX UpdatePanel, as the two aren't talking to each other right now. Personally, I think that the UpdatePanel is the one to chuck, but that can be tricksy if you've already got it in there somewhere.