Many people ask about REST authentication, so here are a few possible approaches.

Simply put, a server provides access to resources by users/clients, and authentication is a mechanism used to identify users. A REST request you make or consume may require authentication in most business situations.

There is really nothing special about REST calls when it comes to authentication because they are ultimately just http requests, only the URL style is “RESTful”, and the techniques below apply to any http implementation, including ASP.NET.
Here are some scenarios that do not involve any third-parties at run-time.

1. Http authentication over SSL

This seems to be a common approach, whereby the client (webpage or application) sends a username and password (un/pw) in the http header to the server over SSL (encryption is important since the un/pw is clear text). The server retrieves this un/pw and authenticates/authorizes the request accordingly.
There are a number of ways to store a user data and authenticate the un/pw against it, from the built-in asp.NET Membership stuff to a simple match of passwords in a User table.

Your IIS website/service can be set up to use “basic authentication”, from website- properties – Directory Security (tab) – Auth and Access control – Edit and check the required box.
Servers that support basic http auth. are usually configured to “require a pre-authorization”. I don’t know how to do this in IIS.

Server code:

The incoming request has a http Request header, which you can get the auth information from.
In your incoming aspx or auth layer, you can get this from Request.Headers[“Authorization”] and will be of the format “Basic dW46cHc=”.

Here’s some aspx code you can use:
Remember to add a try/catch in there.

protected void Page_Load(object sender, EventArgs e)
{
    const string BASIC = "Basic ";

    string authHeader = Request.Headers["Authorization"];

    if (!string.IsNullOrEmpty(authHeader) && authHeader.Contains(BASIC))
    {
        string auth = authHeader.Substring(BASIC.Length);
        System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
        System.Text.Decoder utf8Decode = encoder.GetDecoder();

        byte[] credentialBuffer = Convert.FromBase64String(auth);
        int charCount = utf8Decode.GetCharCount(credentialBuffer, 0, credentialBuffer.Length);
        char[] decoded_char = new char[charCount];
        utf8Decode.GetChars(credentialBuffer, 0, credentialBuffer.Length, decoded_char, 0);
        string authDecoded = new String(decoded_char);

        string[] unpw = authDecoded.Split(':');
        string username = unpw[0];
        string pwd = unpw[1];
    }

…
…
…
}

At the end of this, you will have the supplied credentials in username and pwd.

Client code:

In basic auth with pre-auth required, you make an initial http request without credentials (don’t get confused by the phrase pre-auth) and the server returns a Response code of 401. This indicates that the server is looking for auth info and you resubmit the request this time with the un/pw in the http header. Setting the PreAuthenticate property of your HttpWebRequest object to TRUE, and the auth information will be sent automatically in the http header by .NET, while making any future requests to that URI.
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.preauthenticate.aspx
If the server is not configured for pre-auth, you send the un/pw directly in the initial request.

Here is some sample code for your client to supply basic http auth.. For CRUD operations, you would need to POST some information (for an update) and that is included here.
For plain URL access, replace the method from POST to GET and remove the lines that write to the Request stream.

Add usings at the top:

using System.Net;
using System.IO;
using System.Text;

To post a string called myContent to myURL

try
{

HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(myURL);
req.Method = "POST";
req.Timeout = 10000;        // 10 seconds timeout
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = myContent.Length;
byte[] credentialBuffer = new UTF8Encoding().GetBytes(username + ":" + password);
req.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);
stream = req.GetRequestStream();
stream.Write(Encoding.Default.GetBytes(myContent), 0, myContent.Length);
}
catch (Exception ex)
{
    … //error handling

throw new Exception(ex.Message);
}
finally
{
    if (stream != null)
        stream.Close();
}

Now, to read in the response (for your request object req).

HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
stream = resp.GetResponseStream();

byte[] readBuf = new byte[2048]; //whatever the expected size

int bytesRead = stream.Read(readBuf, 0, 2048);
string readData = Encoding.ASCII.GetString(readBuf);
stream.Close();

string received = readData.Trim();

2. Client certificates

This is the most secure form of identifying a particular client. I will add that is constrained because it needs certificate installation and is expensive but it has its uses in mostly B2B but maybe B2C scenarios as well.
For e.g. A financial application wants to retrieve data from a financial warehouse.

Client certificates identify the client making the request, and are issued by third-parties, like Verisign, who verify the client while issuing the certificate, and vouch for the authenticity of the client.

This URL has pretty much everything you need to know about certificates: http://msdn.microsoft.com/en-us/magazine/cc163454.aspx

Hope that helped…
In the future, I will write about oAuth and federated services.

Advertisements