WCF Services with Claims-based Authentication and Authorization





0/5 (0 vote)
Sample service based on WCF (Windows Communication Foundation)
In the previous article, I’ve presented information about Security Token Service (STS). We know how to build sample Active STS and Relying Party Application. In this article, we focus on sample service based on WCF (Windows Communication Foundation), as we will only try to build sample service with claims-based authentication and authorization. All technical aspects connected with security, e.g., configuration, certificates, encryption, signature or CRL will be described in detail in the next posts.
WCF “ABC”
Windows Communication Foundation (WCF) is a Microsoft framework for building service-oriented applications. “ABC
" is the WCF mantra. "ABC
" is the key to understanding how a WCF service endpoint is composed.
- The Address specifies where the service is residing.
- The Binding is how the service is to be used. The Binding specifies (protocol to use, encoding to use, type of security requirements to be used, such as SSL or SOAP message security)
- The Contract identifies operations exposed by the service.
WCF and WIF
WCF provides easy integration with WIF, which allows to use WIF’s features, such as the new claims model, support for additional security token types and token handling in WCF services. For integration with WIF, WCF offers dedicated binding WS2007FederationHttpBinding.
How to Build WCF Service with Claims-based Authentication and Authorization
In this article, we try to build WCF with claims-based authentication and authorization mechanism. Thanks to the previous article, we know how to build Active STS and Relying Party application (Figure 2 steps 1-3). Now, we’ll try to accomplish the scenario, which is presented in the following diagram (Figure2 steps 4-6).
- The client sends a request message to the service (via application). The request message contains received token.
- The service validates the security token and processes the request. To validate a token connection between service and STS is not necessary – issuer validation is based on PKI (this mechanism will be further described in another article)
- (Optional) The service initializes and sends a response message to the client.
At first, we build and host WCF (with WS2007FederationHttpBinding) service projects (in this article, we won’t focus on implementation of WCF services, we assume that we know how to build and run sample WCF service with httpsBinding
). We prepare sample WCF services (SampleServiceOne
and SampleServiceTwo
) that will be hosted on IIS. The Relying Party application (a WinForm application), which will be a WCF services client, will use a token received from STS to authenticate and authorize. Both services SampleServiceOne
and SampleServiceTwo
provide the same functionalities (return information about claim identity) and use tokens issued by “trusted” STS.
var claimsPrincipal = OperationContext.Current.ClaimsPrincipal;
var identity = claimsPrincipal.Identity as ClaimsIdentity;
The SampleServiceOne
is based on AspNetCompatibilityRequirements to verify client permissions, the SampleServiceTwo
explicitly verifies client permissions. When AspNetCompatibility
mode is enabled in WCF services, we can use the PrincipalPermissionAttribute
(SampleServiceOne
uses this functionality) to verify client’s identity (authenticate and authorize).
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class SampleServiceOne : SampleService, ISampleServiceOne
{
public SampleServiceOne()
{
ServiceName = "Service One";
}
[PrincipalPermission(SecurityAction.Demand, Role = "User", Authenticated = true)]
public string ComputeResponse(string input)
{
return GenerateResponse(input);
}
[PrincipalPermission(SecurityAction.Demand, Role = "Admin", Authenticated = true)]
public string ComputeResponseAdmin(string input)
{
return GenerateResponse(input);
}
[PrincipalPermission(SecurityAction.Demand, Role = "SuperAdmin", Authenticated = true)]
public string ComputeResponseSuperAdmin(string input)
{
return GenerateResponse(input);
}
}
The SampleServiceTwo
explicitly verifies user credentials (authenticate and authorize users).
public class SampleServiceTwo : SampleService, ISampleServiceTwo
{
public SampleServiceTwo()
{
ServiceName = "Service Two";
}
public string ComputeResponse(string input)
{
VerifyUserPermissions("User");
return GenerateResponse(input);
}
public string ComputeResponseAdmin(string input)
{
VerifyUserPermissions("Admin");
return GenerateResponse(input);
}
public string ComputeResponseSuperAdmin(string input)
{
VerifyUserPermissions("SuperAdmin");
return GenerateResponse(input);
}
private void VerifyUserPermissions(string role)
{
var claimsPrincipal = OperationContext.Current.ClaimsPrincipal;
if (!claimsPrincipal.Identity.IsAuthenticated || !claimsPrincipal.IsInRole(role))
{
throw new FaultException("Access denied.");
}
}
}
To run WCF services with WS2007FederationHttpBinding
, we have to prepare service configuration. The configuration may look like “in Listing 4 and Listing 5” (all configurations of technical aspects connected with security will be described in the next post).
<ws2007federationhttpbinding>
<binding name="">
<security mode="TransportWithMessageCredential">
<message algorithmsuite="Default"
establishsecuritycontext="false" issuedkeytype="BearerKey">
</message></security>
</binding>
<binding name="WS2007FederationHttpBinding_ISampleServiceTwo">
<security mode="TransportWithMessageCredential">
<message establishsecuritycontext="false" issuedkeytype="BearerKey">
<tokenrequestparameters>
<trust:secondaryparameters
xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<trust:keytype xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:keytype>
<trust:canonicalizationalgorithm
xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
http://www.w3.org/2001/10/xml-exc-c14n#</trust:canonicalizationalgorithm>
<trust:encryptionalgorithm
xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:encryptionalgorithm>
</trust:secondaryparameters>
</tokenrequestparameters>
</message>
</security>
</binding>
</ws2007federationhttpbinding>
<behavior>
<servicemetadata httpgetenabled="true">
<servicedebug includeexceptiondetailinfaults="true">
<serviceauthorization principalpermissionmode="Always">
<servicecredentials useidentityconfiguration="true">
<clientcertificate>
<authentication certificatevalidationmode="None" revocationmode="NoCheck">
</authentication></clientcertificate>
</servicecredentials>
</serviceauthorization></servicedebug></servicemetadata></behavior>
STS - Relying Party Application – WCF Communication
A Relying Party is an application or service that relies on claims for authentication. In our example, RP application is a simple Win Form application. The application sends an issue request to STS and receives Security Token, which is used to authenticate and authorize a user. The issued token is also used to authenticate and authorize client in WCF services. To run WCF method (with WS2007FederationHttpBinding
), first, we have to open communication channel using security token. In our example, we’ve created a sample service factory, which will create proxy to WCF service.
public class ServiceApiFactory : IDisposable
{
private readonly List<icommunicationobject> _activeServices;
private readonly SecurityToken _authToken;
public ServiceApiFactory(SecurityToken token)
{
_activeServices = new List<icommunicationobject>();
_authToken = token;
}
public void Dispose()
{
foreach (var service in _activeServices)
{
try
{
service.Close();
}
catch (CommunicationObjectFaultedException)
{
service.Abort();
}
catch (TimeoutException)
{
service.Abort();
}
}
}
public T GetService<t>(string endpointConfigurationName)
{
var factory = new ChannelFactory<t>(endpointConfigurationName);
_activeServices.Add(factory);
return factory.CreateChannelWithIssuedToken(_authToken);
}
}
The ServiceApiFactory
requires issued SecurityToken
; then it returns proxy to WCF service (with specified WCF service endpoint configuration).
using (var serviceApi = new ServiceApiFactory(_authController.GeToken()))
{
var client = serviceApi.GetService<isampleserviceone>("WS2007FederationHttpBinding_ISampleServiceOne");
//...
}
How to Run and Test a Sample Solution
To run the sample STS-RP-WCF implementation, we should execute the following steps:
- Get sample source code from Git repository (source code)
- Build STS.sln solution
- Host
SampleServiceOne
andSampleServiceTwo
project on IIS (use https) - Run Relying Party Application
- Login to STS using a user’s name/password credential (the current STS uses authentication mechanism, which verifies if user’s name corresponds to password, e.g., user’s name: user, password: user. If a user’s name is
Admin
, user is assigned to theUser
andAdmin
roles; if a user’s name isSuperAdmin
, user is assigned to theUser
,Admin
andSuperAdmin
roles.
- Login to STS using a user’s name/password credential (the current STS uses authentication mechanism, which verifies if user’s name corresponds to password, e.g., user’s name: user, password: user. If a user’s name is
- As a user in the role of
User
orAdmin
, “Call Service 1” and “Call Service 2”:Figure 3. ServiceOne Call - Admin roleFigure 4. ServiceTwo Call - Admin role- “Call Service 1” (and “Call Service 2”) runs (sequentially) three methods:
ComputeResponse
– requires client inUser
’s roleComputeResponseAdmin
- requires client inAdmin
’s roleComputeResponseSuperAdmin
- requires client inSuperAdmin
’s role
- Analyse execution results (the following figures show sample execution results)
- To verify that security token is issued by trusted STS, remove or comment Issuer thumbprint from
SampleServiceTwo
(orSampleServiceOne
) configuration file and make call to service once again.
- “Call Service 1” (and “Call Service 2”) runs (sequentially) three methods:
<trustedissuers>
<!-- Issuer thumbprint. -->
<!--
<add name="Localhost" thumbprint="5DA000A8A9AE99E5269F283C72911F5D8BE2D6D1">
-->
</add></trustedissuers>
Summary
This article explored the technical approach to authentication and authorization process based on claims in WCF services via STS. We have implemented working exemplary solution, which demonstrates how integration between WCF and WIF works. The next article will describe security aspects of authentication and authorization mechanism based on claims. We’ll try to explain Public Key Infrastructure roles in WIF.