Important about FIM Hotfix Rollup Package (build 4.0.3594.2)

November 17, 2011 at 1:19 AMHenrik Nilsson

Fellow FIM MVP David Lundell has written a great article about the problem of using wildcards (% and _) in FIM XPath queries (Sets, Groups, Search Scopes etc.). The problem lies in that Microsoft has made the choice to treat these wildcard characters as literals instead of wildcards meaning that installing FIM Hotfix Rollup Package 4.0.3594.0 could break your FIM implementation.

Go ahead and read Davids article:

What the %_ is the deal with wildcards in FIM Queries in the latest hotfix?

Posted in: Forefront Identity Manager

Tags: , , ,

ADFS 2.0 Home Realm Discovery Deluxe

November 3, 2011 at 9:06 PMHenrik Nilsson

I’ve been doing some work on Home Realm Discovery lately and I wish to show you how HRD can be performed on the ADFS 2.0 server when you have done the wise decision to centralize all your Claims Providers in ADFS than in each and every application that likely will save you a lot of head ache in the future.

The Problem

This is what users sees when there are 1 ore more Claim Providers configured in ADFS, The ADFS 2.0 Home Realm Discovery Page…

image

This might be ok if the user is sure what Claims Provider Trust to use but what if only 1% of the users  normally located in a branch office realm are supposed to sign in on another Claim Provider – this will force the remaining 99% at the main office realm to go thru this page and do the selection also.

The whr query parameter?

In ADFS 1.0 you could add a query parameter at the end of your url to select Home Realm and bypass the Home Realm Discovery page when requesting the application like this:
https://YourApplication/?whr=TheExactEntityIdOfYourClaimsProvider

Unfortunately WIF won’t forward the whr query parameter to an IdP unless you add or change Global.asax in your WIF enabled application. Add this to Global.asax in the WIF application to make it work:

<%@ Application Language="C#" %>
<%@ Import Namespace="Microsoft.IdentityModel.Web" %>

<script runat="server">

void Application_Start(object sender, EventArgs e)
{
FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider +=

new EventHandler<RedirectingToIdentityProviderEventArgs>(WSFederationAuthenticationModule_RedirectingToIdentityProvider);
}

public void WSFederationAuthenticationModule_RedirectingToIdentityProvider(object sender, RedirectingToIdentityProviderEventArgs e)
{
e.SignInRequestMessage.HomeRealm = Request["whr"];
}
...

 
ADFS 2.0 on the other hand handles the whr query parameter very well and before the Home Realm Discovery page is shown but remember it must match the entityId of the selected Claim Provider exactly including casing.
 

The ADFS Home Realm Discovery page

From the UI (the picture above) you can see that it has a dropdown list containing the Claims Providers available and then there’s a submit button. The code behind class (not shown due to copyright) of the HomeRealmDiscovery page inherits from the HomeRealmDiscoveryPage class that gives us a property, ClaimsProviders that holds a DataTable object with the display name [name] and entity id [id] columns of available Claims Providers that is used to populate the dropdown list. The HomeRealmDiscoveryPage class also gives us the SelectHomeRealm method that will set the home realm to the entity id of the Claims Provider selected in the dropdown list unless it’s the local ADFS that’s selected, in that case an empty string will be passed to the SelectHomeRealm method.

You can easily change the Home Realm Discovery page used in /adfs/ls/web.config file, allowing you to keep the original untouched.

<homeRealmDiscovery page="HomeRealmDiscovery.aspx" />

The Home Realm Discovery Cookie

As you probably know, the local ADFS 2.0 is acting as a relying party when a remote Claims Provider is selected as home realm, an authentication request is created and sent to the remote Claims Provider and when a response is coming back on a successful sign on the MSISIPSelectionPersistent cookie is by default created as a persistent cookie (in opposite to session cookies it will stay after browser is closed) that will live for 30days in the browser.

How and if the cookie is created and it’s lifetime can be configured in the persistIdentityProviderInformation element in the /adfs/ls/web.config file.

<persistIdentityProviderInformation enabled="true" lifetimeInDays="30" />
The enabled attribute controls whether the cookie should be created as a persistent cookie (true) or as a session cookie (false) and the lifetimeInDays attribute how long the cookie will live when persisted. unfortunately it looks like the persisted cookie won’t be extended with each successful login but I’m not 100% sure of this, maybe somebody could tell me!?
 

Possible solutions to the problem

Now that you know most of what there is to know about Home Realm Discovery lets go back to the problem stated above where branch office users will be signing in using a different Claims Provider but where everyone has to select anyway.

One solution could be to distribute url’s with the whr query parameter to everyone with different values depending on Home Realm to use but this is a bit unpractical, almost as unpractical as doing the manual selection at the Home Realm Discovery page.

Another solution would be if we could find out something about the user like for example where he’s connecting from, like for example the IP-Address the user’s machine is having and from that make the decision automatically for the user. This is possible since we can get that information from the HTTP request object in a web application. I’m not saying this is a perfect solution since a branch office user might be visiting the main office when the automatic selection is being made and then will be asked to sign in at the wrong Claims Provider.

There are of course more solutions and depending on your requirements there are things that can be made to simplify Home Realm Discovery but I’m going to show you how this can be done by detecting the IP-address of the user as mentioned earlier.

Automatic Home Realm Discovery from user IP-Address - Deluxe

From what I told you before you now know that using the whr query parameter with a slightly modified WIF application will bypass the Home Realm Discovery page and you also know that we easily can replace the Home Realm Discovery page with our own.

Lets just copy the /adfs/ls/HomeRealmDiscovery.aspx and it’s code behind /adfs/ls/HomeRealmDiscovery.aspx.cs and instead name them HomeRealmDiscoveryDeluxe.aspx and HomeRealmDiscoveryDeluxe.aspx.cs.

Before we continue we need something that could help us store the entity Id of our claims providers we wish to assign automatically to users but also an IP address range for knowing between what IP addresses our users should have it’s own IP address for automatically getting a Home Realm. I’ve chosen to call this class AutomatedClaimsProvider and of course it contains some logic to do the IP address calculations. Copy the code below into a new class file named AutomatedClaimsProvider.cs in the App_Code directory (adfs/ls/App_Code)

using System;
using System.Net;

/// <summary>
/// Summary description for IPRange
/// </summary>
public class AutomatedClaimsProvider
{
/// <summary>
/// Public Constructor
/// </summary>
/// <param name="entityId">Entity Id of the claims provider.</param>
/// <param name="fromIpAddress">IP Address starting the range.</param>
/// <param name="toIpAddress">IP Address ending the range.</param>
public AutomatedClaimsProvider(string entityId, string fromIpAddress, string toIpAddress)
{
if (IpAddressToLongBackwards(fromIpAddress) > IpAddressToLongBackwards(toIpAddress))
throw new ArgumentException("fromIP can not be bigger then toIpAddress.", fromIpAddress);



EntityId = entityId;
FromIpAddress = fromIpAddress;
ToIpAddress = toIpAddress;
}

/// <summary>
/// Claim Provider EntityID
/// </summary>
public string EntityId { get; set; }

/// <summary>
/// IP Address starting the range.
/// </summary>
public string FromIpAddress { get; set; }

/// <summary>
/// IP Address ending the range.
/// </summary>
public string ToIpAddress { get; set; }

/// <summary>
/// Function returning true if in IP is within the specified ip range.
/// </summary>
/// <param name="ipAddress">The ip to check.</param>
/// <returns>true if ip is in range otherwise false.</returns>
public bool IsInRange(string ipAddress)
{
var ip = IpAddressToLongBackwards(ipAddress);
return ip >= IpAddressToLongBackwards(FromIpAddress) && ip <= IpAddressToLongBackwards(ToIpAddress);
}
// Convert IPAddress to long backwards for comparison.
private static long IpAddressToLongBackwards(string ipAddress)
{
IPAddress ip;
if (!IPAddress.TryParse(ipAddress, out ip))
throw new ArgumentException(string.Format("The value '{0}' could not be parsed as an IP address.", ipAddress));

var byteIp = ip.GetAddressBytes();
var longIp = (long)byteIp[0] << 24;
longIp += (long)byteIp[1] << 16;
longIp += (long)byteIp[2] << 8;
longIp += byteIp[3];

return longIp;
}
}

 
So far so good but this was just a utility so lets do the real stuff by implementing our Deluxe Home Realm Discovery page we copied earlier. Open the HomeRealmDiscoveryDeluxe.aspx.cs file and add this using statement at the top together with the others.
using System.Collections.Generic;

…Then add this method that will automate the Home Realm Discovery if the user address can be found within the defined IP ranges.

protected void Page_Load(object sender, EventArgs e)
{
// First we need somewhere to keep our claim providers and while were on it, lets store some Claim Providers,
// this would be better to store in web.config, but for the sake of this example this will have to do.
var claimProviders = new List<AutomatedClaimsProvider>
{
new AutomatedClaimsProvider("", "10.45.2.1", "10.45.12.255"), // Local IdP – Empty String.
new AutomatedClaimsProvider(@"https://idp1.com/adfs/services/trust", "10.10.6.1", "10.10.6.255"),
new AutomatedClaimsProvider(@"http://idp2.org/adfs/services/trust", "192.168.20.1", "192.168.20.255")
};

// Get users IPAddress.
var ipAddress = Request.UserHostAddress;

// Check each AutomatedClaimsProvider if the ip is within its ip range then set Home Realm..
foreach (var claimsProvider in claimProviders.Where(claimsProvider => claimsProvider.IsInRange(ipAddress)))
{
// Match found, Set Home Realm to found identity provider.
SelectHomeRealm(claimsProvider.EntityId);
}

// No match, fall back on Home Realm Discovery page functionality.
}


The ranges – AutomatedClaimProviders should of course not be hard-coded like this but be placed in web.config or some other suitable place. Simply what this method will do is call the SelectHomeRealm not when the user clicks the Home realm Discovery page submit button but when a match on IP range for a Claims Provider is found.

Everything is now in place except one little detail and that is that we have to select the HomeRealmDiscoveryDeluxe.aspx as our Home Realm discovery page in web.config

<homeRealmDiscovery page="HomeRealmDiscoveryDeluxe.aspx" />

 

What else can be done

Well, that depend on requirements and of course what information is available but I’ve also made Home Realm Discovery decisions based on what the user has written in the user name field since a customer of mine used their email addresses as user name by putting it in the userPrincipalName attribute in AD. What happens in that case is that when the user have written their user name (email) and leaves the user name textbox a modal dialog is shown using ajax that propose the user to sign in using a predefined claims provider based on the email address.

Posted in: ADFS | Federation | WIF | Windows Identity Foundation | Home Realm Discovery

Tags: , , ,

New look and feel

October 12, 2011 at 9:39 PMHenrik Nilsson

It was definitely time for my blog to get a new look and feel but most of all it needed an update to get rid of all the spam messages I get from all those that wish to sell me SEO services, maybe the captcha will keep them busy.

I hope you like it!?

Posted in:

Tags:

Role Management in FIM?

September 23, 2011 at 4:38 PMHenrik Nilsson

It was announced today that Microsoft acquires “certain Assets”of BHold company but the roadmap isn’t clear yet.
Unaware of all products from BHold I guess it’s BHold’s Role Management pieces Microsoft lays their hands on or at least I hope it is…

Read more here:
Microsoft’s “Pathway”
Kuppinger Cole’ announcement

I wonder what this means for Omada? Or as Ian Glazer(Gartner) says:
If you get acquired by Microsoft (or Quest), you win! If you don’t get acquired, you lose and the risk to your market increases.  BHOLD wins the Microsoft IAG lottery

Posted in: Forefront Identity Manager | FIM 2010 R2 | Identity Management

Tags: , ,

The FIM Beta Exam 71-158 is available

July 20, 2011 at 7:25 PMHenrik Nilsson

Hurry up if you wish to take it, it’s been made available today and the beta period will end the 4:th of August.
You can read more on how to sign up at Born To Learn.

Unless you’ll be able to take the beta exam the real exam will according to what I’ve heard be available sometime between September and November.

Posted in: Forefront Identity Manager | Exam

Tags:

SAML Tracer for Firefox

July 1, 2011 at 7:57 PMHenrik Nilsson

I just wanted to recommend the terrific SAML Tracer extension for Firefox by Olav Morken at the Norwegian UNINETT, SAML debugging has never been this easy!

image

It works a bit like Fiddler except it’s simpler and it tags each HTTP request that contains a SAML AuthnRequest or Response. If you mark any of the HTTP Requests marked with the SAML sign you’re able to view the SAML message in clear text.

Check it out here: https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/?src=api or check out the press release from UNINETT: https://rnd.feide.no/2011/06/21/uninett-releases-public-beta-of-saml-tracer/

Posted in: ADFS | SAML | SAML2

Tags: , ,

Whats new in FIM 2010 R2

May 19, 2011 at 8:04 AMHenrik Nilsson

Check out this presentation on Channel9 from the ongoing TechEd Atlanta!

Technical Overview of Microsoft Forefront Identity Manager 2010 R2

Oops! Looks like the presentation isn’t live yet but stay tuned and it’ll show up according to the Identity and Access blogIt´s alive!!!

Posted in: Forefront Identity Manager | FIM 2010 R2

Tags: ,

Finally!!! SAML2 for WIF

May 16, 2011 at 10:51 PMHenrik Nilsson

For me WIF has been a cripple without the support for SAML2/SAMLP and I’ve been forced to look at products like the SAML2 from ComponentSpace and “SAML 2 for WIF” from Safewhere (not with us anymore and globeteam.comthat took over the product charged a fortune for using it) but finally I got stuck with OIOSAML/dk.nita originally developed by Safewhere financed by the national E-ID initiative in Denmark and released as Open Source that I’ve been delivering to a bunch of customers after a few changes to make it “less Danish”.

Except for throwing a lot of time away finding the right SAML2 component to deliver I’ve also been a pain in the a** on my Microsoft contacts for not delivering this and I hope my struggle has at least a bit made them understand why SAML2/SAMLP is so important to make WIF complete. I mean WS-Fed is not where the industry is heading even though others are supporting it…unwillingly…

I’ve heard a lot of excuses like “Why don’t you use WS-Fed instead?”, “Why don’t you set up an ADFS 2.0 environment for protocol translation?” - (at least 4 servers)  and “I’m sorry, I don’t understand why we haven’t released it either!” but finally it’s almost here and you can (and I will) check it out here!

Announcing the WIF Extension for SAML 2.0 Protocol Community Technology Preview!

…and additionally a note from Vittorio!…
http://blogs.msdn.com/b/vbertocci/archive/2011/05/16/attention-asp-net-developers-saml-p-comes-to-wif.aspx

…Never heard  about Vittorio or WIF – check this out from Techdays 2010: http://channel9.msdn.com/Blogs/liese/TechDays-2010--Windows-Identity-Foundation-Overview
I just love his – As you can hear from my accent… I’m from Redmond (with Italian accent).

Posted in: WIF | Windows Identity Foundation | SAML2 | Federation

Tags: , , ,

Action Approval

May 11, 2011 at 8:49 PMHenrik Nilsson

To start with, I’m not sure this is supported and maybe this is old news…

Anyway, have you ever wanted to interrupt a request with an approval when a new resource is provisioned into FIM (and already written to App DB) when you can’t do it in the authorization stage or maybe when a resource is transitioning in or out of a set even though the approval activity is an authorization activity and you OOB can’t add it to an action workflow?

With a small tweak this is possible…

  1. Head for Administration (within the portal, are you with me?)
  2. Click All Resources and then probably as number one the resource type - Activity Information Configuration
  3. What you see now is all the available activities within FIM and what we want to do is create a new one so go ahead and click the New button (maybe you have to give yourself rights as an administrator to add Activity Information Configuration resources)
  4. Add the following values to the Common Attributes page:
    Description: This activity applies for approval from specific approvers by mail and from action workflows.
    Display Name: Action Approval
  5. Switch to the Extended Attributes page and add the following values (these values are the same as for the AuthZ Approval activity, the only difference is “Is Action activity”):
    Activity Name: Microsoft.ResourceManagement.Workflow.Activities.ApprovalActivity
    Assembly Name: Microsoft.IdentityManagement.Activities, Version=4.0.2592.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
    Is Action Activity: Checked
    Type Name: Microsoft.IdentityManagement.WebUI.Controls.ApprovalActivitySettingsPart
  6. Click OK and then Submit.

What we’ve just done is created a new Activity resource that’s basically a copy of the original Approval activity (leaving the OOB FIM configuration unchanged is a best practice) but with the difference it’s available for interrupting action workflows before subsequent activities actually do anything that requires an approval.

image

Have fun!

Posted in: Forefront Identity Manager | Workflow | Approval

Tags: , , ,

Additional OOB and Custom Sync Rule Functions… Again!

April 6, 2011 at 9:45 PMHenrik Nilsson

One of the wishes for additional functionality in FIM I’ve had since ILM2 has been custom Sync Rule Functions and except for adding a feature request to Connect that got a lot of votes (and was closed with “Won’t Fix) I blogged about it here.

Why?

The reason I want preferably custom and more OOB functions is simply the available functions are way too limited and much too often you’ll have to fall back on MA Extensions or creating custom workflows/activities where the Function Evaluator can’t help.

I’ve discussed this with a member of the product team and he claims that even though there is a public Sync Service interface allowing for this and a FIM Service system resource type (Function) this has never been a plan, instead this has just been a way of implementing the current functions that remains in the Functionlibrary.dll that is hardcoded to both the FIM service and the Sync Service.

The Survey

Since I’m not a person that takes no as an answer I did a little survey that I addressed my MVP friends and some other FIM initiated friends (and their friends within Microsoft) giving them my ideas for new OOB functions since I’ve got the hint that custom functions are far away from being a reality and asked them to suggest functions they would like to see in FIM in a not too far future.

The Answers

Even though the hint I got and communicated in the survey that custom functions are far away and instead asked for ideas for OOB functions they wished almost everyone said that custom and reusable functions is the only way to satisfy our demands, here are some of the comments …

  • Quite frankly I don't see how they could ever satisfy all the requirements we could come up with. Allowing us to add functions is the only logical solution.
  • Please allow an extension to provide our own custom functions - this was also suggested during the summit. And while we're at it, please allow the same extension to be used for relationship criteria.
  • Could not agree more :), it's what's missing.. I can't stand sync rules.... this would help with the pain...
  • However, I totally agree that custom functions are the only way to satisfy all our requirements, including those that we can't think of right now but that we will have to face some day. In this way, no matter how many more functions we get, we won't be able to use only codeless provisioning.

As you can see above, there’s also a demand for allowing functions in the Sync Rule relationship and I totally agree, as it is now it could be hard to get usable “joins” when having similar but not perfectly equal values for joining on!

OOB functions?

Except for custom functions there’s a demand for more OOB functions that could be used by those who isn’t considering themselves developers. Some of the ideas were so similar that I took the freedom to join them. I got an answer with code examples where I choose not to include the code for readability and I hope it is clear enough anyway.

  • Delete()
    Issue a .Delete on the MV Attribute to clear out unwanted or orphaned data due to removal of flow rules
  • ToInt(string)
    Cast the string to an integer, useful when you have to change an integer based anchor into a string to contribute elsewhere but need to provision it out
  • GetBitOperator(int bitmask, mask)
    Returns true/false of whether or not a bit is active in the mask
  • ConvertGeneralTimeToISO8601(string generalizedtime)
    Converts a flat string date
  • ConvertFileTimeToISO8601(datetime filetime)
    Converts a FileTime attribute to a format the FIM WS can accept
  • GeneratePassword(number length)
    Generate complex password from some predefined character group.
  • GeneratePassword(number length, string chargroup1)
    Generate complex password using characters from chargroup1.
  • GeneratePassword(number length, string chargroup1, string chargroup2)
    Generate complex password using characters from chargroup1 and chargroup2.
  • GeneratePassword(number length, string chargroup1, string chargroup2, string chargroup3)
    Generate complex password using characters from chargroup1 and chargroup2 and chargroup3.
  • IsUnique
  • AddDays(Now(), 15)
  • AddMonths(Now(), 6)
  • Len (string value)
    Function that returns the length of a string, 0 if null or empty.
  • ToString (any type value)
    Function that converts any datatype to string.
    (it’s so irritating trying to map an integer value to a string during inbound sync, for example to employeeID and you get an error)
  • Split (string value, string separators)
    Function that splits a string into a multi-valued string.
  • Join (string multi-valued value, optional string separator)
    Function that joins a multi-valued string value into a single-valued value with an optional separator string.
  • Index (any type multivalued value, number index)
    Function that returns a single value of the same datatype as the multi-valued input value by index.
  • Add (any type multivalued value,  any type single-valued value to add)
    Function that adds a single-valued value to a multi-valued value of the same type (one use could be for handling object classes in LDAP directories)
  • Remove(any type multivalued value, any type single-valued value to remove)
    Function that removes a single-valued value from a multi-valued value of the same type.
  • RegexReplace(string value, string pattern, string replace)
    Function that does a string replace using a regex pattern.
  • StartsWith(string value, string startswith)
    Function useful for finding out if a string starts with a specific string when doing IIF’s.
    Could maybe be solved using the already available Mid function but this is easier.
  • EndsWith(string value, string endswith)
    Function useful for finding out if a string ends with a specific string when doing IIF’s.
    Could maybe be solved using the already available Mid function but this is easier.
  • IsValid(string value, string pattern)
    Function for validating an input value using a regex pattern when doing IIF’s
  • Format(string format, string value1, string value2, string value3… )
    Function that replaces the format item in a specified string with the string representation of a corresponding string in a specified parameter. I just love this function on the .Net string object and I think it could be really useful even thought I understand it could be hard implementing a user interface for and since the FIM functions can’t accept arbitrary number of parameters.
  • Now()
    Function that returns the current date and time.
  • Normalize(string value)
    Function for normalizing characters like ÅÖÄÜ etc. and removing all kinds of diacritics when for example creating email addresses. I’m told this could be done using the EscapeDNComponent function but that’s only available for outbound sync rules.
  • Word (string value, number index, string separators)
    This already available function doesn’t allow you to use an attribute as value only a fixed string.

Conclusion

I’m not the only one asking for this functionality but in order to make a change we need to get votes for it on Connect therefore I’ve made a new request that you can find here:

Custom and additional OOB Sync Rule Functions (again)...

Go ahead and vote for it but don’t forget to make a comment why you wish to be able to create custom functions that can be reused and have a larger set of OOB functions. Also don’t be afraid inviting you friends to vote and publish this or the connect feature request on any social media! Smile

Posted in: Forefront Identity Manager | Sync Functions | Sync Rules | Workflow

Tags: