Jan 23 2011

WorkflowApplication throws ObjectDisposedException on ActivityContext with LINQ queries

Category: .NetRory Primrose @ 08:33

I have written a simple WF4 activity that validates a WIF IClaimsIdentity has certain claims attached to it for a specific claim value. I wrote several unit tests for this activity to validate the implementation. The basic logic is to select a subset of claims that have a specified claim value using Where(). I then fall into a flow chart that validates whether there are any claims (Any() == false) and then whether there is only one claim (First() with a Count()) of a specified claim type that will not be accepted.

image[2]

Almost all of the tests failed with the following error:

Test method Neovolve.Jabiru.Server.Business.UnitTests.Activities.DemandAnyDataChangeClaimTests.DemandAnyDataChangeClaimThrowsExceptionWithManageOnlyClaimTest threw exception System.ObjectDisposedException, but exception System.Security.SecurityException was expected. Exception message: System.ObjectDisposedException: An ActivityContext can only be accessed within the scope of the function it was passed into.
Object name: 'System.Activities.ActivityContext'.

This seemed a little strange as the activity being tested is very simple. The only complexity is that the activity does use a few LINQ queries. Strangely one of the tests did pass and it was one that tested an identity without any claims. I then made a change to one of the other failed tests to remove it’s claim from the test identity and the test then passed. The most likely cause of the exception is the LINQ queries against the claims of the identity.

So this clearly seemed like a bug somewhere in WF. The first net search result turned up with this post on MSDN forums which does indicate a bug with WF and LINQ.

Andrew notes in the forum response that this is a bug that will not get fixed by RTM so it is probably the same issue I am having here. The forum makes some suggestions about how to get around this issue but I was hoping for a simple workaround.

I guessed that perhaps the issue might be due to LINQ queries against a particular IEnumerable<T> type. I then tried putting a ToList() onto the original Where query. Now all the tests pass as expected. This simple workaround is just changing the data type to IList for the other LINQ operations (Any(), First() and Count()) to operate on rather than the IEnumerable returned from Where().

Tags: ,

Jan 3 2011

Stardust theme update instructions for BlogEngine.Net 2.0

Category: .NetRory Primrose @ 06:54

I had a couple of issues with the excellent Stardust theme I use on this site after upgrading to BlogEngine.Net 2.0. The following are the changes I made to make the theme compatible.

  1. Post.IsCommentEnabled has been changed to Post.HasCommentEnabled. This appears in themes/stardust/PostView.ascx.
  2. Login.aspx has been moved into the Account folder. Modify the reference to this in themes/stardust/site.master in the code MenuClass("account/login.aspx")
  3. Similarly to #2, modify the reference to login.aspx in themes/stardust/site.master.cs in the two references to aLogin.HRef

All these three references need to be changed from login.aspx to account/login.aspx.

Tags:

Jan 3 2011

Neovolve.BlogEngine.Web 2.0 released

Category: .Net | My SoftwareRory Primrose @ 06:25

Along with the updates to my BlogEngine.Net extensions, Neovolve.BlogEngine.Net.Web 2.0 is now released.

Neovolve.BlogEngine.Net.Web 2.0 contains an HTTP module that supports CS style urls (as of several years ago at least). There is no functional change in this release as it is simply a refresh against the latest BlogEngine.Net 2.0 binaries.

You can download this release from here.

Tags:

Jan 3 2011

Neovolve.BlogEngine.Extensions 2.0 released

Category: .Net | My SoftwareRory Primrose @ 05:46

I have upgraded this blog to BlogEngine.Net 2.0 that was released yesterday. As part of this I have updated my extensions to support the new code base.

You can download it from here.

Tags:

Nov 21 2010

CodeCampOz: Not a WIF of federation

Category: .NetRory Primrose @ 09:17

My presentation of Not a WIF of federation is done and dusted for CodeCampOz 2010. I got a little cut short by the early arrival of pizza’s so there are a couple of things I had to skip.

One of the important points I was not able to make is that the demo code displayed is not production ready. It’s not that the code itself is flawed rather that the certificates used were development certificates. It is important to secure your WIF implementation with production quality certificates in order to ensure that system security is maintained.

Identity delegation was the last demo that I presented. I didn’t get the opportunity to show the code that was changed in the STS application to make this work. The code in the STS project had not be changed up until this point. The GetOutputClaimsIdentity method of the CustomSecurityTokenService class simply returned a new ClaimsIdentity created from the provided principal. The delegated identity scenario needs to explicitly cater for the ActAs scenario by attaching the delegating identity to the Actor property on the delegated identity being returned.

protected override IClaimsIdentity GetOutputClaimsIdentity(IClaimsPrincipal principal, RequestSecurityToken request, Scope scope)
{
    if (null == principal)
    {
        throw new ArgumentNullException("principal");
    }
 
    IClaimsIdentity claimsIdentity = new ClaimsIdentity(principal.Identity);

    // If there is an ActAs token in the RST, return a copy of it as the top-most identity
    // and put the caller's identity into the Actor property of this identity.
    if (request.ActAs != null)
    {
        IClaimsIdentity actAsSubject = request.ActAs.GetSubject()[0];
        IClaimsIdentity actAsIdentity = actAsSubject.Copy();

        // Find the last actor in the actAs identity
        IClaimsIdentity lastActor = actAsIdentity;
        while (lastActor.Actor != null)
        {
            lastActor = lastActor.Actor;
        }

        // Set the caller's identity as the last actor in the delegation chain
        lastActor.Actor = claimsIdentity;

        // Return the actAsIdentity instead of the caller's identity in this case
        claimsIdentity = actAsIdentity;
    }

    return claimsIdentity;
}

The RP that receives the delegated identity can now look at the Actor property on the IClaimsIdentity to see if the RP is being invoked by a delegating identity.

You can download the source code for the demos and the PowerPoint deck from the link below. The solution in the zip requires that you have WIF installed and the default development certificates configured by FedUtil. You can do this by creating a new project and running FedUtil and adding an STS/IP project. The other requirement is that you have a localhost SSL certificate configured in IIS.

CCOZ2010-NotAWIFOfFederation.zip (1.06 mb)

Tags:

Nov 9 2010

Managing content correlation failures

Category: .NetRory Primrose @ 11:05

I posted yesterday about how to get content correlation of multiple WCF service operations to work with hosted WF services. The request and reply data of the WCF service operations is the basis of content correlation. It is therefore quite easy for a client application to send data to the service that does not satisfy business validation.

If the invalid data sent to the service operation participates in content correlation then the WorkflowServiceHost will not identify a WF instance. This unfortunately means that business validation of this data will not run in the workflow as no workflow instance is executing. The result is that the client will receive the following very unfriendly FaultException (assuming no exception shielding is in place).

System.ServiceModel.FaultException: The execution of an InstancePersistenceCommand was interrupted because the instance key 'bea948ac-70fa-b125-91e6-f06752ce7671' was not associated to an instance. This can occur because the instance or key has been cleaned up, or because the key is invalid. The key may be invalid if the message it was generated from was sent at the wrong time or contained incorrect correlation data.
   at System.ServiceModel.Activities.Dispatcher.ControlOperationInvoker.ControlOperationAsyncResult.Process()
   at System.ServiceModel.Activities.Dispatcher.ControlOperationInvoker.ControlOperationAsyncResult..ctor(ControlOperationInvoker invoker, Object[] inputs, IInvokeReceivedNotification notification, TimeSpan timeout, AsyncCallback callback, Object state)
   at System.ServiceModel.Activities.Dispatcher.ControlOperationInvoker.InvokeBegin(Object instance, Object[] inputs, IInvokeReceivedNotification notification, AsyncCallback callback, Object state)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

If exception shielding is in place by using an IErrorHandler implementation then the client should get a generic service fault message instead. Neither scenario is appropriate as the actual failure is due to the service receiving invalid business data. The service should be able to provide a meaningful business fault to the client in this case to indicate what the client application has done wrong.

This is the outstanding issue from yesterday’s post. How can the service identify that the FaultException thrown relates to a correlation failure and determine which content correlation was the cause?

My scenario from yesterday’s post was using a TransactionId as the value that participates in content correlation between the RegisterAccount and ConfirmRegistration service operations. The client should expect a known business fault that identifies that the TransactionId is invalid rather than the above generic FaultException or shielded exception.

The solution to this issue is to extend the behaviour of an IErrorHandler implementation. The change in question will be to determine that the thrown exception is a content correlation exception. It will then convert the exception to a specific business fault based on the current service operation.

The ProvideFault method in the IErrorHandler implementation in the service has been updated to manage this detection and conversion process.

public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
    Exception errorToProcess = AttemptBusinessFailureExceptionConversion(error);

    BusinessFailureException<BusinessFaultCode> businessFailure = errorToProcess as BusinessFailureException<BusinessFaultCode>;

    if (businessFailure != null)
    {
        IEnumerable<BusinessFaultItem> faultSet = CreateFaultSet(businessFailure.Failures);


        BusinessFault businessFault = new BusinessFault(businessFailure.Message, faultSet);
        FaultException<BusinessFault> faultException = new FaultException<BusinessFault>(businessFault, businessFailure.Message);
        MessageFault messageFault = faultException.CreateMessageFault();

        fault = Message.CreateMessage(version, messageFault, faultException.Action);
    }
    else
    {
        SystemFault systemFault;
        {
            SystemFailureException systemFailure = errorToProcess as SystemFailureException;
            SecurityException securityFailure = errorToProcess as SecurityException;

            if (systemFailure != null)
            {
                systemFault = new SystemFault(systemFailure.Message);
            }
            else if (securityFailure != null)
            {
                systemFault = new SystemFault(Resources.FaultHandler_AccessDenied);
            }
            else
            {
                systemFault = new SystemFault(Resources.FaultHandler_UnknownFailure);
            }
        }

        FaultException<SystemFault> faultException = new FaultException<SystemFault>(systemFault, systemFault.Message);

        MessageFault messageFault = faultException.CreateMessageFault();

        fault = Message.CreateMessage(version, messageFault, faultException.Action);
    }
}

The existing code already managed a BusinessFailureException<T> and converted it to a BusinessFault that is a known fault contract for the service. The method now makes a call out to AttemptBusinessFailureExceptionConversion as an initial step.

private static Exception AttemptBusinessFailureExceptionConversion(Exception errorToProcess)
{
    FaultException thrownFaultException = errorToProcess as FaultException;

    if (thrownFaultException == null)
    {
        return errorToProcess;
    }

    FaultCode faultCode = thrownFaultException.Code;

    if (faultCode == null
        || faultCode.IsPredefinedFault == false
        || faultCode.IsSenderFault == false)
    {
        return errorToProcess;
    }

    FaultCode subCode = faultCode.SubCode;

    if (subCode == null
        || subCode.Namespace != "http://schemas.datacontract.org/2008/10/WorkflowServices"
        || subCode.Name != "InstanceNotFound")
    {
        return errorToProcess;
    }

    String contractName = OperationContext.Current.IncomingMessageHeaders.Action;

    if (contractName == "http://tempuri.org/IRegistration/ConfirmRegistration")
    {
        return new BusinessFailureException<BusinessFaultCode>(BusinessFailureStore.InvalidTransactionIdProvided);
    }
    
    return errorToProcess;
}

The AttemptBusinessFailureExceptionConversion method looks for a predefined FaultException thrown by the service that has a particular failure code. Correlation failures have a Code.SubCode name of InstanceNotFound with the namespace of http://schemas.datacontract.org/2008/10/WorkflowServices. The method can return a specific business failure now that a correlation failure has been identified.

The business failure to return will be determined based on the current service operation. In this scenario there is a check that the failed service operation is the IRegistration.ConfirmRegistration method. A TransactionId value is the content correlation value for this service operation. If the WorkflowServiceHost is not able to identify a workflow instance using the provided TransactionId then the TransactionId value is invalid. This is the business failure that is then returned. The ProvideFault method then continues its existing logic by processing the business failure as an appropriate business fault.

Tags: ,

Nov 8 2010

Hosted workflow service with content correlation

Category: .Net | ApplicationsRory Primrose @ 11:33

Content correlation in hosted WF services seems daunting but is surprisingly simple to use with the available designer support. Content correlation uses data from the workflow to link (correlate) multiple WCF service operations to the same hosted workflow instance. Content correlation is different to context correlation where WCF communication down at the binding level handles correlation. There is unfortunately a lack of detailed examples available on how to get content correlation to work. This post aims to fill that gap.

I have an account registration scenario where the first service operation is to request a new account. The request needs to provide a first name, last name, email address and a password. The register account workflow will run some validation logic and then send an email to the email address with a link back to a website for confirmation.

The confirmation of a registration requires a TransactionId and ChallengeCode. The confirmation link in the email contains the TransactionId and registration request operation returns the ChallengeCode to the user. The service never returns the TransactionId and the email never contains the ChallengeCode.

The user must provide both the TransactionId and the ChallengeCode to the confirmation screen of the website to confirm the registration. This design provides registration security because it ensures that the registration belongs to a valid email address and that the person confirming the registration is the person who made the registration request because only they have both the TransactionId and the ChallengeCode combination. This is similar to how public/private keys work in cryptography.

The registration service workflow looks like the following.

image

The registration service receives the message for RegisterAccount and runs the register account logic. This process generates the TransactionId and a ChallengeCode and sends the confirmation email. The workflow then waits for the confirmation request to come back or for a timeout value to occur. Some kind of correlation is required to link the RegisterAccount service operation to the ConfirmRegistration service operation to ensure that the same workflow instance executes the related service operations.

This registration process cannot use context correlation because there is no WCF binding available that would support this scenario. Different applications may execute the registration and confirmation operations with no knowledge between them. A rich client may make the original registration request while the website processes the confirmation. Context correlation still would not work even if the original registration request and subsequent confirmation were processed by the same website as there is no WCF session between the two website requests. This workflow must use content correlation to link the original registration request with the subsequent confirmation request.

The first step of correlation is to define a CorrelationHandle variable on the workflow at a scope level that is available to both service operations. This variable is the reference that links the service operations using the nominated correlation data.

image

There are two ways that content correlation may satisfy this registration workflow. The first method uses content references that are only available in the service contract. The second method provides a content correlation solution that only partially relies on the service contract data.

Method 1 – Content correlation based on service contract data

This first method uses the correlation support in solely available in the SendReceive activity pairs. The value to correlate on in this case is the ChallengeCode value as it exists as part of the service contract for the RegisterAccount call (the response) and the ConfirmRegistration call (a request property).

The CorrelationInitializers property for the RegisterAccount SendReceive activities must define the content data to correlate the two service operations. The ChallengeCode is generated as part of the RegisterAccount workflow so this value cannot be assigned in CorrelationInitializers of the Receive RegisterAccount Request activity as the value has not yet been determined. It can however be assigned in the related Send RegisterAccount Reply activity.

image

image

The CorrelationHandle variable must be entered on the left. When selected, there are several options available for correlation support. The option to select is Query correlation initializer. The next step is to define an XPath query to the content value in the service contract. The dialog helps out here by providing a dropdown (indicated in the screenshot). The dropdown options provide an easy way to enter the XPath Queries value based on the service contract related to the activity. In this case the RegisterAccountResult (the ChallengeCode) is selected and the XPath Query of sm:body()/xgSc:RegisterAccountResponse/xgSc:RegisterAccountResult is entered automatically.

The next step is to configure the Receive activity of the ConfirmRegistration service operation.

image

The CorrelationHandle variable is defined on the activity as indicated in the above screenshot. The CorrelatesOn property now needs to be set in order to link the ChallengeCode in the ConfirmRegistration service operation with the ChallengeCode generated by RegisterAccount. This will allow the WorkflowServiceHost to identify the correct workflow instance to load to process ConfirmRegistration.

image

The CorrelatesOn dialog provides similar assistance in defining the XPath query to match the content correlation data. In this case the service contract is seen in the drop-down list and the ConfirmRegistrationRequest.ChallengeCode value can be chosen. This results in the XPath Query of sm:body()/xgSc:ConfirmRegistration/xgSc:request/xg0:ChallengeCode. It is important to note that the CorrelationInitializers and CorrelatesOn property values between these activities define the same correlation key value.

Content correlation will now be able to load the correct workflow instance if the ConfirmRegistration service operation request contains the ChallengeCode value returned from a prior call to RegisterAccount (unless the timeout activity has fired first).

Method 2 - Content correlation based on partial service contract data

Defining content correlation on the SendReceive activities in this way restricts you to data that is common between the service contracts for both service operations. This has forced the implementation to use ChallengeCode instead of TransactionId. This is not technically a problem as both values will be unique. The TransactionId value is closer to the concepts of WF instance management and persistence than the ChallengeCode and is a little more appropriate from a design point of view. The ChallengeCode is more of a business-orientated value that has nothing to do with workflows or correlation. Some minor changes to the workflow will be able to use TransactionId rather than ChallengeCode.

The first change is to remove the CorrelationInitializers configuration in Send RegisterAccount Reply activity. Next, we need to drop on an InitializeCorrelation activity before Send RegisterAccount Reply activity. The Correlation property is assigned the CorrelationHandle variable that has been used so far.

image

The CorrelationData property is not restricted to values defined in the service contract. This allows us to define content correlation to use another variable defined in the workflow. We can now select View… and enter the TransactionId value as this is stored in a workflow variable.

image

The first thing to note here is that the same correlation key name is used. The second important thing to note is that content correlation must use a string value. The TransactionId value is a Guid so a ToString will cater for this.

The final change is to update the CorrelatesOn definition on the Receive ConfirmRegistration Request activity. This property will now reference the TransactionId of the ConfirmRegistrationRequest object rather than ChallengeCode.

image

The content correlation will still work here even though the correlation data is a string representation of the TransactionId. Presumably this is because the XPath query is run against the WCF message (as an XML structure) which will result in a string value for TransactionId. Correlation will work in the same way as when ChallengeCode was used as long as the same TransactionId value is provided to the ConfirmRegistration service operation that was generated by RegisterAccount.

In this post we have looked at two ways of getting content correlation support to link two WCF service operations in a hosted workflow service. The remaining obstacle is how to return a meaningful service fault back if the user provides an invalid TransactionId to the ConfirmRegistration operation. I hope that a viable solution will pop up in the next post.

Tags: ,

Nov 5 2010

All about certificates

Category: IT RelatedRory Primrose @ 10:51

There have been a couple of really good posts recently about SSL and certificates over on blogs.msdn.com. Check them out.

Planky - Crypto Primer: Understanding encryption, public/private key, signatures and certificates

Kaushal - SSL Certificates

Tags:

Nov 4 2010

Mixed WCF endpoint bindings for hosted workflow services

Category: .NetRory Primrose @ 10:37

I am working on a project where I have multiple hosted WF services. All the services were secured using federated security with WIF and a custom STS. This has all worked fine until I added a new service workflow that needed to be accessible by anonymous users. This is where things get a little tricky.

The WCF configuration for the hosted services looked a little like this before the anonymous service was added.

    <system.serviceModel>
        <protocolMapping>
            <add scheme="http"
                 binding="ws2007FederationHttpBinding" />
        </protocolMapping> 
        <bindings>
            <ws2007FederationHttpBinding>
                <binding>
                    <security mode="TransportWithMessageCredential">
                        <message establishSecurityContext="false">
                            <issuerMetadata address="https://localhost/JabiruSts/Service.svc/mex" />
                            <claimTypeRequirements>
                                <!--Following are the claims offered by STS 'https://localhost/JabiruSts/Service.svc'. Add or uncomment claims that you require by your application and then update the federation metadata of this application.-->
                                <add claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
                                     isOptional="true" />
                                <add claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
                                     isOptional="true" />
                            </claimTypeRequirements>
                        </message>
                    </security>
                </binding>
            </ws2007FederationHttpBinding>
        </bindings>
        <behaviors>
            <serviceBehaviors>
                <behavior>
                    <federatedServiceHostConfiguration />
                    <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                    <serviceMetadata httpGetEnabled="true" />
                    <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceCredentials>
                        <serviceCertificate findValue="DefaultApplicationCertificate"
                                            storeLocation="LocalMachine"
                                            storeName="My"
                                            x509FindType="FindBySubjectName" />
                    </serviceCredentials>
                    <errorHandler type="Neovolve.Jabiru.Server.Services.FaultHandler, Neovolve.Jabiru.Server.Services" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <extensions>
            <behaviorExtensions>
                <add name="errorHandler"
                     type="Neovolve.Toolkit.Communication.ErrorHandlerElement, Neovolve.Toolkit" />
                <add name="federatedServiceHostConfiguration"
                     type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            </behaviorExtensions>
        </extensions>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    </system.serviceModel>

The key thing to notice is that WCF4 uses default configuration values. These services use ws2007FederationHttpBinding in order to communicate with the STS but this is not the default binding for the HTTP stack. The configuration makes this work by defining the federation binding for HTTP using the protocolMapping/add element. The bindings/ws2007FederationBinding configuration does not specify a name as it represents the default configuration for that type of binding.

I attempted to modify this configuration with an explicit service configuration for my anonymous service that uses an IRegistration contract. There were a few roadblocks along the way, but here are the tips to get you across the line.

The first step is to define a configuration name against the xamlx file. This is accessed by viewing the properties of the workflow (the workflow, not any child activity).

image

This configuration name needs to match to a WCF service configuration name. This configuration can then define a different binding than the default for the HTTP stack. It can then also define the behaviour to use for that endpoint binding.

The relevant change to the above configuration is to add the following.

<services>
    <service name="Neovolve.Jabiru.Server.Services.Registration">
        <endpoint binding="basicHttpBinding"
            bindingConfiguration="SecureBasicHttpBindingConfig"
            contract="IRegistration" />
    </service>
</services>
<bindings>
    <basicHttpBinding>
        <binding name="SecureBasicHttpBindingConfig">
            <security mode="Transport"></security>
        </binding>
    </basicHttpBinding>
</bindings>

The second important step is to define the “correct” contract name. Ordinarily the contract name in WCF would be the [Namespace].[TypeName] value of the service contract. For some reason this only worked when I specified just the type name.

My hosted workflow services can now respond to a mix of endpoint bindings for the service.

Tags: , ,

Nov 3 2010

Updated CodeCampOz presentation abstract

Category: .Net | IT Related | ApplicationsRory Primrose @ 06:38

The preparations for my CodeCampOz presentation have come a long way as has my understanding of the subject matter. I have tweaked my presentation abstract as a result. The new abstract is the following:

Not a WIF of federation

The Windows Identify Foundation (WIF) provides the latest Microsoft implementation for working in the claims-based identity space. WIF has particular strengths in providing federated security for systems that target users across multiple security domains, multiple credential types and multiple credential stores.

Developers of small systems may find it difficult to understand how WIF fits into their system design. Small systems tend to have their own security store, do not cross security domains and may not even run within an Active Directory managed domain. How do developers leverage claims-based security when they do not require federated security?

This session will provide a brief introduction to claims-based security and then look at how to implement WIF in ASP.Net and WCF applications without federation dependencies. It will then extend this to include a federation capable architecture.

Tags: , ,