I am currently using this example:
https://docs.microsoft.com/en-us/azure/active-directory/active-directory-authentication-scenarios#daemon-or-server-application-to-web-api
To check the Client Credentials Flow with OAuth in Azure AD. Theoretically the example works OK. Client App successfully communicates with the server App, obtaining first the OAuth Token from Azure AD token url. No problems there. However, I am trying to use Postman to check the Client Credentials Flow and I cannot get it to work.
In Postman, I should provide an Access Token Url, a Client ID and a Client Secret, Grant Type is set to Client Credentials. Using the same parameters as in the example provided by Microsoft's sample in https://github.com/Azure-Samples/active-directory-dotnet-daemon, I get a 401 response when trying to access the web service. I think the main reason is because in Postman, I can not type the resource I want to access, so the received token is not "linked" to any resource and that is why the authorization fails in the web server? Could this be the reason? If that is the reason, then what should I do in the server, because, somehow it seems as if Postman's requirements should be the ones valid in the Client Credentials Flow (I mean, no resource should be given, according to the OAuth2 Client Credentials Flow, right?
This is the code for the Starup class in the sample downloaded from Microsoft's example
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"]
});
}
ConfigurationManager.AppSettings["ida:Tenant"] is my Azure AD tentant, while ConfigurationManager.AppSettings["ida:Audience"] is the protected resource I need to access. Both values are required, if I do not provide the Audience, I get an error in .NET web API initialization.
You can use the OAuth 2.0 client credentials grant specified in RFC 6749, sometimes called two-legged OAuth, to access web-hosted resources by using the identity of an application.
Go to https://api-console.zoho.com/ and click Add Client to create a new one. Provide a name for the client and select the Type as Server-based Application. Fill in the rest of the form and click Create. The Client ID and Client Secret will be generated for the respective client.
EDIT
I think the problem is that Azure Token server doesn't accept client credentials sent as an Authorization header. e.g.
Authorization: Basic YmE1NTZlYmItZGY2OS00NjBhLWEwMjItNTI0NWQ0MzA2N2UxOmVxVzlqaXRobXF2cVFiVWY5dmxaWnhZN2wwUzZhQ0pHSkExSGt0eUd3N0W6
but that's how Postman's "Get new access token" tool sends it. So it's isn't going to work.
If you look at Microsoft's documentation and search for "get a token" you will see it implies that client credentials should be supplied in the body.
POST /common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=qWgdYAmab0YSkuL1qKv5bPX&grant_type=client_credentials
This works fine but seems to contradict the Oauth 2.0 spec which says:
The authorization server MUST support the HTTP Basic authentication scheme for authenticating clients that were issued a client password.
END EDIT
You definitely can get a bearer token back without supplying a resource.
Notice that resource
isn't even spelt correctly in the postman http body of the previous answer - it's spelt as resrource
which is why it's value of https://graph.microsoft.com
is ignored and does not match the resource
sent back in the response (00000002-0000-0000-c000-000000000000)
. Although funny enough they both relate to the api graph...but that's a digression.
Confusingly there are two ways of supplying client credentials to an Oauth 2.0 server and some servers don't accept both ways!
basic auth
header which is set to Base64(ClientId +
":" + ClientSecret)I guess that's the problem with Oauth 2.0 being a spec rather than a protocol... See - https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1
Postman's Request Token UI (see image below) uses method 1, but Azure auth server expects method 2. I know because I ran fiddler, and could see the request postman put together.
If you manually put the client credentials in the body e.g.
grant_type=client_credentials&scope=&client_id=ba556ebb-xxxx9-460a-ax2x-5245d43067e1&client_secret=eqW9jighghghgvlZZxY7l0S6aCJGJA1HktyGw7E=
and don't use a Basic Auth
http header. You can get a bearer token back even without suppyling a resource.
This works fine - but obviously that's no good for you in terms of using postman to get and store your tokens!
I think the main reason is because in Postman, I can not type the resource I want to access, so the received token is not "linked" to any resource and that is why the authorization fails in the web server? Could this be the reason?
You are correct. To get the access token via client credential flow, we need to provide the resource in the request.
What did you mean that not able to type the resource? The resource parameter is a parameter we can contain it in the body and here is a figure for your reference:
And be ensure that the value of resrouce is eaque to the audience config used to protect the resource.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With