Question

I've created a WCF DataService and for this service I require some custom authentication through the use of HTTP Headers. So i've written special functions that validate this information or throw an 403 page in the user's face when he's not allowed to see it.

To make it easy for myself, I tried to overwrite the OnStartProcessingRequest to perform this check every call, but for some reason this function is never called by my code/WCF service :S

This is the code of the WCF Service:

using System;
using System.Data.Services;
using System.Linq;
using System.Text;
using System.Web;

namespace TenForce.Execution.Web.OData
{
public class TenForceApi : DataService<Entities>
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(IDataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
        config.UseVerboseErrors = true;
        config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
    }

    /// <summary>
    /// <para>This function is called prior to handeling requests. The function will perform basic
    /// authentication using the Headers supplied by the client.</para>
    /// </summary>
    /// <param name="args">The arguments supplied for this call.</param>
    protected override void OnStartProcessingRequest(ProcessRequestArgs args)
    {
        HttpContext context = HttpContext.Current;
        string customAuthHeader = ExtractAuthenticationToken(context);
        ValidateAuthentication(customAuthHeader.Split('|'), context);
        base.OnStartProcessingRequest(args);
    }

    #region Private Members

    /// <summary>
    /// <para>This function will extract the custom tenforce authentication header from the
    /// http context and return the value of that header. If the header cannot be found, a
    /// DataServiceException is thrown.</para>
    /// </summary>
    /// <param name="context">The HttpContext object containing the custom HTTP header.</param>
    /// <returns>The value of the header</returns>
    /// <exception cref="DataServiceException">No Authentication Header provided.</exception>
    private static string ExtractAuthenticationToken(HttpContext context)
    {
        if (!context.Request.Headers.AllKeys.Contains(@"TenForce-Auth"))
            throw new DataServiceException(403, @"No authentication header provided.");
        return Encoding.UTF8.GetString(Convert.FromBase64String(context.Request.Headers[@"TenForce-Auth"]));
    }

    /// <summary>
    /// <para>Validates the authentication credentials stored inside the array.</para>
    /// </summary>
    /// <param name="values">Array holding the required authentication details.</param>
    /// <param name="context">The HttpContext holding the Request and Response for this call.</param>
    private static void ValidateAuthentication(string[] values, HttpContext context)
    {
        if (values.Length != 2) throw new DataServiceException(403, @"insufficient parameters provided for the authentication.");
        string username = values[0] ?? string.Empty;
        string password = values[1] ?? string.Empty;
        string database = Api2.Implementation.Authenticator.ConstructDatabaseId(context.Request.Url.AbsoluteUri);

        if (!Api2.Implementation.Authenticator.Authenticate(username, password, database))
        {
            AddResponseHeader(context, @"TenForce-RAuth", "DENIED");
            throw new DataServiceException(403, @"Incorrect authentication credentials.");
        }
    }

    /// <summary>
    /// <para>Add the specific HTTP Header to the Response of the provided HttpContext.</para>
    /// </summary>
    /// <param name="context">The HttpContext object holding the HTTP Response.</param>
    /// <param name="header">The name of the header to add to the response.</param>
    /// <param name="value">The value of the header.</param>
    private static void AddResponseHeader(HttpContext context, string header, string value)
    {
        if (!context.Request.ServerVariables[@"SERVER_SOFTWARE"].Contains(@"Microsoft-IIS/7."))
            context.Response.AddHeader(header, value);
        else
            context.Response.Headers.Add(header, value);
    }

    #endregion
}
}    

Anyone who could point out what the problem is?

Was it helpful?

Solution

More of a comment than an answer (how to just add comment?) but having what appears to be a very similar setup, I can say that OnStartProcessingRequest() with the signiture you have above is getting called here. These others virtual also work for me.

protected override ent CreateDataSource() {}
protected override void HandleException(HandleExceptionArgs args) {}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top