One of the most authentication protocol used today in the web application is OAuth, as you know the token-based authentication protocol, where a client send the credential for the authentication, and if all goes well it receives a bearer token that the client will use for the further requests to the server.
If I want to implement a C# client that send requests to a OAuth based application, the .NET framework give me some different options, that I want to describe in this post.
WebRequest
This is the first class implemented in the framework for this purpose and the most syntactically verbose, it was introduced in the .NET Framework 2.0.
If we want to send an authentication request to the application and get the access token, we need to write a code like this:
var request = WebRequest.CreateHttp(new Uri(_baseAddress + "/token")); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; var data = new StringBuilder(); data.Append("grant_type=password&"); data.Append("username=User&"); data.Append("password=Password"); var content = Encoding.UTF8.GetBytes(data.ToString()); request.ContentLength = content.Length; var requestStream = await request.GetRequestStreamAsync(); requestStream.Write(content, 0, content.Length); var authenticationResponse = await request.GetResponseAsync(); var responseStream = authenticationResponse.GetResponseStream(); var streamReader = new StreamReader(responseStream); var token = JsonConvert.DeserializeObject<Token>(streamReader.ReadToEnd()); request = WebRequest.CreateHttp(new Uri(_baseAddress + "/api/blogs")); request.Headers = new WebHeaderCollection() { { "Authorization", "Bearer " + token.access_token } }; var apiResponse = await request.GetResponseAsync(); Assert.That(((HttpWebResponse)apiResponse).StatusCode == HttpStatusCode.OK); requestStream.Close(); responseStream.Close(); authenticationResponse.Close(); apiResponse.Close();
The CreateHttp method retrieve an object of type WebRequest, that is used to compose the request with the credentials in the header.
As you can see, is a low level class, where we need to compose the data header by composing the parameters in a string.
The header is then witten in the request stream, retrieved with the GetRequestStreamAsync method.
With the GetResponseAsync we submit the request to the server and we receive the result; If all is fine, in the response we have the access token, and we can use it in another request to get the data.
WebClient
Also this class was introduced in .NET 2.0 framework, it’s an helper for the WebRequest class and the purpose is to give a more confortable interface to the developers.
Effectively, the authetication code looks more pretty that above:
using (var webClient = new WebClient()) { webClient.Headers = new WebHeaderCollection() { { "Content-Type", "application/x-www-form-urlencoded" } }; var content = new NameValueCollection() { { "grant_type", "password" }, { "username", "User" }, { "password", "Password" } }; var response = webClient.UploadValues(_baseAddress + "/token", content); var token = JsonConvert.DeserializeObject<Token>(Encoding.UTF8.GetString(response)); webClient.Headers = new WebHeaderCollection() { { "Authorization", "Bearer " + token.access_token } }; response = webClient.DownloadData(_baseAddress + "/api/blogs"); var results = JsonConvert.DeserializeObject<IEnumerable<Blog>>(Encoding.UTF8.GetString(response)); Assert.IsNotNull(results); }
As you can see, for the header parameters we can use a NameValueCollection because the WebClient class has a UploadValues method that accept this object type and internally deals with transforming of the NameValueCollection into a string before to pass it to the WebRequest class.
Then, the DownloadData internally calls the BeginGetResponse of the WebRequest class.
HttpClient
It’s the newer class introduced in the version 4.0 of the framework and is the easier to use; it’s a replacement of the WebClient and internally it also uses the WebRequest class.
We have to create a new instance of the HttpRequestMessage class and define the content of it with KeyValuePair objects that contains the credentials of the client.
Then, with the SendAsync method we can send the request and get the response with the relative content.
using (var httpClient = new HttpClient()) { httpClient.BaseAddress = new Uri(_baseAddress); var request = new HttpRequestMessage(HttpMethod.Post, "/token") { Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("grant_type", "password"), new KeyValuePair<string, string>("username", "User"), new KeyValuePair<string, string>("password", "Password") }) }; request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); using (var authenticationResponse = await httpClient.SendAsync(request)) { if (authenticationResponse.StatusCode == HttpStatusCode.OK) { var content = await authenticationResponse.Content.ReadAsStringAsync(); var token = JsonConvert.DeserializeObject<Token>(content); request = new HttpRequestMessage(HttpMethod.Get, "/api/Blogs"); request.Headers.Add("Authorization", "Bearer " + token.access_token); using (var apiResponse = await httpClient.SendAsync(request)) { Assert.AreEqual(apiResponse.StatusCode, HttpStatusCode.OK); } } } }
So, the HttpClient is a new implementation of the WebClient, with more features.
Finally, if we don’t have legacy software that is implemented with a older version of .NET framework, the right choice to implement a client with an OAuth authentication is the HttpClient.
Leave a Reply