Click here to Skip to main content
13,456,463 members
Click here to Skip to main content
Add your own
alternative version


78 bookmarked
Posted 4 Mar 2009

Custom Authorization in WCF

, 4 Mar 2009
Rate this:
Please Sign up or sign in to vote.
This article will show you how to implement custom authentication


Windows Communication Foundation (WCF) provides powerful facilities for implementing authorization in services.

This article will show you how to implement custom authentication. Only user with ADMIN role can call the Login() method.

Note: This article only focuses on checking role of user. You can modify this code for checking username, password and role of user by reading from database.


Create Custom Principal

It is to supply your custom IPrincipal implementation to WCF. This gives you the chance to implicitly run code after the authentication stage of each request. For this, you have to create your own custom principal and return it to the WCF plumbing. The custom principal will then be available from Thread.Cur­rentPrincipal to the service code. Custom principals allow full customization of role-based security and expose specialized security logic for the service developer to use.

Writing a custom principal is straightforward. Simply implement the IPrincipal interface and add your own custom functionality. To integrate the principal with WCF, you have to set the Principal­Per­missionMode attribute in the ServiceAuthorization element to "custom" and provide an authorization policy that is responsible for creating the principal and giving it back to WCF. 

An IPrincipal-derived class must implement a single method called IsInRole where you can pass in a role name and get a Boolean response. In addition, the principal has a reference to the identity class it wraps. 

class CustomPrincipal : IPrincipal
public bool IsInRole(string role)

        return _roles.Contains(role);

    // read Role of user from database
    protected virtual void EnsureRoles()
        if (_identity.Name == "AnhDV")
            _roles = new string[1] { "ADMIN" };
            _roles = new string[1] { "USER" };

Create Custom Authorization Policy 

An authorization policy is simply a class that implements the System.IdentityModel.Policy.IAuthorizationPolicy interface. Implementations of this interface must employ a method called Evaluate, which gets called on every request. Here you can reach into the WCF service security context and set the custom principal. The code below shows a custom principal as well as the authorization policy and its corresponding configuration entries.

The important part of AuthorizationPolicy:IAuthorizationPolicy is the Evaluate() method which, using the context of the claim evaluation, trys to get the PrimaryIdentity. This property represents the identity discovered by WCF during user credentials validation. The method then converts this to an CustomPrincipal and attaches it to the current context thus making the principal available on the current running thread. 

class AuthorizationPolicy : IAuthorizationPolicy
    Guid _id = Guid.NewGuid();

    // this method gets called after the authentication stage
    public bool Evaluate(EvaluationContext evaluationContext, ref object state)
        // get the authenticated client identity
        IIdentity client = GetClientIdentity(evaluationContext);

        // set the custom principal
        evaluationContext.Properties["Principal"] = new CustomPrincipal(client);

        return true;

    private IIdentity GetClientIdentity(EvaluationContext evaluationContext)
        object obj;
        if (!evaluationContext.Properties.TryGetValue("Identities", out obj))
            throw new Exception("No Identity found");

        IList<IIdentity> identities = obj as IList<IIdentity>;
        if (identities == null || identities.Count <= 0)
            throw new Exception("No Identity found");

        return identities[0];
 <serviceAuthorization principalPermissionMode="Custom">
   <add policyType="WikiService.AuthorizationPolicy, App_Code/WikiSecurity" />

Create Custom Validator

If left to itself, the service will now try and authenticate the supplied credentials against Windows user accounts and, as we are using our own custom authentication, this will fail!

The password stuff lives in the following override, I call my security module to check the user and password against the db:

public class CustomValidator : UserNamePasswordValidator
    public override void Validate(string userName, string password)
        // validate arguments
        if (string.IsNullOrEmpty(userName))
            throw new ArgumentNullException("userName");
        if (string.IsNullOrEmpty(password))
            throw new ArgumentNullException("password");

        // check the user credentials from database
        //int userid = 0;
        //CheckUserNameAndPassword(userName, password, out userid);
        //if (0 == userid)
        //throw new SecurityTokenException("Unknown username or password");

We indicate to the service that we want our own class, 'CustomValidator' which lives in the assembly 'WikiSecurity', to do the password stuff using this config:   

<userNameAuthentication userNamePasswordValidationMode="Custom"

   customUserNamePasswordValidatorType="CustomValidator, App_Code/WikiSecurity" />  

Create Certificate 

You are able to send your username and password over the wire if you use the following config. 

NOTE: You will need to create and install a suitable certificate on the server side to support this, another story... 

<security mode="Message">
<message clientCredentialType="UserName"/>

You must open \Certificate Setup Application\Certificate Setup\Source Code\Certificate Setup.sln and run it to create your temp certificate example:

And modify your config: 

<serviceCertificate findValue="" 

	x509FindType="FindBySubjectName" />

Your Service Code: Example WikiSecurity Class

Only user with ADMIN role can call the Login() method of the WikiSecurity service: 

[PrincipalPermission(SecurityAction.Demand, Role = "ADMIN")]
public void Login()



The username and password can then be set on your client proxy something like:

var factory = new ChannelFactory<IWikiSecurity>("*");
factory.Credentials.UserName.UserName = "AnhDV";//Do Viet Anh
factory.Credentials.UserName.Password = "anhdv";
var wikiProxy = factory.CreateChannel();

var factory = new ChannelFactory<IWikiSecurity>("*");
factory.Credentials.UserName.UserName = "AnhDV1";//Do Viet Anh 1
factory.Credentials.UserName.Password = "anhdv";
var wikiProxy = factory.CreateChannel();
wikiProxy.Login();//Access Denied

Hope this helps.

Enjoy and have fun.


  • 4th March, 2009: Initial post


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer (Senior) FPT Software JSC & VietSoftware International
Vietnam Vietnam
Programming is my hobby!
Vietanh154, or
Manager for Concat Group: http://nhó
Project Manager & Technical Leader for FPT Software JSC
Solution Architect & Technical Manager for VietSoftware International

Microsoft Certified Application Developer For Microsoft .NET
Microsoft Certified Professional MCP 2.0 -- Certified Professional
Developing and Implementing Web Applications with Microsoft® Visual C#™ .NET and Microsoft® Visual Studio® .NET
Developing and Implementing Windows®-based Applications
with Microsoft® Visual C#™ .NET and Microsoft® Visual Studio® .NET
Developing XML Web Services and Server Components with
Microsoft Visual C# .NET and the Microsoft .NET Framework

You may also be interested in...

Comments and Discussions

QuestionHow to create Custom Identity object? Pin
Pradeep Babu Yadagani9-Feb-11 15:48
memberPradeep Babu Yadagani9-Feb-11 15:48 
AnswerRe: How to create Custom Identity object? Pin
vietanh15423-Jul-12 21:59
membervietanh15423-Jul-12 21:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02-2016 | 2.8.180322.1 | Last Updated 4 Mar 2009
Article Copyright 2009 by vietanh154
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid