I'm attempting to call Identity Server 4 with Flurl
Im getting a 400 back from the ID server. The credentials etc work when I make the call with PostMan or with the methods available in IdentityModel.Client.
I am unsure about the Post i.e. PostUrlEncodedAsync As you can see I have tried various combinations.
This.. does not work
var address = "http://localhost:8027/connect/token";
var x = await address
.WithBasicAuth("clientName", "secretValue")
.SetQueryParams(
new
{
GrantType = "client_credentials",
Scope = "requiredScope"
}
)
.PostUrlEncodedAsync(new { });
//.SendAsync(HttpMethod.Post, null, CancellationToken.None);
//.SendAsync(HttpMethod.Post, y);
This.. does.
var apiClientCredentials = new ClientCredentialsTokenRequest()
{
Address = "http://localhost:8027/connect/token",
ClientId = "clientName",
ClientSecret = "secretValue",
Scope = "requiredScope"
};
var client = new HttpClient();
var tokenResponse = await client.RequestClientCredentialsTokenAsync(apiClientCredentials);
if (tokenResponse.IsError)
{
}
I can see that deep doen inside 'RequestClientCredentialsTokenAsync' it does parameters.Add to add grant type and scope hence I have added those as params.
Have also tried adding the client id and secret to the query params.
Same 400 message.
Any help greatly appreciated.
I believe the difference is that IdentityModel knows to serialize those ClientCredentialsTokenRequest
property names like ClientId
and GrantType
to snake-case, i.e. client_id
and grant_type
, as required by OAuth2. When you hand Flurl an anonymous object, it just serializes the property names exactly as-is. To make it work with Flurl you can either create a class and decorate it with Json.NET serialization attributes, or (what I typically do) keep it simple take some liberties with C# property name conventions:
.SetQueryParams(
new
{
grant_type = "client_credentials",
scope = "requiredScope"
}