Zulfiqar's weblog

Architecture, security & random .Net

Archive for the ‘Federation/STS’ Category

AD RMS protection with Custom STS – Setting the scene

Posted by zamd on June 19, 2013

In a world where device are exploding, the information protection becomes even more important. AD RMS provides an on-primses and cloud platform to protect documents. Protected documents can be freely distributed and the information protection platform ensures compliance and prevents unauthorized access.

The developer story of AD RMS was significantly simplified with AD RMS SDK 2.x aka MSIPC. The original MSDRM API was an extremely complex and required specialized skills to program. Version 2.x of the SDK introduced a simple File Protection API which makes it super easy to incorporate IPC in custom solutions. The SDK comes with a native API and there is a managed sample wrapper available as well.

The on-premises AD RMS Server is implemented using a set of web services (asmx based) which provides keys, certificates & license management infrastructure required to enable information protection.

The flow starts with authenticating the user and once the user is authenticated & authorized, key distribution is kicked off to enable protection/un-protection functionality. The default deployment of AD RMS is configured to use Windows Authentication – which means consumers of the protected contents must be part of the Active Directory.

Sometime there are requirements to make protected content (protected docx) available to users who doesn’t live in your Active Directory – for example sharing the protected documents with a partner organization etc.

Another scenario is where you own the users but they are stored in custom databases (SQL membership DB etc) rather than AD & you want this user base to access protected contents using their existing credentials.

To enable such scenarios, the AD RMS supports federated authentication using the standard WS-Federation protocol. There is useful step by step guide on how to use AD FS to enable federated access with partners who doesn’t have AD RMS deployed. This guide covers the first scenario I mentioned above.

To enable 2nd scenario,  you would need to deploy a custom STS (e.g. thinktecture identity server) and integrate it with AD RMS infrastructure using standard trust management and claims transformation.

The following figure shows the message flow used to acquire a license to un-protect a protected word document.

image

In a future post, I’ll explain the details of enabling this scenario using ThinkTecture Identity Server as a custom STS.

Posted in AD RMS, Federation/STS, MSIPC | Leave a Comment »

Custom STS for Sitefinity 5.x

Posted by zamd on February 6, 2013

Sitefinity 5.x introduced claims based security & Single-Sign-On features based on a simple HTTP redirect based token issuance protocol which I’m going to call ‘Sitefinity sign-in protocol’ in my posts. Version 5.x has also standardized on using Simple Web Token (SWT) as the default token format for user authentication and SSO needs.

Sitefinity 5.x comes with a built-in local STS which authenticates users using the standard membership authentication and issue SWT tokens in accordance with Sitefinity sign-in protocol. Sitefinity doesn’t have a hard dependency on this built-in STS rather it relies on it’s sign-in protocol and SWT token format which means we can introduce a custom STS in the mix and Sitefinity would happily work with our Custom STS which obviously has to adhere to Sitfinity sign-in protocol and token format.

This STS based design in Sitefinity 5.x could enable many SSO scenarios, some of which I’m going to explore in future posts. Following are examples of few possibilities:

  • I can create a Custom STS and then have multiple applications (RPs :)) including Sitefinity 5.x trust this single STS, which would enable the users to single sign-on across all those applications.
  • I can create a multi-protocol STS which can enable user SSO across workloads/products. For example, SSO between Sitefinity & Office 365 or another portals, speaking the SAML protocol.

For now, I’ll show you how to use a custom STS with Sitefinity for user authentication. I have already developed and deployed a Sitefinity compatible STS @ http://sts.pilesoft.com while Sitefinity is running @ http://pilesoft.com.

Step 1: Register custom STS with Sitefinity so that it can trust the token issued by custom STS.

Open the .\App_Data\Sitefinity\Configuration\SecurityConfig.config file and locate the <securityTokenIssuers> element and following line to <securityTokenIssuers> element.

<add key="CD29559E6EDC312272976AC43F7E921C5766D7063DAF6D177F3EEDEB1802FABE" encoding="Hexadecimal" membershipProvider="Default" realm="http://sts.pilesoft.com"/>

Your config should now look like following:

  1. <securityTokenIssuers>
  2.   <add key="CD29559E6EDC312272976AC43F7E921C5766D7063DAF6D177F3EEDEB1802FABE" encoding="Hexadecimal" membershipProvider="Default" realm="http://sts.pilesoft.com"/>
  3.       <add key="6C4B865442D166796756C8DA1765584F7DD5EC0DE81B1CF29AC5FCE85AE5331D" encoding="Hexadecimal" membershipProvider="Default" realm="http://localhost" />
  4.   </securityTokenIssuers>

 

In most cases, you need to configure a custom Membership provider as well, which I’m going to talk in a future post.

Step 2: Open the main web.config file and locate the <federatedAuthentication> under the <microsoft.identityModel> section. This is WIF configuration and we need to change the <wsFederation> element to point to our custom STS.

Locate the <wsFederation> element & change the issuer attribute to point to our Custom STS as shown below:

<microsoft.identityModel>
  <service>
    <claimsAuthenticationManager type="Telerik.Sitefinity.Security.Claims.SFClaimsAuthenticationManager, Telerik.Sitefinity" />
    <securityTokenHandlers>
      <add type="Telerik.Sitefinity.Security.Claims.SWT.SWTSecurityTokenHandler, Telerik.Sitefinity" />
    </securityTokenHandlers>
    <audienceUris mode="Never"></audienceUris>
    <federatedAuthentication>
      
    ==>  <wsFederation passiveRedirectEnabled="true"
                       issuer="http://sts.pilesoft.com/issue/sitefinity" realm="http://localhost" requireHttps="false" />
      
      <cookieHandler requireSsl="false" />
    </federatedAuthentication>
    <issuerNameRegistry type="Telerik.Sitefinity.Security.Claims.CustomIssuerNameRegistry, Telerik.Sitefinity">
      <trustedIssuers></trustedIssuers>
    </issuerNameRegistry>
    <issuerTokenResolver type="Telerik.Sitefinity.Security.Claims.SWT.WrapIssuerTokenResolver, Telerik.Sitefinity" />
  </service>
</microsoft.identityModel>

 

Now if I browse to Sitefinity – I get:

image

When I click on ‘Login to the backend link’, I’m redirected to my Custom STS. The address bar shows the sitefinity sign-in protocol in action.

image

When I sign-in at the STS, it issues a SWT token & redirects me back to the Sitefinity app.

As this STS is trusted by Sitefinity, it happily accepts the incoming SWT token and logs me in.

image

I’ll publish the Custom STS code after removing the IP related bits. Ping me if you desperately needs it :)

Posted in Federation/STS, Sitefinity, SSO | 2 Comments »

NuGet Package to enable SWT in WIF

Posted by zamd on April 27, 2011

Just found Daniel Cazzulino@Clarius has packaged some of my work in a reusable NuGet package. Pretty cool…

image

http://nuget.org/List/Packages/netfx-Microsoft.IdentityModel.Swt

Posted in WIF | Leave a Comment »

Using Simple Web Token (SWT) with WIF

Posted by zamd on February 8, 2011

SAML 1.1/SAML 2.0 is the default token format when using ACS as the authentication service for your website. In this model, your website talks to ACS using WS-Federation protocol and what it normally gets back is a Saml token. This scenarios is fairly straight-forward as WIF natively supports WS-Federation protocol & SAML1.1/SAML 2.0 token formats.

There are cases where you might want to return a Simple Web Tokens (SWT) after a successful authentication. For example, you might want to use this same SWT (available as a bootstrap token) to call other downstream REST/OData services as depicted in the following diagram.

image

ACS fully supports returning an SWT token after a successfully WS-Fed authentication but WIF currently doesn’t support SWT tokens. You would have to write a custom Security Token Handler for WIF to process SWT tokens coming back to your website. I have created some extensions which enables this and other OAuth WRAP related scenarios. Feel free to download the code from my SkyDrive.

Posted in WIF, Windows Azure AppFabric | 13 Comments »

Silverlight Claim-Based-Security

Posted by zamd on February 8, 2011

This would hopefully be a multi-part series showing some tricks to enable claims-based-security in Silverlight 4.0. Silverlight 5.0 would have a much better story around claim-based-security as mentioned here.

In this first post, I’ll give you a high level overview of the solution. The main idea is to use the ‘WCF Routing Service’ in the DMZ to route both token issuance requests & business requests to the actual backend services.

1. Routing Service looks for a token issuing request and forwards it to the STS where the actual authentication is performed. After the successful authentication, STS issues a SAML token which goes back to Silverlight client via the routing service. Routing Service also terminates the SSL and backend is called using straight HTTP. This model offers strong security on the internet while keeping the internal deployment simpler & efficient. This model also resembles with the standard SSL offloading setup where a hardware load-balancer is used to terminate the SSL.

1: Token Issuance Path

image

2. Once the Silverlight client got a SAML token, it can attach it to all subsequent message sent to business service(s). Routing Services forwards al the business messages (messages which doesn’t match the token issuance filter) to the actual backend services again doing the protocol transitioning from HTTPS to HTTP. Please note, here you can use the rich filtering mechanism provided by the Routing services to decide which messages should to which services. I used a very simple MatchAll filter which forwards all the non-token-issuance messages to the business service.

2: Web Service Call Containing a SAML Token

image

To implement the 1st part of solution I have used the WSTrustClient class & the associated bindings from the identity training kit.

var vm = this.DataContext as MainPageViewModel;

var stsBinding = new WSTrustBindingUsernameMixed();

var stsCreds = new UsernameCredentials(vm.UserId, vm.Password);
var client = new WSTrustClient(
    stsBinding,
    new EndpointAddress(vm.SelectedEndpoint),
    stsCreds);

var rst = new RequestSecurityToken(WSTrust13Constants.KeyTypes.Bearer);
rst.AppliesTo = new EndpointAddress(vm.AppliesTo);

client.IssueCompleted += new System.EventHandler<IssueCompletedEventArgs>(client_IssueCompleted);
client.IssueAsync(rst);

For the 2nd part I have implemented a message inspector along with an extension method which makes it super easy to attach the SAML with outgoing messages.

var vm = this.DataContext as MainPageViewModel;
var client = new ServiceReference1.Service1Client();

client.AttachToken(vm.SecurityToken.RawToken);

client.GetDataCompleted += new EventHandler<ServiceReference1.GetDataCompletedEventArgs>(client_GetDataCompleted);
client.GetDataAsync(32);

Posted in Security, WCF, WIF | 11 Comments »

WIF based OAuth WRAP Issuer

Posted by zamd on August 13, 2010

WIF provides an API to develop Security Token Services (STSs) which can then be exposed using either WS-Trust (Active-STS) or WS-Federation(Passive-STS) protocols. As mentioned in last post, WIF currently doesn’t support OAuth WRAP protocol so out of box a WIF based SecurityTokenService cannot be used as an OAuth WRAP issuer. In this post, I’ll show you some extensions I have created to expose a service, based on WIF’s token issuance object model (SecurityTokenService, RequestSecurityTokenRequest etc), as an OAuth WRAP issuer.

1: Create an issuer using the standard WIF approach. The only difference is that I’m using a symmetric key for signatures.

public class OAuthIssuer : SecurityTokenService

{

    public OAuthIssuer(SecurityTokenServiceConfiguration config):base(config){}

 

    protected override IClaimsIdentity GetOutputClaimsIdentity(IClaimsPrincipal principal, RequestSecurityToken request, Scope scope)

    {

        return new ClaimsIdentity(new Claim[] {

               

            new Claim(ClaimTypes.Name, "John"),

            new Claim("email", "John@test.com") });

    }

 

    protected override Scope GetScope(IClaimsPrincipal principal,

        RequestSecurityToken request)

    {

        var scope =  new Scope

        {

            AppliesToAddress = request.AppliesTo.Uri.AbsoluteUri

        };

 

        scope.TokenEncryptionRequired = false;

        scope.SymmetricKeyEncryptionRequired = false;

        scope.SigningCredentials = new SymmetricSigningCredentials("Sapm9PPZZHlo=");

        return scope;

    }

}

2: Host the issuer using following code:

var config = new OAuthIssuerConfiguration()

{

    SecurityTokenService = typeof(OAuthIssuer)

};

config.TokenIssuerName = "MyCustomIssuer";

 

config.SecurityTokenHandlers.AddOrReplace(new CustomUserNameSecurityTokenHandler

{

    UserNamePasswordValidator = (uid, pwd) =>

    {

        Console.WriteLine(uid + " validated.");

    }

});

 

var sh = new OAuthServiceHost(config, new Uri("http://localhost:9111&quot;));

sh.Open();

That’s it, A WIF based OAuth WRAP issuer is ready.

OAuthServiceHost inherits from WCF WebServiceHost and exposes a fixed OAuth WRAP contract to the outside world.

public class OAuthServiceHost : WebServiceHost

{

    internal OAuthIssuerConfiguration Configuration { get; set; }

 

    public OAuthServiceHost(OAuthIssuerConfiguration config)

        : this(config, null) { }

 

    public OAuthServiceHost(OAuthIssuerConfiguration config, Uri baseAddress)

        : base(typeof(OAuthIssuerContract), baseAddress)

    {

        this.Configuration = config;

    }

}

The implementation of OAuth WRAP contract transforms the incoming token issuance request into WIF’s token issuance object model (RequestSecurityTokenRequest etc) and starts the token issuance pipeline. At the end of the pipeline, it packages the final set of claim in a  Simple Web Token and returns it back.

Source code

Posted in WIF | 6 Comments »

Using WIF for securing REST Service

Posted by zamd on July 31, 2010

OAuth WRAP and SWT (Simple Web Token) have emerged as a standard way for employing claim-based-security to the REST services.  Conceptually this model is very similar to the one used in SOAP world. A client goes to an issuer, authenticates itself using some token and gets back a different token (containing claims) in SWT format. 

WIF provides a rich API and object model to claim-enable your .Net applications but currently it doesn’t natively support OAuth or SWT. In this post, I’ll show how you can extend WIF to bring claim-based-security to REST services.  My goal is to implement this functionality in such a way that all the WIF goodness around claims-transformation (ClaimsAuthenticationManager), claim-based-authorization (ClaimsAuthorizationManager) etc can be used exactly the same way in the REST world.

I have achieved this by introducing an OAuth WRAP channel which sits in the WCF channel stack and perform an almost identical job to its SOAP counterpart WS-Security channel.  I have implemented the OAuth WRAP channel using the interceptor API from the REST Starter Kit.

image WebServiceHost2 host = new WebServiceHost2(typeof(TestService), new Uri(http://localhost:9090));

host.Interceptors.Add(new OAuthWrapSecurityChannel());

host.Open();

The OAuth channel takes care of extracting the token from the incoming message, running it through the validation pipeline (based on WIF SecurityTokenHandler framework), calling ClaimsAuthenticationManager, setting the WCF authorization context so that ClaimsAuthorizationManager can be called, and finally presenting the claims to the service method in the standard WIF way: Thread.CurrentPrincipal :)

Now with OAuth channel plugged in, if I call the service with a token issues by the Windows AppFabric ACS:

clip_image002

I get following output on the service side.

clip_image001

And from the service code, you would notice that standard WIF API is used to access incoming claims.

[WebGet]

string Hello()

{

    Console.WriteLine("Hello called…");

    Console.WriteLine("——————");

    var cp = Thread.CurrentPrincipal as IClaimsPrincipal;

    if (cp != null)

    {

        foreach (var id in cp.Identities)

        {

            Console.WriteLine("Authentication Type: " + id.AuthenticationType);

            Console.WriteLine("Is Authenticated: " + id.IsAuthenticated);

            Console.WriteLine("Name: " + id.Name);

            Console.WriteLine();

            Console.WriteLine("Claims…");

            foreach (var c in id.Claims)

            {

                Console.WriteLine(c.ClaimType + ": " + c.Value);

            }

        }

    }

    return "Hello, World";

}

 

WIF would be configured using exactly same configuration settings required for a SOAP service.

  1. <configuration>
  2.   <configSections>
  3.     <section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  4.   </configSections>
  5.  
  6.   <system.serviceModel>
  7.     <behaviors>
  8.       <serviceBehaviors>
  9.         <behavior>
  10.           <federatedServiceHostConfiguration />
  11.           <serviceDebug includeExceptionDetailInFaults="true" />
  12.         </behavior>
  13.       </serviceBehaviors>
  14.     </behaviors>
  15.     <extensions>
  16.       <behaviorExtensions>
  17.         <add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  18.       </behaviorExtensions>
  19.     </extensions>
  20.   </system.serviceModel>
  21.   <!–WIF configuration–>
  22.   <microsoft.identityModel>
  23.     <service>
  24.       <securityTokenHandlers>
  25.         <add type="Microsoft.IdentityModel.OAuth.SWTSecurityTokenHandler, Microsoft.IdentityModel.OAuth, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  26.       </securityTokenHandlers>
  27.       <issuerNameRegistry type="SampleService.MySimpleRegistry, SampleService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  28.       <claimsAuthorizationManager type="SampleService.MySimpleClaimsAuthorizationManager, SampleService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  29.       <audienceUris>
  30.         <add value="http://localhost/" />
  31.       </audienceUris>
  32.       <issuerTokenResolver type="SampleService.WrapIssuerTokenResolver, SampleService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  33.     </service>
  34.   </microsoft.identityModel>
  35.   <startup>
  36.     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  37.   </startup>
  38. </configuration>

 

In summary, these extensions implement OAuth WRAP protocol head for Windows Identity Foundation and re-uses all the neat WIF APIs for deriving the service behaviour. In the next post, I’ll discuss how to create a local OAuth WRAP issuer using the SecurityTokenService WIF API.

Feel free to download the source and experiment.

Posted in WCF, WIF, Windows Azure AppFabric | 6 Comments »

Integrating WIF, WF 4.0 & AppFabric: Claims-Based-Delegation

Posted by zamd on June 3, 2010

Extending upon my last post, where I have talked about basic integration, this post will go into the details of claims-based-delegation in WF 4.0 & AppFabric.

Again I’ll be using activities from the Workflow Security Pack. Let’s start with a diagram which captures the main components of solution and their interactions:

image 

  1. Unauthenticated user browse to web application protected by WIF modules.
  2. WIF redirects user to Passive STS for authentication
  3. User authenticates @ passive STS and is redirected back to the ASP.net app along with the Issued Token. WIF modules processes this token and upon successful validation of the token, user is logged into the application. I have configured SaveBootstrapTokens on this app, so the raw incoming token is preserved as part of IClaimsIdentity.
  4. Users click the “Call Service” link to invoke following client workflow. GetBootstrapToken activity reads the bootstrap token and enlist it with the SecurityTokenHandle (specified on the InitializeActAsToken activity) as an ActAs token.image
  5. InitializeSamlSecurityToken activity issues a request (RST) to acquire a SAML token from the STS using the ActAs token enlisted in step 4. InitializeSamlSecurityToken is able to see the ActAs token (enlisted by InitializeActAsToken activity)  because both of these activities share the same SecurityTokenHandle. At this stage, Web App is authenticated by STS using windows authentication while ActAs token is a Saml token (acquired using forms authentication in step 3). The final Saml token will contain claims for both immediate (web app) and original caller (authenticated user).
  6. TokenFlowScope activity along with the workflowCredentials behaviour (configured on the endpoint used by the Echo activity) enhances the WCF security pipeline to attach the Saml token (acquired in step 5) with the outgoing message. As part of it’s execution, TokenFlowScope will detect that Echo activity requires a Saml token, it will then check it’s enlisted tokens to see if it can satisfy the token requirements of the Echo activity. In this example, there is already a Saml token enlisted with the handle so TokenFlowScope simply attaches that token with the outgoing message.

I have attached complete solution with this post. I tried to keep the solution self-contained by using file-based certificates and other shortcuts so hopefully you should be able to get it working by just hitting Ctrl-F5 :)

Feel free to download and experiment and let me know your thoughts…

Posted in WF4, WFSP, WIF | 10 Comments »

Integrating WIF with WF 4.0 and AppFabric

Posted by zamd on May 18, 2010

WIF is framework to claim-enable ASP.net applications and WCF services. WF 4.0 introduced a new paradigm for developing services (known as Workflow Services), whose implementation is based on workflow. Windows Server AppFabric provides the hosting, management & monitoring capabilities for services with a primary focus on workflow services.

WIF integration with Workflow services can be seen at couple of different scopes.

1. Claims-Enabled Workflow Service

As workflow services are standard WCF services, WIF can easily be enabled at the WCF layer using the standard configuration based approach documented in MSDN. This would claims-enable your workflow services and you can use various WIF’s extensions (code-based) for claims-transformation (ClaimsAuthenticationManager) and claims-based authorization (ClaimsAuthorizationManager).

2. Workflow Services calling other Claims-Enabled Services

WF 4.0 provides messaging activities to call other services from workflows. In most cases, Claims-Enabled services require a token from an STS. In a non-WF world, you can either use wsFederationHttpBinding or the new fine grained WIF API (WSTrustChannelFactory) to do this (you can use IssuedSecurityTokenProvider directly). The wsFederationHttpBinding approach kind of works (transparently) in Workflow services world as well but could be quite expensive in terms of performance. See my post on messaging activities for additional details. The wsFederationHttpBinding approach is also not suitable for scenarios, where you need fine-grained control of issued tokens or you want to use issued token in long-running scenarios without re-acquiring them.

3. WIF in middle-tier Workflow Services

WIF enables claims-based-delegation using then ActAs/OnBehalfOf element of WS-Trust protocol. In code-based services, you can access the incoming token in the middle-tier service and then use this when acquiring a SAML token to call a backend service. With this model, the backend service can see all the identities involved in the call chain. Claims-based delegation is not easily possible in workflow services when using wsFederationHttpBinding.

1 & 2 be greatly enhanced by introducing custom activities which can decouple token acquisition from its use; much like activity counterpart of WIF’s WSTrustChannelFactory API.

saml

In above diagram InitializeSamlSecurityToken custom activity encapsulate the functionality of acquiring a token from a STS using the WS-Trust protocol. Internally it uses the standard correlated Request-Reply pair configured for WS-Trust contract. I’ll talk more about TokenFlowScope in a future post but here it enables the Ping activity to use the acquired token when calling a service which requires Saml token. I have attached complete solution with post (STS, Test Service & a Test Client)which also includes alpha drop of WFSP binaries as well. Feel free to download and experiment and let me know your thoughts.

Posted in WF4, WFSP, WIF | 9 Comments »

Configuring SAML Assertion Subject Name and Format for a WIF STS

Posted by zamd on April 27, 2010

In some interop scenarios, subject name and its format needs to be included in the Saml token/assertion generated by the STS. You can easily configure a WIF based STS to generate this by adding a NameIdentifier claim and by settings it’s format property.

protected override IClaimsIdentity GetOutputClaimsIdentity(IClaimsPrincipal principal,

    RequestSecurityToken request, Scope scope)

{

    var nameIdentifierClaim = new Claim(ClaimTypes.NameIdentifier, "me@zamd.com");

    nameIdentifierClaim.Properties[ClaimProperties.SamlNameIdentifierFormat] = "EMAIL";

 

    return new ClaimsIdentity(

        new Claim[]

        {

            new Claim(System.IdentityModel.Claims.ClaimTypes.Name, "Zulfiqar"),

            nameIdentifierClaim

        });

 

This generates following Saml Assertion where you can see the generated NameIdentifier & format attribute.

 <saml:AttributeStatement xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
   <saml:Subject>
    <saml:NameIdentifier Format="EMAIL">me@zamd.com</saml:NameIdentifier>
     <saml:SubjectConfirmation>
      <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
    </saml:SubjectConfirmation>
  </saml:Subject>
   <saml:Attribute AttributeName="name" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
    <saml:AttributeValue>Zulfiqar</saml:AttributeValue>
  </saml:Attribute>
</saml:AttributeStatement>

Posted in WIF | 1 Comment »

 
Follow

Get every new post delivered to your Inbox.