Identity Management through FIM

An Ex-MSFTie's thoughts

Posts tagged FIM

2 notes &

Correct syntax for case insensitive regular expressions in RCDC

Just noticed the documentation was incorrect for the RCDC in FIM.  Here’s what it hsould be 

 

Making regular expressions case insensitive

In FIM 2010, it can be helpful to make some regular expressions case insensitive. You can ignore case within a group by using ?!:. For example, for Employee Type, use the following:

^(?i:contractor|full time employee)$

The incorrect version was ^(?!:contractor|full time employee)%

Filed under fim rcdc case insensitive regular expression

27 notes &

FIM: Kick Off AuthN/AuthZ from within activities

I thought I posted the follow up but must’ve got sidetracked.

Scenario:
User John does an update request on John.Manager => launches authorization workflow, which uses the public client to create a request to the middle tier on John’s behalf?

If you enable delegation on your public proxy WCF bindings, you can in your activities impersonate the user credentials with this call:
(actually, you may only need to be impersonation since you’re impersonated call never leaves the box to talk to the fim service)

ServiceSecurityContext.Current.WindowsIdentity.Impersonate();

Then, if you use the public client in your code to make calls to the fim service, you will be under that user’s credentials and can kick off other necessary MPRs.

Couple of salient points:

1. All code that follows that impersonation call will be under the users credentials. Makes sense right? So what happens if you have a create activity or an update activity in your workflow? It fails b/c that thread is under the user context so any connections to the sql fim store to run any sprocs will fail b/c that user doesn’t have access to the DB.

2. ServiceSecurityContext is backed by a [ThreadStatic] attribute. ThreadStatic means an variable is scoped only to the current thread. Which means if you fork a new thread, that context is lost. So why does this matter to us? Well, when workflows passivate or get persisted to the DB (ex: when an activity is waiting on input from an approver), that context gets lost. So when your code comes back up, you no longer have access to ServiceSecurityContext.

3. If you’re under the impersonated context when the workflow passivates….wild things may happen. Haven’t tested it.

4. You no longer have parenting of requests. There are no longer chains of requests so if you cancel a parent request, the new request you spawned may

5. You have to handle the logic of how to wait on the new request you just spawned: does your activity proceed if there’s an authz workflow kicked off? Does it wait on the input? What if there’s an authn workflow? Does it handle the child requests interactive action workflows? Yup, it’s very nasty and hairy to solve in the general case (there is a reason why the FIM team doesn’t have this enabled by default)

Here’s what I would suggest (haven’t had time to fully explore this, just used this to implement delegation as a proof of concept):

1. Store the WindowsIdentity locally when overriding OnActivityExecutionLoad

2. Have very simple defined cases of when you kick off requests that spawn new AuthZ workflows. Don’t try to solve the general case. Any case that requires chainign of requests => pain

3. Keep the impersonation scope very limited and defined:

using(ServiceSecurityContext.Current.WindowsIdentity.Impersonate())

{

//Code to call public client to talk to FIM service

}//Impersonation is always reverted this way

4. For auditing/reporting, the child request that gets created this way will have the user as the actorID. Just be aware.

Filed under FIM Delegation activities authz

27 notes &

Turning On FIM/WCF Tracing

First, let it be known that I hate xml config files.  It’s a pain in the ass to write a script to modify certain portions of it…like when I want to turn off or turn on tracing in the FIM portal or the RMS.  So I usually resort it to doing it by hand….which is terrible because I always forget small details.

Like why is message logging not happening? Oh yeah.  Have to add this tag:

<system.serviceModel>

    <diagnostics wmiProviderEnabled=”true”>

        <messageLogging 

             logEntireMessage=”true” 

             logMalformedMessages=”true”

             logMessagesAtServiceLevel=”true” 

             logMessagesAtTransportLevel=”true”

             maxMessagesToLog=”3000” 

         />

    </diagnostics>

    <behaviors>

       <serviceBehaviors>

          <behavior name=”Default”>

             <serviceDebug includeExceptionDetailInFaults=”true”/>

            </behavior>

        </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

  <system.diagnostics> 

    <sources> 

      <source name=”System.ServiceModel.MessageLogging” switchValue=”Verbose,ActivityTracing”> 

        <listeners> 

          <add type=”System.Diagnostics.DefaultTraceListener” name=”Default”> 

            <filter type=”” /> 

          </add>

          <add name=”DiagnosticListener”> 

            <filter type=”” /> 

          </add> 

        </listeners> 

      </source> 

      <source name=”System.ServiceModel” switchValue=”Information,ActivityTracing” propagateActivity=”true”> 

        <listeners> 

          <add type=”System.Diagnostics.DefaultTraceListener” name=”Default”> 

            <filter type=”” /> 

          </add> 

          <add name=”DiagnosticListener”> 

            <filter type=”” /> 

          </add> 

        </listeners> 

      </source>

      <source name=”Microsoft.ResourceManagement” switchValue=”Verbose,ActivityTracing” propagateActivity=”true”>

        <listeners>

          <add type=”System.Diagnostics.DefaultTraceListener” name=”Default”>

            <filter type=”” />

          </add>

          <add name=”DiagnosticListener”>

            <filter type=”” />

          </add>

        </listeners>

      </source>

    </sources> 

    <sharedListeners>

      <add initializeData=”C:\logs\FIMPortal.Client_tracelog.svclog” type=”System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”

        name=”DiagnosticListener” traceOutputOptions=”LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack”>

        <filter type=”” />

      </add>

    </sharedListeners> 

    <trace autoflush=”true” />  

  </system.diagnostics> 

Filed under FIM logging tracing wcf

0 notes &

Sample SMS OTP Authentication Activity for FIM

I published all the source code for the OTP Demo I did over at TEC at https://github.com/ikrima/Public-Development

The source code contains a sample password reset activity using the interactive activity, the SMS One Time Password Authentication activity, an aspx web app that allows you to perform web based password reset, and the necessary public client extensions that allow you to talk to interactive activities (it would be easy to extend it to communicate to the OOB Password Reset Activity)

Filed under FIM password reset otp one-time password

19 notes &

Speaking at TEC in vegas! What would you like a focus on?

So I’m speaking at The Experts Conference (TEC) this year in vegas.  I have two presentations and as I’m wrapping up writing them, I realized that there’s just way too much content for two one hour presentations.  So I carved out the important bits but I figured I’d ask the interweb about the rest: what would you like an emphasis on?

Presentation 1: How to write custom authentication activities in FIM (e.g. OTP)

- Writing GINA Win32 UI (so your activity shows up in GINA)

-Extending the public client to talk to authentication activities for password reset

-Writing interactive activities (e.g. a non-password reset activity)

Presentation 2: Delegation model in FIM

- Which example should we work through: Approve on Behalf of vs. Password Reset on behalf of (It admin resets the password of another user)

-Go into detail about extending the public client to talk to interactive activities

-How to write activities invoke authorization workflows on the user’s behalf (impersonation)

Filed under FIM TEC The Experts Conference Password Reset Authentication

0 notes &

Types of Load on FIM Service

The FIM webservice is multithreaded so each new client request has its own request and request state (SQL is the persistence store that’s used).  So the number of active “requests” is limited to whatever your WCF configuration binding dictates (you can set maximum number of simultaneous TCP/IP connections, maximum timeout, maximum payload, etc etc etc). These configuration parameters dictate how many active connections you have, as opposed to requests in the system.

Now each request may spawn off AuthN, AuthZ, or Action Workflows.  And those workflows are run in parallel by the Workflow Engine.  AuthN workflows run in their own “context” and they are synchronous to each request.  For example, if Ikrima requests to join BillG’s Direct Reports and he kicks off 2 authentication workflows and at the same time, Frank requests to join Administrator’s Group and he kicks off an AuthN workflow, what will happen?

Well both requests will happen at the same time b/c the webservice is multi-threaded. So here’s a timeline view

Ikrima

 Join Group

 Authenticate to AuthN Workflow 1

Authenticate to AuthN Workflow 2

Continue processing

Frank

Join Group

Authenticate to AuthN Workflow 2

Continue Processing

So the webservice sequentially processes AuthN workflows in the context of one request.

Now what about AuthZ/Action workflows?  Well those are asynchronous. Suppose Ikrima joins BillG’s group and he kicks off an Email Notification workflow and an Approval Workflow.  And suppose Frank does that at the same time.  What does that look like?

Ikrima

Join Group

Approval Workflow Gets Kicked Off <—-Notice, they get kicked off at the same time

Email Notification Workflow Gets Kicked off  <—-Notice, they get kicked off at the same time

Frank

Join Group

Approval Workflow Gets Kicked Off  <—-Notice, they get kicked off at the same time

Email Notification Workflow Gets Kicked off  <—-Notice, they get kicked off at the same time

So how many workflows do we have in flight in the AuthN scenario?  2 at most.  Ikrima’s AuthN Workflow 1 & Frank’s AuthN Workflow 1.

What about AuthZ? 4. Ikrima & Frank’s Approval & Email workflows.

And now how many workflows can we have inflight at the same time?  Well, those are determined by configuration parameters

So why is there a different maxSimultaneousAuthenticationWorkflows & maxSimultaneousAuthorizationAndActionWorkflows?

Well, remember that Authorization/Action workflows can be long-running and are asynchronously invoked.  For example, the approval activity needs to wait on a manager to approve a request.  But, the approval activity doesn’t need to be running and in memory the entire time.  So, it can passivate (aka store itself & state to SQL) and then the workflow engine can go off and process another workflow.

Authentication activities are a different matter.  We need a response right now; imagine if when logging in or resetting your password, you were stuck waiting on a manager’s approval to authenticate yourself.  So, because of this, authentication workflows never passivate which is why I said earlier, you would have a problem trying to get 70k users registering at the same time.

As far as how many longstanding requests are in the system, well, you can have as many as your system handles it (and maybe there are some other configuration parameters that cull out expired requests too).

Filed under FIM performance

0 notes &

How To Retrieve Endpoint address in Custom Interactive Activities

This has been frustrating me for a couple of days since I couldn’t find a supported way of doing it, so I finally just found a way to use reflection to poke deep into some dataexchanges.  Use at your own risk, as this is not supported.
In your activity, you write:

protected override void OnActivityExecutionContextLoad(IServiceProvider provider)

        {

            if (this.baseAddresses == null)

            {

                Type hostActivationServiceInteralType =typeof(Microsoft.ResourceManagement.AuthenticationWorkflowMode).Assembly.GetType(“Microsoft.ResourceManagement.Workflow.Runtime.HostActivationService”);

                hostActivationServiceInternalObject = provider.GetService(hostActivationServiceInteralType);

 

                var propertyInfo = hostActivationServiceInternalObject.GetType().GetProperty(“BaseAddresses”,

                                                                                            BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

 

                if (propertyInfo != null)

                {

                    ReadOnlyCollection<Uri> result = propertyInfo.GetValue(hostActivationServiceInternalObject, nullas ReadOnlyCollection<Uri>;

 

                    this.baseAddresses = new List<string>();

                    if (result != null)

                    {

                        foreach (Uri baseAddress in result)

                        {

                            if (baseAddress.AbsoluteUri.StartsWith(“http:”,StringComparison.OrdinalIgnoreCase))

                            {

                                this.baseAddresses.Add(baseAddress.AbsoluteUri);

                            }

                        }

                    }

                }

Filed under FIM

1 note &

How To Bulk Register Users for Password Reset in FIM

To do this bulk load, you have to understand how the FIM engine stores authentication information. To make this simple, let’s use the User Ikrima as our user, the default QA Activity as the authentication activity, and the default authentication workflow as our example (but you can generalize to everything else)

  • Ikrima has a multi-valued attribute (AuthNWFRegistered ) that lists all the workflows that he has registered for.  This attribute normally gets populated by FIM when Ikrima finishes registration.

So, to programmatically register Ikrima, you would need to insert the GUID of the default AuthN Workflow (9c3aca59-a85c-437f-bb67-9ce5a70521d7) into Ikrima.AuthNWFRegistered

  • Now each activity in your AuthN workflow stores its registration data in GateRegistration Objects (the workflow engine creates these objects, the activity is only responsible for providing the data it needs to store).  So, you’ll need to use the FIM Public client to create those objects.  Some activities (such as the PasswordCheckGate & LockoutGate) do not need to create registration data.  The QA Activity does.

So what goes inside a GateRegistration Object? Well, here are the attributes you need to fill

  1. GateID - This identifies which instance of the QA Activity in that workflow this registration data is tied to.  For example, if we had two different QA Activities inside one workflow, which one does this Gate Registration Object belong to?  That’s what GateID is for.  What is the format of GateID?  Well, it’s the QualifiedName of the activity (in the workflow context, you can retrieve it from Activity.QualifiedName).  But where else can you retrieve this?  Look at the XOML of the workflow definition.
For example, here’s the XOML snippet for the OOB authn definition:
<ns0:AuthenticationGateActivity ValidationError="{x:Null}" x:Name="authenticationGateActivity3" RegistrationData="{x:Null}" ChallengeResponse="{x:Null}">
    <ns0:AuthenticationGateActivity.AuthenticationGate>
      <ns0:QAAuthenticationGate ResponseTimeout="00:05:00" NumQsReqCorrectAns="3" NumQsReqRegistration="3" NumQsRandomPresented="3" NumQsDisplayedForReg="3" ValidationError="{x:Null}">
        <ns0:QAAuthenticationGate.Questions>
          <x:Array Type="{x:Type p9:String}" xmlns:p9="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <ns1:String xmlns:ns1="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">Customized Question 1</ns1:String>
            <ns1:String xmlns:ns1="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">Question Custom 2</ns1:String>
            <ns1:String xmlns:ns1="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">The 3rd question</ns1:String>
          </x:Array>
        </ns0:QAAuthenticationGate.Questions>
      </ns0:QAAuthenticationGate>
    </ns0:AuthenticationGateActivity.AuthenticationGate>
  </ns0:AuthenticationGateActivity>

You can see, the Activity name is “authenticationGateActivity3”.  

  1. GateType - This used to specify the type of activity tied to this GateRegistration object.  For example, it would distinguish between LockOut Activity vs. QA Activity.  To my recollection, this isn’t used anymore.  But, the QA GateType ID is 45C4D8BB-D34C-453d-8346-C9061A2A1E4C
  2. UserID - This is the GUID of the Ikrima user object
  3. WorkflowDefinition - This is the GUID of the Password Reset AuthN Workflow: 9c3aca59-a85c-437f-bb67-9ce5a70521d7
  4. GateData - Now this is the custom data that the QA Gate activity stores.  If you look at the public client solution, you can see that other people have reverse engineered this data format.

To rehash that, the GateData for QA Gate is in the format:
answerIndex + ‘\n’ + SHA256Hash( normalizedResponse(userAnswer)+user.Guid.ToString()).GetUnicodeEncoding() + ‘\n’
normalizeResponse() means strip all the whitespace and turn everything to lower case; also, answerIndex starts at 1, not 0. So answerIndex = 1 means the answer to question 1; 0 is not a valid index.  So, an example layout would be
2’\n’djfkddjfkddjfkddjfkddjfkddjfkddjfkddjfkd’\n’ 4’\n’djfkddjfkddjfkddjfkddjfkddjfkddjfkddjfkd’\n’

After you created the Gate Registration Object for the QA Gate, your user should now be able to authenticate against the AuthN Password Reset Workflow

Filed under FIM Password Reset Registration

0 notes &

FIM Gotcha with Interactive Endpoints: Security Check Failed

Alright, after a couple of hours of troubleshooting a customized deployment, I found the probable cause. This fault is what’s returned from any activity that uses the XmlInteractiveActivity (e.g. Password Reset, Approval activity, etc) when validation fails.

When a client talks to these activities, it talks to them directly through an endpoint they create.  In my case, we were talking directly to the Password Reset activity. The PWResetActivity gives access to its endpoint to two users (Anonymous & the user who’s trying to reset his password).  

But, how does it determine if a user is anonymous?
Well, it does a sid lookup of the credentials coming in and matches it with sids in the FIM store.
If there’s no match, it stamps the identity as Anonymous.

Now when would this be problematic?
Well, if you set the identity of the PwdMgmtProxy.exe service to a FIM Account, every request to reset password will happen in that FIM Account’s context.
And every password reset will fail.

Same thing happens if you have a custom client that’s talking to the endpoints directly running under an account that’s in the FIM Store. This is not necessary when communicating with the FIM Service endpoint because it stamps any request coming in through the alternate endpoint as anonymous, regardless of the windows credentials attached to your request.

Why is this layer necessary? 
Well when you get to the password reset endpoint, it’s a separate interactive workflow endpoint, created by the receive activity.  
So without this layer, any user can talk to that endpoint to reset the password of users going through this workflow.

Filed under FIM Troubleshooting