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:
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:
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.