Wednesday, December 19, 2012

WCF : Missing WCF .svc file in project

 

I created a WCF project in VS 2010 in the normal manner but when I wanted to connect to it, I found that the .svc file was missing?

WTF?

So I published the project to a folder. Lo and behold, the .svc file appeared in all its glory!

I then added this folder as an application to IIS 7.5 and all was sweetness and light.

Enjoy!

Friday, December 14, 2012

SAML : Encoding / decoding a trace

 

I blogged previously about ways to look at the SAML trace and decode the gobbledegook (actually it’s Base 64!).

One of the ways I mentioned was to use the text wizard inside Fiddler.

The problem is that to use it, you have to start Fiddler which installs proxies, generates certificate errors etc. The cure is almost worse than the symptoms!

So I sent Eric Lawrence (the author of Fiddler) an email to ask if they could make the text wizard functionality a standalone option.

You may think that’s a bit of a cheek but in my experience, people welcome feedback etc. as long as it’s valid and not the “Please do my homework for me” or “Help it doesn’t work” kind of stuff.

He was kind enough to reply and he suggested:

Inside Fiddler’s Rules > Customize Rules > OnBoot, insert:

 static function OnBoot() {
if (Environment.CommandLine.Contains("-TextWizard"))
{
FiddlerApplication.UI.actShowTextWizard(null);
}



Then create a shortcut that launches Fiddler like so:





C:\>"C:\Program Files\Fiddler2\Fiddler.exe" -viewer –TextWizard



Works like a dream.



Enjoy!

Thursday, November 29, 2012

stackoverflow : Finally – 5 figures!

 

image

Will there it is. I finally cracked the magic 10,000 rep. mark!

And at the same time …

image

… I made it into the top 3%.

Enjoy!

Tuesday, November 20, 2012

Misc : On asking questions

 

Jon Skeet wrote a very good article : Writing the perfect question.

I’m active on stackoverflow and the MSDN forums and I wish more people would read this article.

Recently there was a question and I replied waxing voluble about how to do something using WIF and the dude replied:

“Actually it’s a Java application”.

FFS dude, why didn’t you put that minor piece of information in the question?

The quality of the answer is directly related to the quality of the question.

And for God’s sake, spell check it!

Enjoy!

Friday, November 16, 2012

Visual Studio : Cannot import the following key file

 

When you have a signed project in TFS, every time a new person gets it out, they have this problem. So they create a new certificate, check it all in and the next person has the same problem. WTF.

The error is:

“Cannot import the following key file: xxx.pfx. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: VS_KEY_blah”

Mr Google to the rescue. Found a number of “solutions” but then stumbled across one that worked.

In the project properties under “Signing”, click the dropdown arrow and click on the pfx file name. This invokes the password dialogue so you can type in the new password and Bingo!

All then compiles.

Enjoy!

Thursday, November 15, 2012

Stackoverflow : What can I say?


Taken a while but I finally got there!

image 

image

Enjoy!

Monday, November 05, 2012

ADFS : Exclusive Canonicalization transform error

 

Busy trying to get ADFS v2.0 to work with a third-party SAML implementation and got this weird error:

System.Security.Cryptography.CryptographicException: ID6005: Exclusive Canonicalization transform does not support the algorithm 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'.

“IDxxxx” as an error normally implies it comes from WIF so trawl through that and it turns out that the only transform it accepts is:

http://www.w3.org/2001/10/xml-exc-c14n#

The transforms .NET works with are all listed in:

System.Security.Cryptography.Xml.SignedXml

So I had to get the third party code changed to conform with ADFS.

What is the point of all this, you may ask.

This is all connected with signatures e.g. your sp.xml looks like:

SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"

Because XML can have many forms e.g. whitespace or none, CR or CR/LF etc. you need to convert the XML to an agreed format before you sign it. Otherwise the other side may be checking the signature on a “different” document. These “agreed formats” are the canonical transforms. They are all W3C standards.

So e.g. it may state:

The canonical form of an XML document is the physical representation of the document produced by the method described in this specification. The changes are summarized in the following list:

  • The document is encoded in UTF-8
  • Line breaks normalized to #xA on input, before parsing
  • Attribute values are normalized, as if by a validating processor
  • Character and parsed entity references are replaced
  • CDATA sections are replaced with their character content
  • The XML declaration and document type declaration (DTD) are removed
  • Empty elements are converted to start-end tag pairs

etc.

Enjoy!

Friday, November 02, 2012

C# : & in the XML

 

If you have an XML string (e.g. the appSettings in web.config) that contains an “&” it won’t compile e.g.

<add key="URL" value="http://example.com?ID1=abc&ID2=123"/>

The solution is to escape it with the Unicode number i.e.

<add key="URL" value="http://example.com?ID1=abc&#038;ID2=123"/>

Enjoy!

Tuesday, October 30, 2012

IIS : Could not load file or assembly

 

So I had a website – .NET Framework 4 / IIS 7.5 - working perfectly on my PC.

Moved it to another box and got the error with one of my dlls.

“Could not load file or assembly ‘xxx’ or one of its dependencies. An attempt was made to load a program with an incorrect format”

WTF!

Mr. Google to the rescue. Normal battle with the ten tons of shite but then one link rang a bell.

My original box was 32 bit whereas the new one is 64 bit.

What you have to do with the ApplicationPool is:

In IIS 7 Manager:

  • Click ApplicationPools
  • Select the one for your application.
  • Click “Advanced Settings” on the right
  • Under “General” at the top, set “Enable 32-bit Applications” to be “True”

Bingo – problem solved.

Enjoy!

Monday, October 29, 2012

ADFS : I want to see the SAML data


There are a number of ways to see the SAML data.

Fiddler is one way.

You can use the TextWizard to URL decode and SAML decode. Refer my update on this - SAML : Encoding / decoding a trace

Refer Using Fiddler to trace a SAML IDP Request from ADFS 2.0

Dominick Baier wrote a Fiddler Inspector for Federation Messages.

Also described here : Viewing SAML/Federation response in Fiddler.

Also, the Troubleshooting WS-Federation and SAML2 Protocol tool. 

There's also the Feide SAML 2.0 Debugger.

And a URL Decoder/Encoder.

And another SAML 2.0 debugger.

But my favourite way is to use the:

SAML Tracer

which is a FireFox add-on..

Or Auth0 SAML tool

Or the Chrome SAML extension:

SAML Chrome extension 

And there are some more tools here:

Collection of Useful SAML Tools

Enjoy!

Friday, October 26, 2012

ADFS : IDP / IP and SP Initiated flows


This confuses some people so some ADFS v2.0 screen shots might be helpful.

SP Initiated is the more normal flow. The user navigates to the application, WIF (or whatever) redirects to ADFS and you get the normal login screen:

ScreenShot036

After the user is logged in, the application gets the SAML token.

IDPInitiated in ADFS only works for SAML bindings.

The ADFS IDPInitiated URL is:
https://xxx/adfs/ls/IdpInitiatedSignOn.aspx

ScreenShot035

ADFS looks through all the configured RP to find any with a SAML binding and then displays them all in the dropdown.

The user can either sign in first using the first option and then navigate directly to one of the dropdown applications or first select a dropdown entry using the second option and then sign in.

After the user is logged in, the application gets the SAML token.

The SAML token is the same for both IP and SP initiated.

Enjoy!

Thursday, October 25, 2012

ADFS : General SAML problems

 

From experience, make sure you:

  • Map email in a transform rule to “NameID – Transient”
  • Use SHA1 not SHA 256 (In the RP Advanced tab).

Enjoy!

Wednesday, October 10, 2012

ADFS : NameID / qualifier in claims

 

Firstly, there’s an excellent write-up here:

ADFS – SAML 2.0 Identity Provider and SaaS Service Providers

I was busy configuring a SAML provider in ADFS v2.0 when I got this error:

“The SAML Single Logout request does not correspond to the logged-in session participant.
Requestor: sp_test
Request name identifier: Format: urn:oasis:names:tc:SAML:2.0:nameid-format:transient, NameQualifier: http://xxx/adfs/services/trust SPNameQualifier: sp_test, SPProvidedId: 
Logged-in session participants:
Count: 1, [Issuer: sp_test, NameID: (Format: urn:oasis:names:tc:SAML:2.0:nameid-format:transient, NameQualifier:  SPNameQualifier: sp_test, SPProvidedId: )] 

This request failed.

User Action
Verify that the claim provider trust or the relying party trust configuration is up to date. If the name identifier in the request is different from the name identifier in the session only by NameQualifier or SPNameQualifier, check and correct the name identifier policy issuance rule using the AD FS 2.0 Management snap-in.”

I had a custom claims rule:

c:[Type == "http://mycompany/internal/sessionid"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",  Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/spnamequalifier"] = "sp_test");

So I had the sp_test part but not the http://xxx/adfs/services/trust part. The key was in the “User Action” message above. As my two messages only differed by NameQualifier, I needed to expand my rule to:

c:[Type == "http://mycompany/internal/sessionid"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient", Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/namequalifier"] = http://xxx/adfs/services/trust, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/spnamequalifier"] = "sp_test");

Enjoy!

Friday, September 14, 2012

ADFS : Beware the FedUtil shortcut

 

Running FedUtil is a PIA.

I find it much easier to save the web.config, deploy the application and then use WinMerge to copy over the relevant pieces from the saved web.config to the deployed one.

But beware.

There is also the metadata directory.

If ADFS is setup to update from metadata and you redeploy it, it drags over the new (and probably incorrect) metadata into the RP section. So if you were testing on your PC i.e. “localhost” suddenly all hell breaks loose because ADFS will throw an exception. I’ll bet your application is not on the ADFS box, right?

So save the metadata as well.

And always run a smoke test after a redeploy.

Enjoy!

Thursday, September 13, 2012

Windows : File names that start with a period

 

If you play around with Java on your Windows box, sooner or later you are going to hit the problem where you need to create a file that starts with a period (aka. dot or full stop) e.g. “.keypass”.

Explorer won’t let you do this.

The solution is to create a file called keypass (no period) in Explorer and then use the command prompt to run a DOS command:

ren keypass .keypass

“ren” = “rename”

Good, old DOS to the rescue!

Enjoy!

Tuesday, September 11, 2012

Firefox : Displaying the SAML content

 

The SAML Tracer add-on is a really useful tool to display the SAML message flow during SSO and logout with ADFS.

(Ain’t gonna help you with WIF though because that’s WS-Federation through and through and there ain’t no add-on for that).

Neat!

Enjoy!

Wednesday, September 05, 2012

Visual Studio : XML comments

 

Also called programmatic comments or xml documentation.

If you have a method like:

public void blah (String a, int b)
{

}


and you want the comments, just type /// on the line before and you get:



/// <summary>
///
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
public void blah (String a, int b)
{

}


If you have ReSharper, put the cursor over the method name i.e. “blah” and press Ctrl / Shift / F1.



You get a neat popup window.

Enjoy!

Friday, August 24, 2012

ASP.NET : reCaptcha with proxy

 

If you need reCaptcha in your project, this is a really good one to use. it’s also available as a NuGet package.

The only problem is that it doesn’t use a proxy. There is a Proxy attribute in the control but it inherits from IWebProxy and I couldn’t figure out how to set it.

So (with the help of TortoiseSVN) I grabbed the source and added this code to

public RecaptchaResponse Validate() in RecaptchaValidator.cs

//if (this.proxy != null)
//{
//request.Proxy = this.proxy;
IWebProxy rProxy = WebRequest.GetSystemWebProxy();
string login = ConfigurationManager.AppSettings["reCaptchaLogin"];
string password = ConfigurationManager.AppSettings["reCaptchaPassword"];
if (!String.IsNullOrEmpty(login))
rProxy.Credentials = new NetworkCredential(login, password);
else
rProxy.Credentials = CredentialCache.DefaultCredentials;
request.Proxy = rProxy;
//}


and then I added an appsettings to the web.config in the Tests directory



<appSettings>
<!-- Needed to get past proxy -->
<add key="reCaptchaLogin" value="" />
<add key="reCaptchaPassword" value="" />
</appSettings>

Problem solved!

Enjoy!


Thursday, August 16, 2012

WIF : Migration from 1.0 to 4.5

 

Interesting interview with Dominick Baier to discuss his new course Introduction to Identity and Access Control in .Net 4.5. The link is here.

To quote:

“ [Dominick] Yeah, that’s a good question. So, as I just said, Microsoft basically injected these new base classes. And they were really careful that they didn’t break compatibility with existing systems. So, if you are used to using the IIdentity.Name property, for example, what they do under the covers is they go to the clams collection and search for a name claim and give you back that value. So, from the outside, this thing works the same, under the covers, it uses claims. If you are used to use–IsInRole for example, or like the existing like the authorization module in ASP.NET, then what under the covers is happening is that is in role search, it’s for a role claim and to look if that is part of your claims collection. So, in other words, if you haven’t done any heavy customization of .NET built-in security system, things should just work in 4.5. That means, you don’t take advantage of the new system but you don’t break your application just by compiling against 4.5. That also means that you can gradually move into this claims-based world. So you can make use of this new property called Claims which is a collection of statements that you can attach to a user. And yeah, for existing applications, things shouldn’t change at least not from the outside. If you are investing in a new system, or you are not happy with what you have so far, then it’s definitely worth to look like trying to make use of the claims-based infrastructure right from the start. But, I guess the good news is that your systems shouldn’t break, at least if you haven’t done anything radical to .NET built-in infrastructure.”

So hopefully things will just work as normal after the migration.

You can see the class diagram changes at Identity in .NET 4.5–Part 1: Status Quo (Beta 1).

Enjoy!

Monday, August 13, 2012

ADFS : Problems with wevtutil

 

When you are trying to turn on the debug logging for ADFS and you Google it, you will find some entries that tell you to run wevtutil as follows:

wevtutil.exe sl “AD FS 2.0 Tracing/Debug” /L:5

The problem is that you then get an error:

“Too many arguments are specified. The parameter is incorrect.”

To fix this, run:

wevtutil sl “AD FS 2.0 Tracing/Debug” /L:5

Enjoy!

Tuesday, August 07, 2012

AD : Programmatically getting password policy

 

On Windows Server 2008, this doesn’t seem possible. There doesn’t appear to be an API that gives you all the details of the current user’s password policy.

Why does this matter?

Because when the user needs to pick a password and they get it wrong, the standard message is:

“The password you have chosen does not meet corporate policy. Please contact the help desk”.

The standard wrt. complexity is normally:

“The password contains characters from three of the following categories:

  • Uppercase letters of European languages (A through Z, with diacritic marks, Greek and Cyrillic characters)
  • Lowercase letters of European languages (a through z, sharp-s, with diacritic marks, Greek and Cyrillic characters)
  • Base 10 digits (0 through 9)
  • Non-alphanumeric characters (special characters) (for example, !, $, #, %)
  • Any Unicode character that is categorized as an alphabetic character but is not uppercase or lowercase. This includes Unicode characters from Asian languages.”

However, you can summarise the above and then get the pieces of the puzzle individually. To do this, you would have to get each attribute from AD.

Refer Windows Domain Password Policies

msDS-PasswordSettingsPrecedence
Establishes what takes precedence in situations where a user has membership in multiple groups with different password policies.

msDS-PasswordReversibleEncryptionEnabled
Toggles whether reversible encryption is enabled.

msDS-PasswordHistoryLength
Determines how many intervening passwords must be unique before one can be reused.

msDS-PasswordComplexityEnabled
Establishes the number and type of characters required in a password.

msDS-MinimumPasswordLength
Establishes the minimum length of a password.

msDS-MinimumPasswordAge
Determines how long a user must use a password before changing it.

msDS-MaximumPasswordAge
Determines how long a user can use a password before being required to change it.

msDS-LockoutThreshold
Determines how many failed password attempts will be allowed before locking out user account.

msDS-LockoutObservationWindow
Determines the time after which the bad password counter will be reset.

msDS-LockoutDuration
Determines how long the account will be locked out after too many failed password attempts.

So the message could be something like:

“Your password must be <msDS-MinimumPasswordLength> characters long, you cannot use one of your previous <msDS-PasswordHistoryLength> passwords and you will have to change it every <msDS-MaximumPasswordAge> days”.

Enjoy!

Monday, August 06, 2012

ADFS : Some of the content in the federation metadata was skipped

 

If you configure ADFS on a regular basis, you are pretty much guaranteed to get this message.

The full text is that it is not supported by ADFS and you should review carefully.

The first step is to get the RP metadata as a file and have a look at it.

The number one reason in my experience is that the connection is http rather than https.

ADFS REQUIRES https – no exceptions.

The number two reason is that the federation has SAML1 stuff e.g.

<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location=https://xxx index="1"/>

will throw the warning.

Enjoy!

ADFS : Restricting access to an application

 

Most of the available documentation talks about ADFS as a claims-provider and the RP (the application) uses the set of claims to decide on access and functionality.

However, there are claims which restrict access at the ADFS level.

These are the permit / deny claims.

Refer:

Create a Rule to Permit or Deny Users Based on an Incoming Claim

An ADFS Claims Rules Adventure

Introduction to Token Issuance Authorization in AD FS 2.0 RC

If you set these rules up correctly, you will get an “Access Denied” error from ADFS.

Because this is all controlled by the claims rules language, you can have complex IF – AND – OR – NOT scenarios to decide whether or not the user gets access to the application.

Enjoy!

Thursday, July 12, 2012

AD : Adding the extension attributes

 

Quite often when you work with AD, you need some extra attributes to store customer specific information. I normally use the extensionAttributes (1 through 15) for this.

The problem is that they are not in AD out-the-box.

They are part of the Microsoft Exchange Server schema. The schema is the only part you have to install. You do NOT have to install Exchange.

Refer Prepare Active Directory and Domains

I used Exchange 2010 SP2. I guess you could download the trial version if you don’t have the DVD to hand?

To install, just run “Setup /PrepareSchema” to have the additional extension attributes added.

Note that you need to be a “Domain Admin” & “Schema Admin” & “Enterprise Admin” in order to run this script.

Enjoy!

Friday, July 06, 2012

ADFS : List of claims types

There’s a number of lists all over the place.

This one comes from SelfSTS.

"http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor",
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous,
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authentication,
http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant,
"http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims",
"http://schemas.xmlsoap.org/ws/2009/09/identity/claims",
"http://schemas.microsoft.com/ws/2008/06/identity/claims",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dns",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/expired",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/hash",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/homephone",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/ispersistent",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/version",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/x500distinguishedname",
"http://schemas.xmlsoap.org/claims",
"http://schemas.xmlsoap.org/claims/CommonName",
"http://schemas.xmlsoap.org/claims/EmailAddress",
"http://schemas.xmlsoap.org/claims/Group",
"http://schemas.xmlsoap.org/claims/UPN"

You are free to construct any claim type you wish e.g.

http://schemas.company.co.nz/identity/claims/teamidentifier

Enjoy!

Friday, June 29, 2012

Powershell : Setting credentials for a web request


Trying to get through a proxy and getting the dreaded “407 – Proxy Authentication Required.
The solution is to use:

$wcl = New-Object Net.Webclient
$wcl.Credentials = new-object Net.NetworkCredential("login", "password", "domain")
$wcl.Proxy.Credentials = new-object Net.NetworkCredential(("login", "password", "domain"); 

And suddenly we’re through the proxy and all is good!

Enjoy!

Thursday, June 21, 2012

ADFS : Sending groups as claims

 

When you are configuring the claims rules in ADFS, you have a number of options for sending AD groups.

You can send them all at once – “Send LDAP Attributes as Claims” or you can send then individually – “Send Group Membership as a Claim”.

In the latter case, you get to “clean” the name up.

e.g. you can have a group called “TN-W2008-Test-Marketing-Editor” because of some company naming convention but you can configure the claim to be of type:

http//schemas.microsoft.com/ws/2008/06/identity/claims/role with a value of “MarketingEditor”.

The downside with this is that if the groups are deleted or renamed, you have to manually reconfigure ADFS.

For the former, ADFS simply sends the whole lot. If a group is renamed, it simply sends the new name.

There are a number of options for the groups i.e.

Token-Groups as SIDs

Token-Groups - Qualified by Domain Name

Token-Groups - Qualified by Long Domain Name

Token-Groups - Unqualified Names

If you gave a group called Editor with a SID of S-1-5-21-3794324387-748717723-962058466-1466 and a domain of company.com (and assuming you map them all to a type of “role”) then the four different types result in:

…identity/claims/role = S-1-5-21-3794324387-748717723-962058466-1466

…identity/claims/role = company\Editor

…identity/claims/role = company.com\Editor

…identity/claims/role = Editor

Note that you get a role claim per group. If the user is a memberof 6 groups, they will get six separate claims of type “role”. This includes the default claim of “Domain Users”.

Enjoy!

Friday, May 18, 2012

ADFS : There was a problem accessing the site - Reference number xxx

 

If you work with ADFS, you get pretty used to the error box with a GUID reference number. So what is this mythical number? It’s a reference to the Windows Event Viewer. To see these GUIDs: refer ADFS v2.0 : Finding errors referenced by the reference number.

To quote @Marnix in the above link:

“Open the Event Viewer. Navigate to 'Applications and Services Logs' -> 'AD FS 2.0' -> Admin. In the 'View' menu, using 'Add/Remove Columns...', add the 'Correlation Id' column. Look up the reference number “xxx” in the 'Correlation Id' column.”

Enjoy!

Tuesday, May 08, 2012

ADFS : Beware automatic WIA (Windows Integrated Authentication)

 

IE has the neat feature that if you are on the Intranet and you navigate to a site that requires authentication, IE checks if you have a Kerberos ticket (derived from when you logged into your desktop) and, if so, logs you in under the hood.

The problem when you are playing around with ADFS and WIA is that you can’t tell if the site you are going to logged you in automatically or if you have somehow removed or screwed up the authentication option!

There are a number of workarounds:

  • Use Firefox (which by default doesn’t do this).
  • IE / Tools / Internet Options / Security / Local Intranet Zone / Custom / Scroll down to User Authentication – Logon and ensure that “Automatic logon only in Intranet zone” is not enabled.

Note: You can configure Firefox to support WIA – refer Firefox supports Integrated Windows Authentication.

Enjoy!

Friday, May 04, 2012

Misc : Notepad++ and inserting a CR

 

Had a situation where I had a huge HTML file with no carriage returns and I wanted to place a CR at the end of every line after the <href …> specifically after the </a>.

The way to do this in Notepad++ is:

In the Search / Replace menu:

Find what:       </a>

Replace with:   \n

Select the “Regular Expression” button.

Check with a “Find Next: / “Replace” and then “Replace All”.

Ah – regex – don’t you just love them Smile

Enjoy!

Wednesday, April 18, 2012

ADFS : Problems with SAML and domains

 

Busy testing a 3rd party SAML provider and getting it to integrate with ADFS.

First tried it on my dev. PC using https://mypc/3rdparty.

All well and good – tick that one off – but then I needed to test it from outside of the dev. domain i.e.

https://mypc.mydomain.com/3rdparty.

Firstly, got the error:

“MSIS3020: The relying party trust with identifier 'https://xxx/sp' could not be located.”

OK, so off to the RP properties config. in ADFS.

Click on the “Identifiers” tab.

Click on the existing RP identifier and then click “Remove”. This puts the URL in the “Add” box where you can add the “mydomain.com” piece and then click “Add”

So now you have two identifiers; one without the domain and one with.

Ok – lets try that again.

Get the error:


“The request specified an Assertion Consumer Service URL 'https://xxx/sp…' that is not  configured on the relying party 'https://xxx/sp'.

User Action
Use the AD FS 2.0 Management snap-in to configure an Assertion Consumer Service with the specified URL for this relying party.”

Mr Google leads to this: AD FS 2.0: "The request specified an Assertion Consumer Service URL that is not configured on the relying party"

and states:

“There are two options:
1. Configure the RP so that AssertionConsumerService is not specified in the AuthnRequest
2. Configure the RP to send a AssertionConsumerService value in the AuthnRequest which matches the AssertionConsumerService value on the Endpoints tab of the RP Trust in AD FS 2.0.”

Hmmm – 1 is not an option because it’s a 3rd party product.

Went with 2.

In the RP properties config. in ADFS.

Click on the “Endpoints” tab.

Under “SAML Assertion Consumer Endpoints”:

In my case there were two with bindings for POST and Artifact.

Click on “Edit”, copy the URL, then click on “Add”. Fix the domain, select the binding and an index number that’s not used.

When I finished I had four entries, two POSTS bindings and Artifact bindings.

And then, verily, it all just worked.

Enjoy!

Thursday, April 12, 2012

Tuesday, March 27, 2012

AD : Enumerating UserAccountControl

 

There doesn’t seem to anything built into the .NET framework to do this and it’s a lot easier to read actual names rather than hex boolean manipulation so I rolled my own:

[Flags]
enum UserAccountControl
{
ADS_UF_SCRIPT = 1, // 0x1
ADS_UF_ACCOUNTDISABLE = 2, // 0x2
ADS_UF_HOMEDIR_REQUIRED = 8, // 0x8
ADS_UF_LOCKOUT = 16, // 0x10
ADS_UF_PASSWD_NOTREQD = 32, // 0x20
ADS_UF_PASSWD_CANT_CHANGE = 64, // 0x40
ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 128, // 0x80
ADS_UF_TEMP_DUPLICATE_ACCOUNT = 256, // 0x100
ADS_UF_NORMAL_ACCOUNT = 512, // 0x200
ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 2048, // 0x800
ADS_UF_WORKSTATION_TRUST_ACCOUNT = 4096, // 0x1000
ADS_UF_SERVER_TRUST_ACCOUNT = 8192, // 0x2000
ADS_UF_DONT_EXPIRE_PASSWD = 65536, // 0x10000
ADS_UF_MNS_LOGON_ACCOUNT = 131072, // 0x20000
ADS_UF_SMARTCARD_REQUIRED = 262144, // 0x40000
ADS_UF_TRUSTED_FOR_DELEGATION = 524288, // 0x80000
ADS_UF_NOT_DELEGATED = 1048576, // 0x100000
ADS_UF_USE_DES_KEY_ONLY = 2097152, // 0x200000
ADS_UF_DONT_REQUIRE_PREAUTH = 4194304, // 0x400000
ADS_UF_PASSWORD_EXPIRED = 8388608, // 0x800000
ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 16777216 // 0x1000000
} 

With this you can write code like:


val = val | (int) UserAccountControl.ADS_UF_DONT_EXPIRE_PASSWD;


Far more readable, I think you’ll agree.


And remember:


To clear a value, use:


val = val & (int) ~UserAccountControl.ADS_UF_ACCOUNTDISABLE;


The ~ is a boolean complement ~ Operator.


Enjoy!

Friday, March 23, 2012

C# : Logging the variables in a class

 

Imagine you have a web site with a bunch of global variables. You want to display them in a debug page. So you could use intellisense and manually traverse through the class but if it’s a big class it’s a right royal pain and you have to keep updating the code as you add new variables.

Enter stage right Reflection.

Type objectType = typeof (GlobalVar);
GlobalVar gv = new GlobalVar();
System.Reflection.FieldInfo[] fieldInfo = objectType.GetFields();

foreach (System.Reflection.FieldInfo info in fieldInfo)
{
xxx.Text = info.Name;

object oText = info.GetValue(null);
if (oText is string)
yyy.Text = (String)oText;
else if (oText is int)
yyy.Text = oText.ToString();
else if (oText is bool)
yyy.Text = oText.ToString();
else if (oText is long)
yyy.Text = oText.ToString();
}


Note the “GetValue(null); “. This is because all the variables in the class are static.



For a non-static class, see C# Tutorial - Using Reflection to Get Object Information.



Enjoy!

Thursday, March 22, 2012

ASP.NET : At least one check box must be checked

 

The ASP.NET Validation Controls are a really neat way of doing user validation. However, they are pretty basic. What about more complicated stuff? For that you need a CustomValidator.

e.g. I have a number of check boxes on the page and one of the validation rules is that at least one of the check boxes must be checked. Mr Google to the rescue and (roll of drums) the answer is:

Put this script at the top of the page:

<script runat="server">

void CustomValidator_CBValidate(Object source, ServerValidateEventArgs args)
{
args.IsValid = (chkBox1.Checked == true) || (chkBox2.Checked == true) || ...;
}

</script>



And then in your page:



<asp:CheckBox ID="chkBox1" Text="xxx" runat="server" />

<asp:CheckBox ID="chkBox2" Text="yyy" runat="server" />

...

<asp:CustomValidator id="CustomValidator1"
runat="server" ErrorMessage="Please select an option"
OnServerValidate="CustomValidator_CBValidate">
</asp:CustomValidator>


Enjoy!



C# : Active Directory Resources

 

Being doing a bit of work in this space and I found the following links to be really useful:

Howto: (Almost) Everything In Active Directory via C#

Everything in Active Directory via C#.NET 3.5

Active Directory and .NET

Active Directory Objects and C#

Active Directory With C#

So if you want to create users, work with their passwords, update their details, add them to groups etc. you’ll find something above to help you.

Enjoy!

Wednesday, March 14, 2012

C# : The server is unwilling to process the request

 

Busy doing some AD work with C#.

I’m creating the user, changing some of the attributes (e.g. setting “DONT_EXPIRE_PASSWORD”) and then setting the password.

Got the exception:

DirectoryServicesCOMException (0x80072035): The server is unwilling to process the request

Mr. Google to the rescue. After sorting through the huge pile of crap, found the answer.

You need to do it in the following order:

  • Create the user
  • Commit changes
  • Set the password
  • Commit changes
  • Change the attributes
  • Commit changes

i.e. Set the password BEFORE doing any attribute CRUD stuff.

Enjoy!

Thursday, March 08, 2012

WCF : Message logging


The best developer tool is Google. 99 % of the time you can find an answer or sample code to your problem.

On the other hand, the worst developer tool is Google. At least half the links are rubbish. There should be some kind of peer review like stackoverflow has to delete crap articles from the Web.

This came about because I was looking for a way to log the actual messages being sent over WCF.

Came across loads of articles, none of which worked 100%. Some were misleading and some were absolute rubbish.

The worst aspect was that they include some small XML snippet which you cut and paste into the web.config without any context i.e. just where are you supposed to insert it?

Anyway, here’s the solution I came up with:

<configuration>
...
  </system.serviceModel>
    <diagnostics>
         <messageLogging 
         logEntireMessage="true" 
         logMalformedMessages="false"
         logMessagesAtServiceLevel="true" 
         logMessagesAtTransportLevel="true"
         maxMessagesToLog="3000"
         maxSizeOfMessageToLog="2000"/>
     </diagnostics>    
  </system.serviceModel>
...
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" switchValue=
"Information,ActivityTracing"
        propagateActivity="true">
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="messages"
                 type="System.Diagnostics.XmlWriterTraceListener"
                 initializeData="c:\...\messages.svclog" />
        </listeners>
      </source>  
    </sources>
       <sharedListeners>
      <add initializeData="C:\...\Trace.svclog"  
type="System.Diagnostics.XmlWriterTraceListener"
        name="xml" />
    </sharedListeners>
    <trace autoflush="true" />
  </system.diagnostics>
...
<configuration>

Enjoy!

Wednesday, February 29, 2012

Visual Studio : "Set As Start Page" doesn't work in the real world

I have a web site that contains a "Default.aspx" but I want the start page to be "abc.aspx".

So in Visual Studio 2010, I right click the "abc.aspx" page and select "Set As Start Page".

Hit F5 - works perfectly.

Deploy it to a real IIS 7 server and WTF - Default.aspx is displayed in all its delights?

Turns out the "Set As Start Page" option only applies to Cassini - the VS internal web server (which is why it works when you hit Run ( = F5)).

In the real world, you have to go to the web site inside the IIS Manager, select "Default Document" and then type abc.aspx and move it up to the top.

There you go!

Enjoy!

msdeploy : Package installation failed - 'managedRuntimeVersion' differs

So there I was trying to use msdeploy to deploy a web site from Visual Studio 2010 into an IIS 7 server on another box using the "Build Deployment Package".

I got the error:

The package installation failed.
Details:
The application pool that you are trying to use has the 'managedRuntimeVersion' property set to 'v4.0'. This application requires 'v2.0'.

My web application used the "Default Web Site" and the application pool that it was connected to (DefaultAppPool) was .NET Framework 2.0. Yeah - I screw around with IIS a lot!

Of course, where I was deploying it to was the more usual .NET Framework 4.0.

Mr. Google to the rescue and the answer is to set the following options under the project / Properties / Package/Publish Web:



You need to tick the two text boxes "Include IIS Settings" and "Include application pool settings".
And away you go with msdeploy.

Enjoy!



Wednesday, February 22, 2012

WIF : Web Platform Installer

WIF has just been added to the Microsoft Web Platform Installer. (WPI)

Just search on the keyword "identity".

Hey - hey - it's becoming mainstream.

Makes it just that bit easier to download.

The WPI is a really useful tool that collects a pile of Microsoft (and other) downloads in one place. Well worth 5 minutes of your time to go and have a look!

Enjopy!


Monday, February 13, 2012

C# : Some basic validation




Doing some basic validation and I found these to be useful:

Check for mandatory fields:
if (String.IsNullOrEmpty (xxx)) … error

Field must be numeric only:
int number;
bool result = Int32.TryParse (xxx, out number);
if (!result) … error

Valid date format:
DateTime date;
bool result = DateTime.TryParse (xxx, out date);
if (!result) … error

Valid email format:
bool result = Regex.IsMatch(xxx, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)
(([\w-]+\.)+))([a-zA-Z]{2,4}[0-9]{1,3})(\]?)$");
if (!result) … error

Enjoy!

WCF : soapUI error "BadContextToken"

 

While soapUI is a really useful tool for web service unit testing, it doesn’t work with WCF.

In particular, with the default "wsHttpBinding", you get the message  "BadContextToken".

Mr. Google comes back with tons of results about why soapUI doesn’t play nicely with WCF and recommends WCF Storm which looks good but it’s not free.

So a whack of investigation later:

Add the following binding into the <bindings> section of your web.config:

<!-- soapUI -->
      <wsHttpBinding>
        <binding name="wsHttpBindingNoSecurity">
          <security mode="None">
            <transport clientCredentialType="None" />
            <message establishSecurityContext="false" />
          </security>
        </binding>
      </wsHttpBinding>

Add the following "bindingConfiguration” parameter to your <endpoint> section:

binding="wsHttpBinding" bindingConfiguration="wsHttpBindingNoSecurity"

The WCF service has an endpoint like:

blahblah.svc

For soapUI you need to change this to blahblah.svc?wsdl when you “Add WSDL”.

Once you’ve added the service to soapUI, click the default operation and then click the “WS-A” tab at the bottom.

Click “Enable/disable WS-A addressing”.

Click “Add default wsa:Action”.

Click “Add default wsa:To”.

And (finally) success!

REMEMBER: Every time you change the web.config, you need to right-click the soapUI service and “Update Definition” or F5!

Enjoy!

Wednesday, February 08, 2012

Visual Studio : Showing the active file in the Solution Explorer tree

So there I was doing some consultancy work on site and I noticed that when you click through the open files in the file bar on the top, their Visual Studio tracks the active file in the tree.

Something I've always thought would be really useful.

Turns out the way to do this is via:

Tools / Options / Projects and Solutions / General / Click "Track Active Item in Solution Explorer".

WTF isn't this the default?

Enjoy!

Stackoverflow : The big 100 badges

Another of my goals - getting 100 badges on stackoverflow.




Enjoy!


Thursday, January 26, 2012

c# : Nullable DateTime


So there I was trying to convert a nullable date time "DateTime?" to DateTime.

Then I got the error:

"Cannot implicitly convert type 'System.DateTime?' to 'System.DateTime'. An explicit conversion exists (are you missing a cast?)"

stackoverflow to the rescue and you need to use the null-coalescing operator.

So the code ended up like:
DateTime x = DateTime y ?? DateTime.Now;
Love those "??".

Aside: When I tried to find the article again for this blog, found that searching Google for "??" is an interesting exercise.

Enjoy!