I'm trying to send a request to Auth0
from my asp.net core application.
I am using HttpClient
for that.
Issue is when I create same request in postman everything works fine but if I use it from my .NET Core app than it throws
System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).
Here's the image of postman example:
Request type is POST
Successful call would return access_token
POST Request expects few body parametes:
and Header
content-type must be application/x-www-form-urlencoded
.
So the request from postman looks like this:
https://mydemoapplication.auth0.com/oauth/token? grant_type=client_credentials &client_id=some_my_id &client_secret=some_my_client_secrets &audience=https://mydemoapplication.auth0.com/api/v2/
And this works perfectly fine.
But when I try to repeat same action from .NET CORE Web api
I get 401 (Unauthorized).
all the time.
Here is my C# code:
First we are starting with method RequestTokenFromAuth0
public async Task<string> RequestTokenFromAuth0(CancellationToken cancellationToken)
{
// tokenUrl represents https://mydemoapplication.auth0.com/oauth/token
var tokenUrl = $"{_auth0HttpConfig.TokenEndpoint}";
// Creating anonymous object which will be used in post request
var data = new
{
grant_type = "client_credentials",
client_id = _auth0HttpConfig.ClientId ,
client_secret = _auth0HttpConfig.ClientSecret,
audience = _auth0HttpConfig.Audience
};
//var data = $"grant_type=client_credentials&client_id={_auth0HttpConfig.ClientId}&client_secret={_auth0HttpConfig.ClientSecret}&audience={_auth0HttpConfig.Audience}";
var response = await _auth0Client.PostToken<Auth0Auth>(tokenUrl, data, cancellationToken);
if(response!= null && response.Success && response.Data != null && !string.IsNullOrWhiteSpace(response.Data.Token))
{
return response.Data.Token;
}
else
{
throw new ArgumentException("Token is not retrieved.");
}
}
public async Task<T> PostToken<T>(string endpoint, object jsonObject, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(endpoint))
{
throw new ArgumentNullException(endpoint);
}
var reqMessage = GenerateTokenRequestMessage(HttpMethod.Post, jsonObject, endpoint);
var result = await GetResult<T>(httpRequestMessage, cancellationToken);
return result;
}
public HttpRequestMessage GenerateTokenRequestMessage(HttpMethod httpMethod, object objectToPost, string endpoint)
{
var httpRequestMessage = new HttpRequestMessage(httpMethod, endpoint);
var serializedObjectToCreate = JsonConvert.SerializeObject(objectToPost, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
httpRequestMessage.Content = new StringContent(serializedObjectToCreate);
httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
return httpRequestMessage;
}
private async Task<T> GetResult<T>(HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
HttpResponseMessage response = await _client.SendAsync(request, cancellationToken);
response.EnsureSuccessStatusCode(); // THIS LINE Throws exception 401 Unathorized
var result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
catch (Exception ex)
{
throw;
}
}
Something is wrong here and I don't know why I'm getting unathorized, what might be wrong here I'm not sure really! Any kind of help would be great!
P.S Repeating once more again from postman everything works fine!
Thanks
Cheers
_auth0Client.PostToken<Auth0Auth>(tokenUrl, data, cancellationToken);
And PostToken
takes data
as object jsonObject
and passes it to GenerateTokenRequestMessage
which then creates the HTTP content:
var serializedObjectToCreate = JsonConvert.SerializeObject(objectToPost, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
httpRequestMessage.Content = new StringContent(serializedObjectToCreate);
httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
But here you are putting in the data serialized as JSON and expect it to be application/x-www-form-urlencoded
. But that’s obviously not the case. What you are generating looks like this:
{"grant_type":"client_credentials","client_id":"ClientId","client_secret":"ClientSecret","audience":"Audience"}
But instead, it should look like this:
grant_type=client_credentials&client_id=ClientId&client_secret=ClientSecret&audience=Audience
You can use the FormUrlEncodedContent
type for this:
httpRequestMessage.Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "client_credentials",
["client_id"] = _auth0HttpConfig.ClientId,
["client_secret"] = _auth0HttpConfig.ClientSecret,
["audience"] = _auth0HttpConfig.Audience,
});