Wednesday, 9 August 2017

Using PKCE with IdentityServer from a Xamarin Client

The OpenID Connect and OAuth 2.0 specifications define a number of authentication flows between clients and authentication providers. These include:

  • Implicit.This authentication flow is optimized for browser-based apps. All tokens are transmitted via the browser.
  • Authorization code. This authentication flow provides the ability to retrieve tokens on a back channel, as opposed to the browser front channel, while also supporting client authentication.
  • Hybrid. This authentication flow is a combination of the implicit and authorization code flows. The identity token is transmitted via the browser channel and contains the signed protocol response along with other artifacts such as the authorization code. After successful validation of the response, the back channel is used to retrieve the access and refresh tokens.

The eShopOnContainers mobile app communicates with an identity microservice, which uses IdentityServer 4 to perform authentication, and access control for APIs. The app uses the hybrid authentication flow to retrieve access tokens, as this flow mitigates a number of attacks that apply to the browser channel, and this approach is explained in the guidance documentation.

However, OAuth 2.0 clients that utilize authorization codes are susceptible to an authorization code interception attack. In this attack, the authorization code returned from an authorization endpoint is intercepted within a communication path not protected by Transport Layer Security (TLS), such as inter-application communication within the client’s operating system. Once the attacker has gained access to the authorization code, it can be used to obtain the access token. While a number of pre-conditions must hold for the authorization code interception attack to work, it has been observed in the wild.

To mitigate this attack, the Proof Key for Code Exchange (PKCE) extension to OAuth 2.0 adds additional parameters to the OAuth 2.0 authorization and access token requests:

  1. The client creates a cryptographically random key called a code verifier, and derives a transformed value, called a code challenge, which is sent in the OAuth 2.0 authorization request along with the transformation method.
  2. The authorization endpoint responds as usual but records the code challenge and transformation method.
  3. The clients sends the authorization code in the access token request, and also includes the code verifier.
  4. The authorization server transforms the code verifier and compares it to the code challenge. Access is denied if they are not equal.

This works as a mitigation for native apps because if an attacker intercepts the authorization code in step (2), it can’t redeem it for an access token as the attacker is not in possession of the code verifier. In addition, the code verifier can’t be intercepted since it’s sent over TLS.

For detailed information about PKCE, see Proof Key for Code Exchange by OAuth Public Clients.

Implementing PKCE

Following the guidance in the OAuth 2.0 for Native Apps specification, that PKCE should be used in authorization code based authentication flows, I’ve recently updated the eShopOnContainers mobile app to use PKCE when communicating with IdentityServer.

Server Side

IdentityServer must be configured to require the use of PKCE. This is achieved by modifying the configuration of the IdentityServer Client object for the Xamarin client:

public static IEnumerable<Client> GetClients(Dictionary<string,string> clientsUrl) { return new List<Client> { ... new Client { ClientId = "xamarin", ClientName = "eShop Xamarin OpenId Client", AllowedGrantTypes = GrantTypes.Hybrid, ClientSecrets = { new Secret("secret".Sha256()) }, RedirectUris = { clientsUrl["Xamarin"] }, RequireConsent = false, RequirePkce = true, PostLogoutRedirectUris = { $"{clientsUrl["Xamarin"]}/Account/Redirecting" }, AllowedCorsOrigins = { "http://eshopxamarin" }, AllowedScopes = new List<string> { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.OfflineAccess, "orders", "basket" }, AllowOfflineAccess = true, AllowAccessTokensViaBrowser = true }, ... }; }

This configuration adds the RequirePkce property to the Client object. The RequirePkce property specifies whether clients using an authorization code must send a proof key.

Client Side

The CreateAuthorizationRequest method in the IdentityService class creates the URI for IdentityServer’s authorization endpoint, and the URI must be modified to include additional query parameters. The following code example shows the modified method:

public string CreateAuthorizationRequest() { // Create URI to authorization endpoint var authorizeRequest = new AuthorizeRequest(GlobalSetting.Instance.IdentityEndpoint); // Dictionary with values for the authorize request var dic = new Dictionary<string, string>(); dic.Add("client_id", GlobalSetting.Instance.ClientId); dic.Add("client_secret", GlobalSetting.Instance.ClientSecret); dic.Add("response_type", "code id_token"); dic.Add("scope", "openid profile basket orders locations marketing offline_access"); dic.Add("redirect_uri", GlobalSetting.Instance.IdentityCallback); dic.Add("nonce", Guid.NewGuid().ToString("N")); dic.Add("code_challenge", CreateCodeChallenge()); dic.Add("code_challenge_method", "S256"); // Add CSRF token to protect against cross-site request forgery attacks. var currentCSRFToken = Guid.NewGuid().ToString("N"); dic.Add("state", currentCSRFToken); var authorizeUri = authorizeRequest.Create(dic); return authorizeUri; }

The client first creates a code verifier for the authorization request, with the CreateCodeChallenge method:

private string CreateCodeChallenge() { _codeVerifier = RandomNumberGenerator.CreateUniqueId(); var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256); var challengeBuffer = sha256.HashData( CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(_codeVerifier))); byte[] challengeBytes; CryptographicBuffer.CopyToByteArray(challengeBuffer, out challengeBytes); return Base64Url.Encode(challengeBytes); }

The CreateUniqueId method in the RandomNumberGenerator class creates a high-entropy cryptographic random string using the PCLCrypto library. Note that the PKCE specification requires that the code verifier is base64 URL-encoded to produce a URL safe string. However, the code verifier here is already URL safe, and so this additional operation isn’t required.

The CreateCodeChallenge method then creates a code challenge derived from the code verifier. This can be achieved by using one of the following transformations:

  • code challenge = code verifier (known as the plain transformation)

OR

  • code challenge = base64urlencode(Sha256(code_verifier)) (known as the S256 transformation)

If the client is capable of using the S256 transformation, it must do so, as this transformation is mandatory to implement on compliant servers. The CreateAuthorizationRequest method uses the S256 transformation, which SHA256 encodes the code verifier, and then base64 url-encodes the SHA256 output.

The client then sends the code challenge as part of the OAuth 2.0 authorization request, using the following additional parameters:

  • code_challenge – the derived code challenge
  • code_challenge_method – S256 (or plain)

When IdentityServer issues the authorization code in the authorization response, it associates the code challenge and code challenge method values with the authorization code so that it can be verified later. Note that if IdentityServer is configured to use PKCE, and the client does not send the code challenge, the authorization endpoint responds with an error response set to invalid_request.

Upon receipt of the authorization code, the client sends the access token request to the token endpoint. In addition to the existing parameters, it also sends the following parameter:

  • code_verifier – the code verifier

In the eShopOnContainers app, this is achieved with the GetTokenAsync method in the IdentityService class:

public async Task<UserToken> GetTokenAsync(string code) { var data = string.Format("grant_type=authorization_code&code={0}&redirect_uri={1}&code_verifier={2}", code, WebUtility.UrlEncode(GlobalSetting.Instance.IdentityCallback), _codeVerifier); var token = await _requestProvider.PostAsync<UserToken>(GlobalSetting.Instance.TokenEndpoint, data, GlobalSetting.Instance.ClientId, GlobalSetting.Instance.ClientSecret); return token; }

Upon receipt of the request at the token endpoint, IdentityServer verifies it by calculating the code challenge from the received code verifier, and comparing it with the previously associated code challenge, after first transforming it according to the code challenge method specified by the client. If the values are not equal, an error response indicating invalid_grant is returned. If the values are equal, the token endpoint continues processing as normal and responds with an access token, identity token, and refresh token.

Summary

OAuth 2.0 clients that utilize authorization codes are susceptible to an authorization code interception attack. To mitigate this attack, the PKCE extension to OAuth 2.0 adds additional parameters to the OAuth 2.0 authorization and access token requests.

Following the guidance in the OAuth 2.0 for Native Apps specification, that PKCE should be used in authorization code based authentication flows, I’ve recently updated the eShopOnContainers mobile app to use PKCE when communicating with IdentityServer.

For detailed information about PKCE, see Proof Key for Code Exchange by OAuth Public Clients.

Monday, 31 July 2017

Transient Fault Handling in Xamarin.Forms using Polly

Previously I wrote about transient fault handling in Xamarin.Forms, and discussed an implementation of the retry pattern that uses exponential backoff. The advantage of the implementation was that the retry pattern was implemented without requiring any library code, for those sensitive to bloating their application package size.

There are, however, transient fault handling libraries available and the go to library for .NET is Polly, which includes fluent support for the retry pattern, circuit breaker pattern, bulkhead isolation, and more. In Polly, these patterns are implemented via fault handling policies, which handle specific exceptions thrown by, or results returned by, the delegates that are executed through the policy.

This blog post will discuss using Polly’s RetryPolicy, which implements the retry pattern.

Implementation

The sample application, which can be found on GitHub, is similar to the sample application from my previous blog post, with the custom implementation of the retry pattern replaced with Polly’s.

Initialization

The App class in the sample application initializes the classes that are responsible for communicating with the REST service:

TodoManager = new TodoItemManager( new RestService( new ResilientRequestProvider()));

The RestService class provides data to the TodoItemManager class, with the RestService class making REST calls using the ResilientRequestProvider class, which uses Polly to implement the retry pattern, using exponential backoff.

ResilientRequestProvider

The following code example shows the GetAsync method from the ResilientRequestProvider class, which makes GET requests to a specified URI:

async Task<HttpResponseMessage> HttpInvoker(Func<Task<HttpResponseMessage>> operation) { return await retryPolicy.ExecuteAsync(operation); } public async Task<TResult> GetAsync<TResult>(string uri) { string serialized = null; var httpResponse = await HttpInvoker(async () => { var response = await client.GetAsync(uri); response.EnsureSuccessStatusCode(); serialized = await response.Content.ReadAsStringAsync(); return response; }); return JsonConvert.DeserializeObject<TResult>(serialized); }

The GetAsync method code is identical to my previous blog post. The lambda expression is passed to the HttpInvoker method, which in turn passes it to the ExecuteAsync method of the RetryPolicy instance. Therefore, the code in the lambda expression is what will be retried if the GET request fails.

The RetryPolicy type is a Polly type, which represents a retry policy that can be applied to delegates that return a value of type T. The following code example show the RetryPolicy<T> declaration from the sample application:

RetryPolicy<HttpResponseMessage> retryPolicy;

This declares a RetryPolicy that can be applied to delegates that return a HttpResponseMessage.

There are 3 steps to using a fault handling policy, including the RetryPolicy<T> type, in Polly:

  1. Specify the exceptions you want the policy to handle.
  2. Optionally specify the returned results you want the policy to handle.
  3. Specify how the policy should handle any faults.

The following code example shows all three steps for defining the operation of the RetryPolicy<T> instance:

HttpStatusCode[] httpStatusCodesToRetry = { HttpStatusCode.RequestTimeout, // 408 HttpStatusCode.InternalServerError, // 500 HttpStatusCode.BadGateway, // 502 HttpStatusCode.ServiceUnavailable, // 503 HttpStatusCode.GatewayTimeout // 504 }; retryPolicy = Policy .Handle<TimeoutException>() .Or<HttpRequestException>() .OrResult<HttpResponseMessage>(r => httpStatusCodesToRetry.Contains(r.StatusCode)) .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (response, delay, retryCount, context) => { Debug.WriteLine($"Retry {retryCount} after {delay.Seconds} seconds delay due to {response.Exception.Message}"); });

The Policy.Handle method is used to specify the exceptions and results you want the policy to handle. Here it specifies that the delegate should be retried if a TimeoutException or HttpRequestException occurs, or if the resulting HttpResponseMessage includes any of the HTTP status codes contained in the httpStatusCodesToRetry array. Therefore, the RetryPolicy<T> instance handles both exceptions and return values in a single policy.

After specifying the exceptions and results you want the policy to handle, you must specify how the policy should handle any faults. Several of Polly’s methods can be used here, including Retry, RetryForever, WaitAndRetry, or WaitAndRetryForever (along with their async variants). I chose to use one of the WaitAndRetryAsync overloads, for which three arguments must be specified:

  1. The maximum number of retries to make. Note that the overall number of attempts that will be made is one plus the number of retries configured. Therefore, four attempts can be made with this code: the initial attempt, plus up to three retries.
  2. A delegate, expressed here as a lambda expression, that calculates the duration to wait between retries based on the current retry attempt.
  3. An action to be called on each retry, that provides the current exception, duration, retry count, and context.

The advantage of using this overload is that it allows an exponential backoff strategy to be specified through calculation, and to output messages as retries are attempted.

Executing an Action through the Policy

The overall operation is that the GetAsync method in the ResilientRequestProvider class invokes the HttpInvoker method, passing an action that represents the GET request. The HttpInvoker method invokes Polly’s RetryPolicy.ExecuteAsync method, passing the received action as an argument.

The retry policy then attempts the action passed in via the ExecuteAsync method. If the action executes successfully, the return value is returned and the policy exits. If the action throws an unhandled exception, it’s rethrown and the policy exits – no further retries are made. However, if the action throws a handled exception, the policy performs the following operations:

  • Counts the exception.
  • Checks whether another retry is permitted:
    • If not, the exception is rethrown and the policy terminates.
    • If another try is permitted, the policy calculates the duration to wait from the supplied sleep duration configuration, waits for the calculation duration, and returns to the beginning of the cycle to retry executing the action again.

Running the Sample Application

The sample application, which can be found on GitHub, connects to a read-only REST service hosted by Xamarin, and it’s most likely that when running the sample the GET operation will succeed on first attempt. To observe the retry pattern in operation, change the RestUrl property in the Constants class to an address that doesn’t exist – this can be accomplished by adding a random character to the end of the existing string. Then run the application and observe the output window in Visual Studio. You should see something like:

Retry 1 after 2 seconds delay due to 404 (Not Found) Thread started: <Thread Pool> #10 Thread started: <Thread Pool> #11 Retry 2 after 4 seconds delay due to 404 (Not Found) Retry 3 after 8 seconds delay due to 404 (Not Found) ERROR: 404 (Not Found)

This shows the GET operation being retried 3 times, after an exponentially increasing delay. Remember that the number of retries, and backoff strategy can be specified with Polly’s WaitAndRetry method. This allows the RetryPolicy to be customized to fit individual application requirements.

The advantage of using Polly over implementing your own retry pattern is that Polly includes multiple transient fault handling patterns that can easily be combined for additional resilience when handling transient faults.

Summary

Polly is a .NET transient fault handling library, which includes fluent support for the retry pattern. In Polly, the retry pattern is implemented by the RetryPolicy type, which handles specific exceptions thrown by, or results returned by, the delegates that are executed through the policy.

The RetryPolicy type is highly configurable, allowing you to specify the exceptions to be handled, the return results to be handled, and how the policy should handle any faults.

The advantage of using Polly over implementing your own retry pattern is that Polly includes multiple transient fault handling patterns that can easily be combined for additional resilience when handling transient faults.

Wednesday, 26 July 2017

Transient Fault Handling in Xamarin.Forms

All applications that communicate with remote services and resources must be sensitive to transient faults. Transient faults include the momentary loss of network connectivity to services, the temporary unavailability of a service, or timeouts that arise when a service is busy. These faults are often self-correcting, and if the remote access request is repeated after a suitable delay it’s likely to succeed.

Transient faults can have a huge impact on the perceived quality of an application, even if it has been thoroughly tested under all forseeable circumstances. To ensure that an application that communicates with remote services operates reliably, it must be able to:

  1. Detect faults when they occur, and determine if the faults are likely to be transient.
  2. Retry the operation if it’s determined that the fault is likely to be transient, and keep track of the number of times the operation is retried.
  3. Use an appropriate retry strategy, which specifies the number of retries, the delay between each attempt, and the actions to take after a failed attempt.

This transient fault handling can be achieved by wrapping all attempts to access a remote service in code that implements the retry pattern.

Retry Pattern

If an application detects a failure when it tries to send a request to a remote service, it can handle the failure by:

  • Retrying the operation – the application could retry the failing request immediately.
  • Retrying the operation after a delay – the application could wait for a suitable amount of time before retrying the request.
  • Cancelling the operation – the application should cancel the operation and report an exception.

The retry strategy should be tuned to match the business requirements of the application. For example, it’s important to optimize the retry count and retry interval to the operation being attempted. If the operation is part of a user interaction, the retry interval should be short and only a few retries attempted to avoid making users wait for a response. If the operation is part of a long running workflow, where cancelling or restarting the workflow is expensive of time-consuming, it’s appropriate to wait longer between attempts and retry more times.

If a request still fails after a number of retries, it’s better for the app to prevent further requests going to the same resource and to report a failure. Then, after a set period, the application can make one or more requests to the resource to see if they’re successful. I’ll return to this topic in a future blog post.

Retrying after an Exponential Delay

If transient faults are occurring because a remote service is overloaded, or being throttled at the service end, the service could reject new requests. While this scenario can be handled by the retry pattern, it’s possible that retry requests could add to the overloading of the service, which means that the service could take longer to recover from its overloaded state.

Exponential backoff attempts to deal with this problem by exponentially increasing the delay between retries, rather than retrying after a fixed delay. The purpose of this approach is give the service time to recover, in case the transient fault is due to a service overload. For example, when the initial request fails it can be retried after 1 second. If it fails for a second time, wait 2 seconds before the next retry. Then if the second retry fails, wait for 4 seconds before the next retry.

Implementing the Retry Pattern

In this blog post I’ll explain how I implemented the retry pattern, with exponential backoff. The advantage of the approach presented here is that the retry pattern is implemented without requiring any library code, for those sensitive to bloating their application package size.

My implementation of the retry pattern adds to Xamarin’s TodoREST sample. This sample demonstrates a Todo list application where the data is stored and accessed from a RESTful web service, hosted by Xamarin. However, I’ve modified the original implementation so that the RestService class moves some of its responsibilities to the RequestProvider class, which handles all REST requests.This ensures that all REST requests are made by a single class, which has a single responsibility. The following code example shows the GetAsync method from the RequestProvider class, which makes GET requests to a specified URI:

public async Task<TResult> GetAsync<TResult>(string uri) { var response = await client.GetAsync(uri); response.EnsureSuccessStatusCode(); string serialized = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject<TResult>(serialized); }

Note, however, that the sample application, which can be found on GitHub, doesn’t use the RequestProvider class. It’s included purely for comparison with the ResilientRequestProvider class, which the application uses, and which implements the retry pattern.

Initialization

The App class in the sample application initializes the classes that are responsible for communicating with the REST service:

TodoManager = new TodoItemManager ( new RestService ( new ResilientRequestProvider( new RetryWithExponentialBackoff())));

The RestService class provides data to the TodoItemManager class, with the RestService class making REST calls using the ResilientRequestProvider class, which uses the RetryWithExponentialBackoff class to implement the retry pattern, using exponential backoff.

ResilientRequestProvider

The following code example shows the GetAsync method from the ResilientRequestProvider class, which makes GET requests to a specified URI:

async Task<HttpResponseMessage> HttpInvoker(Func<Task<HttpResponseMessage>> operation) { return await retry.RetryOnExceptionAsync<HttpRequestException>(operation); } public async Task<TResult> GetAsync<TResult>(string uri) { string serialized = null; var httpResponse = await HttpInvoker(async () => { var response = await client.GetAsync(uri); response.EnsureSuccessStatusCode(); serialized = await response.Content.ReadAsStringAsync(); return response; }); return JsonConvert.DeserializeObject<TResult>(serialized); }

Notice that the code from the GetAsync method in the RequestProvider class is still present, but is now specified as a lambda expression. This lambda expression is passed to the HttpInvoker method, which in turn passes it to the RetryOnExceptionAsync method of the RetryWithExponentialBackoff class. Therefore, the code in the lambda expression is what will be retried if the GET request fails.

RetryWIthExponentialBackoff

The RetryWithExponentialBackoff class has a constructor with three arguments, as shown in the following code example:

public RetryWithExponentialBackoff(int retries = 10, int delay = 200, int maxDelay = 2000) { maxRetries = retries; delayMilliseconds = delay; maxDelayMilliseconds = maxDelay; }

The constructor arguments specify a maximum number of retries, the initial delay between retries (in milliseconds), and a maximum delay between retries (in milliseconds). However, the three constructor arguments also specify default values, allowing a parameterless constructor to be specified when the class is initialised in the App class.

The RetryOnExceptionAsync method in the RetryWithExponentialBackoff class is shown in the following code example:

public async Task<HttpResponseMessage> RetryOnExceptionAsync<TException>(Func<Task<HttpResponseMessage>> operation) where TException : Exception { HttpResponseMessage response; var backoff = new ExponentialBackoff(maxRetries, delayMilliseconds, maxDelayMilliseconds); while (true) { try { response = await operation(); break; } catch (Exception ex) when (ex is TimeoutException || ex is TException) { Debug.WriteLine("Exception: " + ex.Message); await backoff.Delay(); } } return response; }

This method is responsible for implementing the retry pattern - retrying failed operations with an exponential backoff up to a maximum number of retries. It uses an infinite loop to execute the operation that was specified as a lambda expression in the GetAsync method in the ResilientRequestProvider class. If the operation succeeds the infinite loop is broken out of, and the response received from the web service is returned. However, if the operation fails due to a transient fault, that is a TimeoutException or a HttpRequestException, the operation is retried after a delay controlled by the ExponentialBackoff class.

Obviously, the implementation of the RetryWithExponentialBackoff class could be tidied up so that it takes a dependency on an IBackoff type, which the ExponentialBackoff struct would implement. This would allow different backoff strategy implementations to easily be swapped in and out. However, the current implementation does adequately demonstrates what I’m trying to show – retrying requests that failed due to transient faults.

ExponentialBackoff

The ExponentialBackoff struct has a constructor requiring three arguments:

public ExponentialBackoff(int noOfRetries, int delay, int maxDelay) { maxRetries = noOfRetries; delayMilliseconds = delay; maxDelayMilliseconds = maxDelay; retries = 0; pow = 1; }

All three arguments must be specified when creating an instance of the struct, and they should be identical to the values of the arguments in the RetryWithExponentialBackoff class constructor.

The RetryOnExceptionAsync method in the RetryWithExponentialBackoff class invokes the Delay method in the ExponentialBackoff class if a transient fault has occurred. The Delay method is shown in the following code example:

public Task Delay() { if (retries < maxRetries) { retries++; pow = pow << 1; } else { throw new TimeoutException($"{maxRetries} retry attempts made. Retries failed."); } int delay = Math.Min(delayMilliseconds * (pow - 1) / 2, maxDelayMilliseconds); Debug.WriteLine($"Retry {retries} after {delay} milliseconds delay. Maximum delay is {maxDelayMilliseconds} milliseconds."); return Task.Delay(delay); }

This method implements a roughly exponential delay, up to a maximum number of milliseconds specified by the maxDelayMilliseconds variable, while ensuring that the maximum number of retry attempts isn’t exceeded by throwing a TimeoutException when the number of actual retries is equal to the maximum number of retries allowed.

Running the Sample Application

The sample application, which can be found on GitHub, connects to a read-only REST service hosted by Xamarin, and it’s most likely that when running the sample the GET operation will succeed on first attempt. To observe the retry pattern in operation, change the RestUrl property in the Constants class to an address that doesn’t exist – this can be accomplished by adding a random character to the end of the existing string. Then run the application and observe the output in the output window in Visual Studio. You should see something like:

Exception: 404 (Not Found) Retry 1 after 100 milliseconds delay. Maximum delay is 2000 milliseconds. Exception: 404 (Not Found) Retry 2 after 300 milliseconds delay. Maximum delay is 2000 milliseconds. Thread started: <Thread Pool> #10 Exception: 404 (Not Found) Retry 3 after 700 milliseconds delay. Maximum delay is 2000 milliseconds. Exception: 404 (Not Found) Retry 4 after 1500 milliseconds delay. Maximum delay is 2000 milliseconds. Exception: 404 (Not Found) Retry 5 after 2000 milliseconds delay. Maximum delay is 2000 milliseconds. Exception: 404 (Not Found) Retry 6 after 2000 milliseconds delay. Maximum delay is 2000 milliseconds. Exception: 404 (Not Found) Retry 7 after 2000 milliseconds delay. Maximum delay is 2000 milliseconds. Exception: 404 (Not Found) Retry 8 after 2000 milliseconds delay. Maximum delay is 2000 milliseconds. Thread started: <Thread Pool> #11 Thread started: <Thread Pool> #12 Exception: 404 (Not Found) Retry 9 after 2000 milliseconds delay. Maximum delay is 2000 milliseconds. Exception: 404 (Not Found) Retry 10 after 2000 milliseconds delay. Maximum delay is 2000 milliseconds. Exception: 404 (Not Found) ERROR: 10 retry attempts made. Retries failed.

This shows the GET operation being retried 10 times, after a roughly exponential increasing delay, up to a maximum of 2000 milliseconds. Remember that the number of retries, initial delay (in milliseconds), and maximum delay (in milliseconds) can be specified when creating the RetryWithExponentialBackoff instance. This allows the retry pattern to be customized to fit individual application requirements.

Summary

The retry pattern allows applications to retry a failing request to a remote service, after a suitable delay. Remote access requests that are repeated after a suitable delay are likely to succeed, if the fault in the remote service is transient.

This blog post has explained how to implement the retry pattern, with exponential backoff. The number of retries, initial delay, and maximum delay can all be specified, allowing the retry pattern to be customized to fit individual application requirements.The advantage of the approach presented here is that the retry pattern is implemented without requiring any library code, for those sensitive to bloating their application package size.

In my next blog post I’ll show how to re-implement the retry pattern using Polly.

Friday, 23 June 2017

Making a POST request to IdentityServer's token endpoint from a Xamarin client

I recently had to implement a hybrid authorisation flow from a Xamarin client to IdentityServer 4. This involved making a browser request to IdentityServer’s authorize endpoint to retrieve an authorisation code, and then making a REST request to IdentityServer’s token endpoint, exchanging the authorisation code for an access token.

However, I found the documentation on the token endpoint to be slightly lacking. It states that the token endpoint requires a POST request, along with a series of URL query parameters:
POST /connect/token client_id=client1& client_secret=secret& grant_type=authorization_code& code=hdh922& redirect_uri=https://myapp.com/callback
Every attempt at making this request failed. On top of that I wasn’t keen on sending a client secret potentially in the clear. After some digging through the IdentityServer code I was able to construct a POST request that worked for me, which I verified using Advanced REST Client. My POST request was:
POST /connect/token grant_type=authorization_code& code=hdh922& redirect_uri=https://myapp.com/callback
The value of the code parameter is the authorisation code retrieved from IdentityServer’s authorize endpoint, and the value of the redirect_uri parameter is the callback URL registered with IdentityServer. Note that this isn’t the only way of making the POST request to the token endpoint, as IdentityServer permits several variations.

So what’s happened to the client_id and client_secret query parameters listed in the first POST request? While IdentityServer can accept them as query parameters, I was unhappy about sending my client secret as a query parameter. Luckily, IdentityServer also permits both client_id and client_secret to be sent in the Authorization header of the POST request, encoded as a basic authentication value, which is what I did. For more information about basic authentication, see Specifying Basic Authentication in a Web Request.

Translating this into code produces the GetTokenAsync method, which makes the request using the PostAsync method of the RequestProvider class:
public async Task<UserToken> GetTokenAsync(string code) { string data = string.Format("grant_type=authorization_code&code={0}&redirect_uri={1}", code, WebUtility.UrlEncode(GlobalSetting.Instance.IdentityCallback)); var token = await _requestProvider.PostAsync<UserToken>(GlobalSetting.Instance.TokenEndpoint, data, GlobalSetting.Instance.ClientId, GlobalSetting.Instance.ClientSecret); return token; }
The PostAsync method in the RequestProvider class is shown in the following code example:
public async Task<TResult> PostAsync<TResult>(string uri, string data, string clientId, string clientSecret) { HttpClient httpClient = CreateHttpClient(string.Empty); if (!string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(clientSecret)) { AddBasicAuthenticationHeader(httpClient, clientId, clientSecret); } var content = new StringContent(data); content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); HttpResponseMessage response = await httpClient.PostAsync(uri, content); await HandleResponse(response); string serialized = await response.Content.ReadAsStringAsync(); TResult result = await Task.Run(() => JsonConvert.DeserializeObject<TResult>(serialized, _serializerSettings)); return result; }
After creating the HttpClient instance, the PostAsync method calls the AddBasicAuthenticationHeader method, which is shown in the following code example:
private void AddBasicAuthenticationHeader(HttpClient httpClient, string clientId, string clientSecret) { if (httpClient == null) return; if (string.IsNullOrWhiteSpace(clientId) || string.IsNullOrWhiteSpace(clientSecret)) return; httpClient.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(clientId, clientSecret); }
The AddBasicAuthenticationHeader method adds the Authorization header to the POST request, with its value being the clientId and clientSecret values encoded using basic authentication.

Back in the PostAsync method, the other piece of the puzzle that was missing from the IdentityServer documentation is that the ContentType of the POST request must be set to application/x-www-form-urlencoded. I suspect this is the missing piece of the puzzle that caused the original request to fail.

To see the full application from which I’ve taken this code, along with more content about using IdentityServer from a Xamarin client, see Enterprise Application Patterns using Xamarin.Forms.

Monday, 5 June 2017

Enterprise Application Patterns using Xamarin.Forms

For the last few months I've been working on a Xamarin.Forms guide, about building cross-platform enterprise apps. The first edition of the guide is now published as an eBook, and can be downloaded here, or by clicking the image below.


What's it all about?

The eBook provides guidance on building cross-platform enterprise apps using Xamarin.Forms. It focuses on providing architectural guidance for developing adaptable, maintainable, and testable Xamarin.Forms enterprise apps. Guidance is provided on how to implement MVVM, dependency injection, navigation, validation, and configuration management, while maintaining loose coupling. In addition, there's also guidance on performing authentication and authorization with IdentityServer, accessing data from containerized microservices, and unit testing.

The guide comes with source code for the eShopOnContainers mobile app, and source code for the eShopOnContainers reference app. The eShopOnContainers mobile app is a cross-platform enterprise app developed using Xamarin.Forms, which connects to a series of containerized microservices known as the eShopOnContainers reference app.

Who's it intended for?

The guide is aimed at readers who are already familiar with Xamarin.Forms. For a detailed introduction to Xamarin.Forms, see the Xamarin.Forms documentation on the Xamarin Developer Center, and Creating Mobile Apps with Xamarin.Forms.

The guide is complementary to .NET Microservices: Architecture for Containerized .NET Applications, which focuses on developing and deploying containerized microservices.

What's in the sample application?

The guide includes a sample application, eShopOnContainers, that's an online store that includes the following functionality:
  • Authenticating and authorizing against a backend service.
  • Browsing a catalog of shirts, coffee mugs, and other marketing items.
  • Filtering the catalog.
  • Ordering items from the catalog.
  • Viewing the user's order history.
  • Configuration of settings.
The following diagram provides a high-level overview of the architecture of the sample application:
The sample application ships with three client apps:
  • An MVC application developed with ASP.NET Core.
  • A Single Page Application (SPA) developed with Angular 2 and Typescript. This approach for web applications avoids performing a round-trip to the server with each operation.
  • A mobile app developed with Xamarin.Forms, which supports iOS, Android, and the Universal Windows Platform (UWP).
For information about the web applications, see Architecting and Developing Modern Web Applications with ASP.NET Core and Microsoft Azure.

The sample application includes the following backend services:
  • An identity microservice, which uses ASP.NET Core Identity and IdentityServer.
  • A catalog microservice, which is a data-driven create, read, update, delete (CRUD) service that consumes an SQL Server database using EntityFramework Core.
  • An ordering microservice, which is a domain-driven service that uses domain-driven design patterns.
  •  A basket microservice, which is a data-driven CRUD service that uses Redis Cache.
These backend services are implemented as microservices using ASP.NET Core MVC, and are deployed as unique containers within a single Docker host. Collectively, these backend services are referred to as the eShopOnContainers reference application. Client apps communicate with the backend services through a Representational State Transfer (REST) web interface. For information about the implementation of the backend services, see .NET Microservices: Architecture for Containerized .NET Applications.

What's the mobile app?

The guide focuses on building cross-platform enterprise apps using Xamarin.Forms, and uses the eShopOnContainers mobile app as an example. The following screenshots show the pages from the eShopOnContainers mobile app that provide the functionality outlined earlier:


The mobile app consumes the backend services provided by the eShopOnContainers reference application. However, it can be configured to consume data from mock services for those who wish to avoid deploying the backend services.

The eShopOnContainers mobile app exercises the following Xamarin.Forms functionality:
  • XAML
  • Controls
  • Bindings
  • Converters
  • Styles
  • Animations
  • Commands
  • Behaviors
  • Triggers
  • Effects
  • Custom Renderers
  • MessagingCenter
  • Custom Controls
In addition, unit tests are provided for some of the classes in the eShopOnContainers mobile app. For more information about this functionality, see the Xamarin.Forms documentation on the Xamarin Developer Center, and Creating Mobile Apps with Xamarin.Forms.

Where can I get help and provide feedback?

This project has a community site, on which you can post questions, and provide feedback. The community site is located at https://github.com/dotnet-architecture/eShopOnContainers. Alternatively, feedback about the eBook can be emailed to dotnet-architecture-ebooks-feedback@service.microsoft.com.

Friday, 24 March 2017

Validating User Input in Xamarin.Forms IV

Previously I discussed how validation can be automatically triggered when properties changes, or manually triggered to validate all properties. In this blog post I’m going to explore how to notify the user about any validation errors that have occurred.

Displaying Validation Errors

Validation errors are shown to the user by highlighting the control that contains invalid data, and by displaying an error message beneath the control, as shown in the following screenshot:

Validation errors

Highlighting a Control that contains Invalid Data

The Validation attached behaviour class is used to highlight controls where validation errors occur. The following code example shows how the Validation behaviour is attached to an Entry control:

<Entry Placeholder="Enter forename here" Text="{Binding User.Forename, Mode=TwoWay}" local:Validation.Errors="{Binding User.Errors[Forename]}" />

The Validation attached behaviour gets and sets the Errors bindable property, and in this example binds it to the Errors property of the User model class that’s exposed by the associated view model. The User.Errors property is provided by the ValidatableBase class, from which all model classes derive, and is an instance of the Validator class. The indexer of the Validator class returns a ReadOnlyCollection of error strings, to retrieve any validation errors for the Forename property. The Validation attached behavior class is shown in the following code example:

public static class Validation { public static readonly BindableProperty ErrorsProperty = BindableProperty.CreateAttached( "Errors", typeof(ReadOnlyCollection<string>), typeof(Validation), Validator.EmptyErrorsCollection, propertyChanged: OnPropertyErrorsChanged); public static ReadOnlyCollection<string> GetErrors(BindableObject element) { return (ReadOnlyCollection<string>)element.GetValue(ErrorsProperty); } public static void SetErrors(BindableObject element, ReadOnlyCollection<string> value) { element.SetValue(ErrorsProperty, value); } static void OnPropertyErrorsChanged(BindableObject element, object oldValue, object newValue) { var view = element as View; if (view == null | oldValue == null || newValue == null) { return; } var propertyErrors = (ReadOnlyCollection<string>)newValue; if (propertyErrors.Any()) { view.Effects.Add(new BorderEffect()); } else { var effectToRemove = view.Effects.FirstOrDefault(e => e is BorderEffect); if (effectToRemove != null) { view.Effects.Remove(effectToRemove); } } } }

The Errors attached property is registered as a ReadOnlyCollection of strings, by the BindableProperty.CreateAttached method. When the value of the Errors bindable property changes, the OnPropertyErrorsChanged method is invoked. The parameters for this method provide the instance of the control that the Errors bindable property is attached to, and any validation errors for the control. The BorderEffect class is added to the control’s Effects collection if validation errors are present, otherwise it’s removed from the control’s Effects collection.

The BorderEffect class subclasses the RoutingEffect class, and is shown in the following code example:

class BorderEffect : RoutingEffect { public BorderEffect() : base("Xamarin.BorderEffect") { } }

The RoutingEffect class represents a platform-independent effect that wraps an inner effect that’s usually platform-specific. This simplifies the effect removal process, since there is no compile-time access to the type information for a platform-specific effect. The BorderEffect calls the base class constructor, passing in a parameter consisting of a concatenation of the resolution group name, and the unique ID that’s specified on each platform-specific effect class.

The following code example shows the Xamarin.BorderEffect implementation for iOS:

[assembly: ResolutionGroupName("Xamarin")] [assembly: ExportEffect(typeof(BorderEffect), "BorderEffect")] namespace MVVMUtopia.iOS { public class BorderEffect : PlatformEffect { protected override void OnAttached() { try { Control.Layer.BorderColor = UIColor.Red.CGColor; Control.Layer.BorderWidth = 1; } catch (Exception ex) { Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); } } protected override void OnDetached() { try { Control.Layer.BorderWidth = 0; } catch (Exception ex) { Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); } } } }

The OnAttached method sets Control.Layer properties to values to create the red border, and the OnDetached method removes the red border. This functionality is wrapped in a try/catch block in case the control that the effect is attached to does not have the required Control.Layer properties.

For more information about effects, see Effects.

Displaying an Error Message

Each control that undergoes validation also has a Label beneath it, which is used to display the error message associated with the control. The following code example shows the Label displayed underneath the Entry that accepts a user’s forename:

<Label Text="{Binding User.Errors[Forename], Converter={StaticResource FirstErrorConverter}" />

The Label binds its Text property to the Errors property of the User model class that’s exposed by the associated view model. The User.Errors property is provided by the ValidatableBase class, from which all model classes derive, and is an instance of the Validator class. The indexer of the Validator class returns a ReadOnlyCollection of error strings, with the FirstErrorConverter retrieving the first error from the collection, for display.

Summary

Any mobile app that accepts user input should ensure that the input is valid. This could involve, for example, checking that input contains only characters in a particular range, or is of a certain length. Without validation, a user can supply data that can cause the app to fail.

In the context of MVVM, user input can be synchronously validated client-side in view model objects or in model objects. However, validating data in view models often means duplicating model properties. Instead, view models can delegate validation to the model objects they contain, with validation then being performed on the model objects. Validation rules can be specified on the model properties by using data annotations that derive from the ValidationAttribute class.

To participate in validation, model classes must derive from the ValidatableBase class, which provides an error container whose contents are updated whenever a model class property value changes. The Validator and ValidatableBase classes both implement INotifyPropertyChanged in order to provide property change notification.

The SetProperty method in the ValidatableBase class performs validation when a model property is set to a new value. The validation rules come from data annotation attributes that derive from the ValidationAttribute class. The attributes are taken from the declaration of the model property being validated.

Users are notified of validation errors by highlighting the controls that contain the invalid data with red borders, and by displaying error messages that inform the user why the data is invalid.

The code can be downloaded from GitHub.