How to authorize a WCF service in the anonymous internet

Sometimes I feel like in the time of exploration where I’m a discoverer … But than I always realize that I’m only a developer who tries to understand the mysteries of the Microsoft Framework …

Introduction:
I had to program an authorization mechanism between a client application and a webservice that is hosted by a internet provider. In such a case, we have two different domains in place, no windows integrated authentication, no certificate or something else. The old fashioned way in that case is to use a SoapHeader in order to send informations about the user to the web service … That’s the point where the trail starts …

SoapHeader in WCF Services:
The new Microsoft Technology is not in love with SoapHeaders. Actually it does not know them. But fortunately there is a project on CodePlex called “WCFExtras” which re-implemented the [SoapHeader] Attribute for WCF. So I created an Authentication class in the following way.

[DataContract(Name="AuthenticationHeader")]
public class AuthenticationHeader
{
    [DataMember]
    public string TpUser { get; set; }
    [DataMember]
    public string TpPwdMd5 { get; set; }
    
    [DataMember]
    public string Culture { get; set; }
}

.. And tagged my methods within the [ServiceContract] with the new [SoapHeader] attribute.

[OperationContract]
[SoapHeader("Authentication", typeof(AuthenticationHeader))]
UserStub CreateUser(string logonName);

In order to use the [SoapHeader] attribute, I had to references the WCFExtras.dll in my project and within my web.config file in the behaviorExtensions.

<behaviors>
<endpointBehaviors>
<behavior name="UserServiceEndpointBehaviors">
<wsdlExtensions/>
</behavior>
</endpointBehaviors>
</behaviors>

<extensions>
<behaviorExtensions>
<!– Declare that we have an extension called WSDL Extras–>
<add name="wsdlExtensions" type="WCFExtras.Wsdl.WsdlExtensionsConfig, WCFExtras, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null;/>
</behaviorExtensions>
</extensions>

At server side everything had been fine now.

How to add the SoapHeader at the client side:
But on the client side, I had to send the SoapHeader over the wire whenever a method will be called. For that you have to know, that a SoapHeader is bound to the EndpointAddress of the WCF Service. The binding on the EndpointAddress can be done when creating the WebService via the ChannelFactory.

var authentication = new Dao.Core.TpAuthentication
{
    TpUser = connection.UserName,
    TpPwdMd5 = Md5Crypt.ComputeHash(connection.UserPassword),
    Culture = Thread.CurrentThread.CurrentUICulture.Name
};

var authenticationHeader = AddressHeader.CreateAddressHeader("Authentication", "", authentication);
var serviceUri = new Uri("http://localhost:81/tphost/UserService.svc"));

var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
var endpointAddress = new EndpointAddress(serviceUri, new [] { authenticationHeader});
wst = new ChannelFactory<WebServiceTemplate>(basicHttpBinding, endpointAddress).CreateChannel();

At this point in the service host I was able to read user information which have been sent, by the client using the SoapHeader.

But how could I manage the Authentication in my service host?
It was my goal to use declarative and imperative authentication by using the Thread.CurrentPrincipal.IsInRole functionality. In order to use this functionality I had to create my own implementation of IPrincipal and IIdentity. I assume that you know how to implement this interfaces, because the implementation is mainly driven by your business logic. That’s why I jump directly to the interessting part, the AuthorizationPolicy. At server side I had to create a new class that inherits the IAuthorizationPolicy interface.

public class AuthorisationPolicy : IAuthorizationPolicy
{
    string id = Guid.NewGuid().ToString();
    
    public string Id
    {
        get { return id; }
    }
    
    public ClaimSet Issuer
    {
        get { return ClaimSet.System; }
    }
    
    public bool Evaluate(EvaluationContext context, ref object state)
    {
        // Extract the authentication
        var authentication = SoapHeaderHelper<Authentication>.GetInputHeader("Authentication");
        
        …
        
        context.Properties["Principal"] = new CustomPrincipal(webServiceUser, new CustomIdentity(webServiceUser));
        
        return true;
    }
}

The interface has only three methods. The property Id is only a unique identifier of your AuthorizationPolicy – so I did not care about. The Claimset Issuer is only used to define, if the System claims the authorization, or if Windows itself claims it. In my case – it’s always the System. The real magic is implemented within the Evalute method.

The first method reads the SoapHeader that contains the user information.

var authentication = SoapHeaderHelper<Authentication>.GetInputHeader("Authentication");

With this information I had been be able to authenticate the user. If the authentication fails, the method must return false. If not, a new Principal must be set into the context.Properties["Principal"]. The key “Principal” is pre-defined by Microsoft and the new content will instantly placed into the Thread.CurrentPrincipal.

So, that’s the magic.

But who calls the AuthorizationPolicy?

In order to make the new AuthorizationPolicy available to the WCF Framework, I had to to publish it in my [ServiceBehaviors] within the web.config file.

<serviceBehaviors>
<behavior name="UserServiceBehaviors" >
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="WebServices.Core.AuthorisationPolicy, WebServices, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</authorizationPolicies>
</serviceAuthorization>
</behavior>
</serviceBehaviors>

So, that’s it. Knowing this, you are also able to write your own authorization process, in case you need it.

So enjoy this piece of code
- Gerhard

kick it on DotNetKicks.com

You can only add project references to other Silverlight projects in the solution.

If you start with silverlight, I bet with you that you’ll get that anoying message in any case. But it has a reason why Microsoft doesn’t allow that.

It’s because Silverlight owns a very tiny implementation of the .NET framework in order to reduce the download size for the user. So it’s very likely that your project uses a method which is not supported by the .NET silverlight framework. But how can we get arround this irritating message? The question is easy, but although I’m working day by day with Visual Studio, I did not recognize the functionality until Davit Betz showed me that egg of Columbus.

First of all you have to create a silverlight project. In my case I named it like the project I wanted to use and added a “.Silverlight” at the end of the project name. (e.g. Utils.Silverlight). After that you create the folders as in your original project.

And now the magic: Add the files by clicking to “Add existing item” and use “Add Link” (instead of simply Add).
AddLink

As a result the files will only be referenced by the new project, but not copied into the folder physically. With that feature, you can build your silverlight assembly without duplicating the sources. And I think you’ll wonder how many changes you need …

So remember, with every change here – you’ll probably break your original assembly there. In order to prevent breaking the code, you can use the precompiler. In every Silverlight Assembly the SILVERLIGHT Symbol is predefined.

So use, #if SILVERLIGHT … #endif to encapsulate the code that is only interessting for your silverlight application.

May the code be with you
- Gerhard

kick it on DotNetKicks.com

How to manage Control States in Silverlight Applications

In 2006 I developed a small piece of code in order to use a declarative control state handling in WinForm Applications. Three years later (2009) I thought declarative control state handling should be standard in Silverlight – but I failed. So I decided to migrate that piece of code to the new Silverlight plattform.

Imagine you have a really big application – How would you ensure the control state of every control? In former times this had been done in endless “if – then – else” horror code blocks. That time is history now. A better solution is to use a configuration file and define rules to enable/disable and visible/collapse controls.

Before you read: Here’s an example application.

Here’s the configuration file for the example:

<?xml version="1.0" encoding="utf-8"?>
<uipConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<StateSections>

<section name="Page">
<Elements>
<add key="txtAlwaysVisible" state="True"/>
<add key="txtVisibleHidden" check="IsVisible" changeVisibility="true"/>
<add key="radEnabled" check="IsRadioButtonEnabled" />
<add key="radAdmin" roles="Admin" />
<add key="radEditor" roles="Editor" />
<add key="radBoth" roles="Admin, Editor" />
</Elements>
</section>

</StateSections>
</uipConfig>

As you can see the uipConfig file is devided in Sections. A Section is a logical component that contains controls. In our example the Section is defined as the Silverlight Page. In the every section all controls that are interessting for us have a key that is used to define the rules.

Here are the allowed attributes:

Attribute Description
state Can be set to true / false or can be left empty. If a state has been set, all other checks will be ignored.
roles It’s a comma separated list with roles, the current principal must belong to. If the current principal does not belong to the role, the control will be disabled.
check It’s a comma separated list with check routines that tells the State Manager if the control has to be disabled or enabled. Such a check routine can be implemented in a controller class or within the Page itself – and it’s more or less a property that returns true or false.
changeVisibility This flag defines, if the visibility of the control shall be changed. If this flag has not been defined, the enabled/disabled state is used.

All you have to do is to make the ControlStateExtender available to your silverlight application. Therefore you have to place the reference in your UserControl element of your page.

<UserControl x:Class="SilverlightControlState.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:state="clr-namespace:SilverlightControlState.ControlState;assembly=SilverlightControlState"

After that you can add the attribute sate:ControlStateExtender.ControlKey to any of your controls.

Example:

<TextBlock state:ControlStateExtender.ControlKey="Page, txtVisibleHidden"
</TextBlock>

The first word defines the section, the second the key of the control within the section. Now – what do you have to change in code?

That’s pretty easy and also straight forward. You have to add a private readonly ControlStateExtender to your page. This object handles the state of your controls. Furthermore you have to initialize the ControlStateExtender object after the call of InitializeComponent().

public partial class Page : UserControl
{
    private readonly ControlStateExtender cse = ControlStateExtender.GetExtender("Page");
    
    /// <summary> Constructor </summary>
    public Page()
    {
        InitializeComponent();
        cse.Initialize(this);
    }

Now you can define the control state rules in your application.
Example:

#region Control State Rules

public bool IsVisible
{
    get
    {
        return radVisible.IsChecked.Value;
    }
}

private bool disableRadioButtons = false;
public bool IsRadioButtonEnabled
{
    get
    {
        return !disableRadioButtons;
    }
}

#endregion

The control state rules (business rules) will be invoked by the ControlStateManager when the Refresh() method is called. So, any time, you expect the control states to be changed you have to call the Refresh() method of the ControlStateManager to re-validate the rules.

Example:

#region Handler that refrehes the control state

private void OnRadChecked(object sender, RoutedEventArgs e)
{
    cse.Refresh();
}

private void OnEnableDisableClick(object sender, RoutedEventArgs e)
{
    disableRadioButtons = !disableRadioButtons;
    cse.Refresh();
}

private void SetAsEditor(object sender, RoutedEventArgs e)
{
    CurrentPrincipal.Principal = new MyEditorPrincipal();
    cse.Refresh();
}

private void SetAsAdmin(object sender, RoutedEventArgs e)
{
    CurrentPrincipal.Principal = new MyAdminPrincipal();
    cse.Refresh();
}

#endregion

If you write your own application, don’t forget to embedd the uiStates.config in your silverlight application. To to this, set the Build Acction to “Embedded Resource” for the uiStates.config.
uiStates

Last but not least I want to say thanks for the ReaderWriterLock Re-Implementation of Vance Morrison. As an additional goodie the code uses a Cache Implementation to store the method, properties and config sections. This Cache Implementation is not dependend on the ControlStateExtender and can be used everywhere in your application.

Here’s the complete source code of the ControlStateExtender example application.

Hope you enjoy it.
Cheers

- Gerhard

kick it on DotNetKicks.com

How to localize Silverlight Applications the smart way

Introduction:
A very common task when developing business applications is to localize them for english, german and other languages. The most common approach is to use ResX files in order to create resource classes which can be used to bind the silverlight controls to. This approach is perfectly described by Sly (that is his nickname). Due to a bug in the resource generator from Microsoft, you always have to change the created resource class from internal to public (look at point 17 on his blog entry), which is very annoying … That’s why I was searching for a better solution to localize silverlight applications – and I think I found a really smart way to do that task.

Silverlight Localization (the smart way):
Step1:
ResourceFilesFirst of all you need a silverlight application;) If you already have one – fine. If not, create a new example application. After that you have to add a new resource file. First of all, add a fallback resource file which can be used as an alternativ, if the string can’t be found in one of the language dependend resource files. After that add a resource file for every language you want to add (and call it like the neutral resource file with the postfix of your designated language).

Step2:
Because we go the smart way, it’s important to disable the code generation. In order to do that, open the neutral resource file with a double click in Visual Studio and switch the Access Modifier to “No code generation”.
AccessModifier

Step3:
Now add some string resources to the resources files …

Step4:
Microsoft does not really very much to support the localization task, because by default, the resource files won’t be included in the created XAP file. To include the language depended resources into the XAP file, you have to open the project file (.csproj) in your favored text editor (e.g. Notepad++) and add the languages comma separated to the <SupportedCultures> Tag.

<SupportedCultures>de,en</SupportedCultures>

Step5: (We get it soon)
Now we can implement a new class that reads the resources and returns the localized strings.

public class ApplicationResources : IValueConverter
{
    /// <summary>
    /// The Resource Manager loads the resources out of the executing assembly (and the XAP File where there are embedded)
    /// </summary>
    private static readonly ResourceManager resourceManager =
    new ResourceManager("SilverlightLocalization.Resources.Strings",
    Assembly.GetExecutingAssembly());
    
    /// <summary>
    /// Use this property to specify the culture
    /// </summary>
    private static CultureInfo uiCulture = Thread.CurrentThread.CurrentUICulture;
    public static CultureInfo UiCulture
    {
        get { return uiCulture; }
        set { uiCulture = value; }
    }
    
    /// <summary>
    /// This method returns the localized string of the given resource.
    /// </summary>
    public string Get(string resource)
    {
        return resourceManager.GetString(resource, UiCulture);
    }
    
    #region IValueConverter Members
    
    /// <summary>
    /// This method is used to bind the silverlight component to the resource.
    /// </summary>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var reader = (ApplicationResources)value;
        return reader.Get((string)parameter);
    }
    
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // ConvertBack is not used, because the Localization is only a One Way binding
        throw new NotImplementedException();
    }
    
    #endregion
}

Step6:
Now we have to publish the ApplicationResources class as a Application Resource in order to use it for our binding. To to this, open the App.xaml and extend the Application.Resources.

<Application.Resources>
<SilverlightLocalization:ApplicationResources x:Key="Localization"/>
</Application.Resources>

Step7 (last step):
Yeahh – we can bind the silverlight components now. Therefore replace the content of the Text attribute of the component to localize with the following generic replacement: {Binding ConverterParameter=Page_label01, Converter={StaticResource Localization}, Source={StaticResource Localization}}

e.g. “Page_label01″ is the name of the label specified for that component within the resource file.

The complete example could look like this:

<TextBlock
FontSize="32"
TextAlignment="Center"
Margin = "0,200,0,0"
Text="{Binding ConverterParameter=Page_label01, Converter={StaticResource Localization}, Source={StaticResource Localization}}"
MouseLeftButtonUp="OnClick"
/>

Advantages of this solution:
First of all, I think this solution is very smart, because you don’t need to update the class modifier from internal to public, everytime you change the resource strings.
A second advantage is, that the XAP file is not as big, as if you would use code generation. Why? Because you simply don’t have to create tons of resource access properties. Every resource is loaded within the ApplicationResource class.

Example:
With the following link you can try a working example: Click me Example Application
And here’s the example source code to download: Smart Silverlight Localization (You have to set SilverlightLocalizationTestPage.aspx as the Start Page)

Hope you enjoy this solution.
Cheers
- Gerhard

kick it on DotNetKicks.com

Posted in .NET, C#. Tags: . 8 Comments »