Authorization Sample 303 – Metadata-Aware Authorization

In Authorization Sample 301 I explained the ins-and-outs of the authorization sample and offered a few hints as to how it could be used. In this post, I will show a specific example where I put together an authorized form that responds to metadata on the object.

image

I started with a simple type with AuthorizationAttributes applied to a couple properties. In this sample, I only wanted the user to see controls for properties they were authorized to see.

   public class Model
  {
    public int Id { get; set; }

    [RequiresRole("member")]
    public ModelValue Value { get; set; }

    [RequiresRole("administrator")]
    public string Text { get; set; }
  }

It wasn’t instantly obvious how to tie the metadata to UI components. If I were using the DataForm in the Silverlight Toolkit, I would choose to tie into the AutoGeneratingField event and apply the AuthorizationRules there. Another good option would have been to put the corresponding property name in an attached property. However, for this sample, I took a simpler approach and just put the name in the Tag for each control.

   <!-- Value -->
  <TextBlock Grid.Row="1" Grid.Column="0"
             Style="{StaticResource FormLabelStyle}"
             Text="Value" Tag="Value" />
  <ComboBox Name="ValueComboBox" Grid.Row="1" Grid.Column="1"
            Style="{StaticResource FormFieldStyle}"
            SelectedValue="{Binding Value, Mode=TwoWay}" Tag="Value" />

My next step was to create an AuthorizationRule to process the metadata based on the target’s Tag.

   public class MetadataAuthorizationRule : AuthorizationRule
  {
    public override IEnumerable<AuthorizationAttribute>
                      GetAuthorizationAttributes(object target)
    {
      List<AuthorizationAttribute> attributes =
                                     new List<AuthorizationAttribute>();

      FrameworkElement targetFe = target as FrameworkElement;
      if (targetFe != null)
      {
        Type modelType = targetFe.DataContext.GetType();
        string tag = targetFe.Tag as string;

        if (tag != null)
        {
          PropertyInfo info = modelType.GetProperty(tag);
          if (info != null)
          {
            object[] customAttributes = info.GetCustomAttributes(false);
            attributes.AddRange(
                         customAttributes.OfType<AuthorizationAttribute>());
          }
        }
      }

      return attributes;
    }
  }

Finally, I’ve applied the rule to each control in the form.

   MetadataAuthorizationRule metadataRule = new MetadataAuthorizationRule();
  foreach (UIElement child in this.LayoutRoot.Children)
  {
    Authorization.Authorize(child, metadataRule);
  }

I’ve included the source for the sample here.

There are plenty of interesting scenarios for using metadata. Like ValidationAttributes and DisplayAttributes, AuthorizationAttributes could regularly be included in the model to indicate read access, write access, or any other special access rules that apply to an application.