401 on OData call to D365FO - oauth-2.0

I'm trying to make an OData call to retrieve a D365FO data entity.
https://[root_URL]/data/CostGroups
When logged into D365FO in my browser, this call works.
I'm working in PHP.
I've registered my app in Azure Active Directory.
I've provided my app the https://erp.dynamics.com/Connector.FullAccess API permission.
I've registered my app in D365FO with a user that has admin privileges (the same user used for the successful browser call).
I am able to acquire an authentication token.
Its "aud" field is "https://erp.dynamics.com"
Its "appid" field matches that of the app's Azure AD registration
Its "roles" field includes only "Connector.FullAccess"
I'm using curl in PHP to make the OData GET request. I use the URL listed above and my headers are
curl_setopt($curl, CURLOPT_HTTPHEADER, [
'Accept: application/json',
'OData-MaxVersion: 4.0',
'OData-Version: 4.0',
'Authorization: Bearer ' . $this->accessToken
]);
Response is "401 Unauthorized"
Does anyone know what's going wrong or how I can find more information about the failure? Is there anywhere in D365FO I can look for logs of my attempts?

The resource seems to be incorrect. It should be the base URL of the instance without the trailing '/'.
Your "aud" field is https://erp.dynamics.com. In this case, it should be your [root URL]. Like this:
Check your resource when you post a request to https://login.microsoftonline.com/[tenant ID]/oauth2/token.

Related

Issues authenticating to Twilio to send message from sub-account or using API Keys

I'm having some issues sending SMS messages via a Twilio messaging service.
I have parent account and sub-account configuration.
cURL statement is as follows:
curl --location --request POST 'https://api.twilio.com/2010-04-01/Accounts/{{account-sid}}/Messages.json' \
--header 'Authorization: Basic {{auth}}' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'Body=test' \
--data-urlencode 'MessagingServiceSid={{messaging-service-SID}}' \
--data-urlencode 'To=REDACTED'
I can get it working for some combinations of account-sid and auth header, but not all is working as expected.
e.g. here is a table that describes what works and what doesn't.
Number
account-sid in URL path
username in auth header
password in auth header
Works?
Expected Result?
#1
Parent Account SID
Parent Account SID
Parent Account Auth Token
NO - HTTP 404
YES
#2
Parent Account SID
Parent Account API Key
Parent Account API Secret
NO - HTTP 401
NO - should return HTTP 404
#3
Parent Account SID
Sub Account SID
Sub Account Auth Token
NO - HTTP 401
NO - should return HTTP 404
#4
Parent Account SID
Sub Account API Key
Sub Account API Secret
NO - HTTP 401
NO - should return HTTP 404
#5
Sub Account SID
Sub Account SID
Sub Account Auth Token
NO - HTTP 401
NO
#6
Sub Account SID
Sub Account API Key
Sub Account API Secret
NO - HTTP 401
NO
#7
Sub Account SID
Parent Account SID
Parent Account Auth Token
YES
YES
#8
Sub Account SID
Parent Account API Key
Parent Account API Secret
NO - HTTP 401
NO
Any ideas as to why some of these (specifically the ones where the expected result in the table above is 'NO') aren't working? FYI., the basic auth is calculated by Postman as shown below, so there shouldn't be any issues with this. Note: I've been changing the variables appropriately and even hard coded the usernames/passwords...
FWIW I didn't expect any of the ones with the parent account SID in the URL path to work, but just added them for completeness... the one I really want to get working is #6 as I want to generate separate API keys for individual subsystems to mitigate risk/impact if one of the API keys gets compromised. Any ideas why this might not be working...
The behavior varies based on the host portion of the API you are calling.
Only api.twilio.com supports calling the sub-accounts using the main accounts Account SID and Auth Token. This is done using the construct defined here (Node.js example):
const client = require('twilio')(accountSid, authToken, { accountSid: subaccountSid });
Source: https://www.twilio.com/docs/iam/api/subaccounts
When performing CRUD operations within a subaccount, use the
subaccount SID and auth token. Alternatively, you can generate API
Keys at the subaccount level for authentication.
I managed to narrow this down to being an issue with the API Key/secret. Multiple Twilio staff had given me examples that they claimed worked, which were exactly the same as what I had, but weren't working for me... I tried creating an API Key/secret in a different region and it worked. Seems that only API Keys in the AU1 region have this issue. When I tried with an API Key in the US1 region it worked!
Suspect it's not fully available in the AU region at the time of this writing - see https://www.twilio.com/docs/global-infrastructure/regional-product-and-feature-availability#australia-au1-region

What scope should we use to sent messages to skype bot

Using https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-protocols-oauth-code/, i was able to generate access token. But when i try to sent a message to skype bot using the access token generated using scopes defined in above url, i get a "401: The provided 'OAuth' ticket failed authentication." error. What scopes should i use while i generate a code or access token to sent a message to skype bot via API (https://docs.botframework.com/en-us/skype/chat/#rest-api ) . The scope specified here under skype/chat/#authentication does not even takes me to login page to generate code .
To generate a token you should do the HTTP call described in https://api.botframework.com/en-us/skype/chat/#authentication, i.e.
POST /common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=<your bot msa app id>&client_secret=<your bot secret>&grant_type=client_credentials&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
So the scope is 'https://graph.microsoft.com/.default'.

How to access another user's data via the Graph API?

Using the Graph API and related authentication/authorization flows, how can I access data of all users in an organization? Also, multiple organizations/tenants need to be able to use the app.
As an example: I have an app which needs to read events from all calendars of all users under contoso.onmicrosoft.com. I would like that jack#contoso.onmicrosoft.com, the administrator, authorizes the app which will then be able to read the mentioned the data. Using the Managed API this can be easily done via impersonation.
However, I am trying to do the same with Graph API and OAuth, but I can't find a straight forward solution, or I must be missing something very obvious. I have created an app through manage.windowsazure.com (multi-tenant), and configured it so that it requires Microsoft Graph API (all application and delegated permissions).
I did the following:
1) Point jack#contoso.onmicrosoft.com towards https://login.microsoftonline.com/common/oauth2/authorize?response_type=code&redirect_uri=<my redirect url>&client_id=<my client id>
2) Jack authorizes the app
3) I get back: <my redirect url>/?code=<my authorization code>&session_state=<blah>
4) I send a POST request like below:
POST https://login.microsoftonline.com/common/oauth2/token
Headers: content-type: application/x-www-form-urlencoded
Body:
grant_type=authorization_code&code=<my auth code from step above>
&redirect_uri=<my redirect url>
&client_id=<my client id>
&client_secret=<my client secret>
&resource=https%3A%2F%2Fgraph.microsoft.com%2F
5) When I do the following:
GET https://graph.microsoft.com/v1.0/users/jack#contoso.onmicrosoft.com/messages
Headers: Authorization: Bearer <auth token from step #4>
I get a 200 OK response with the messages.
When I do the following:
GET https://graph.microsoft.com/v1.0/users/anyotheruser#contoso.onmicrosoft.com/messages
Headers: Authorization: Bearer <auth token from step #4>
I get a 403 Forbidden response with:
{
"error": {
"code": "ErrorAccessDenied",
"innerError": {
"date": "2016-06-07T08:47:27",
"request-id": "5b629e30-e6bd-474d-b3dd-8ce25c5ad1c4"
},
"message": "Access is denied. Check credentials and try again."
}
}
The flow/URLs you've referenced are for the authorization code flow which leverages delegated scopes.
A) If you want the app to only work (i.e. access all calendars) for admins then you are using the right flow.
B) If you want the app to work for all users after the admin consents to it, you'll need to use the app (client credentials) flow and use application scopes. This means that you'll need to separate out consent from the regular auth flow.
For consent you'll need to to point the admin to the following url:
GET https://login.microsoftonline.com/common/oauth2/authorize?resource=https://graph.microsoft.com/&client_id=<YourClientId>&client_secret=<YourClientSecret>&response_type=code&redirectUri=<YourRedirectUri>&prompt=admin_consent
For auth flow you'll need a single call from your web server:
POST https://login.microsoftonline.com/common/oauth2/token
body resource=https://graph.microsoft.com/&client_id=<YourClientId>&client_secret=<YourClientSecret>&response_type=code
Or better yet, just use ADAL's AquireToken(resource, clientCredentials) overload.
Once that's done, your app should be good to go to make requests to Graph.
Regardless if you want to stick to A) or switch over to B), to double check that things are set up correctly you can:
Check the token that you get back from Graph (the one you attach to the request along with Bearer) and confirm that it has a roles entry with the roles you need i.e. Calendars.Read
NOTE: The following steps 2.a & 2.b require you to have admin to a test tenant where you'd be consenting to the application.
2.a Use GraphExplorer (https://graphexplorer2.azurewebsites.net/) and confirm that consent has been properly set up by querying
beta/servicePrincipals?$filter=displayName eq '[YourApplicationName]'
If nothing shows up, then the no one has consented to the application.
2.b (only applicable for auth code flow with delegated scopes) Use GraphExplorer and confirm that either delegation has been authorized correctly by querying
beta/oauth2permissiongrants?$filter=clientId eq '[IdFrom ServicePrincipal in 2.a]'
And ensuring you get either a result for the specific user in question or for "AllPrincipals".
More info on app vs delegated scopes here: http://graph.microsoft.io/en-us/docs/authorization/permission_scopes
More info on app flow here: https://graph.microsoft.io/en-us/docs/authorization/app_only
Please use the app-only auth flow (see https://graph.microsoft.io/en-us/docs/authorization/app_only) to use the application permissions - for the token request (step 4) you need to pass grant_type=client_credentials instead of grant_type=authorization_code.

how to get an access token from wunderlist using OAuth2

How do you get an access token from the wunderlist api using oauth?
The wunderlist documentation says:
Wunderlist redirects back to your site
If the user accepts your request, Wunderlist will redirect to your redirect_uri with a temporary code in a code parameter as well as the state you provided in the previous step in a state parameter. If the states don't match, the request has been created by a third party and the process should be aborted.
Exchange code for an access token:
POST https://www.wunderlist.com/oauth/access_token
I do not understand
Exchange code for an access token
am I supposed to redirect to https://www.wunderlist.com/oauth/access_token to get an access token?
Exchanging the code for an access_token is done by executing an HTTP POST message to the token endpoint, in your case to https://www.wunderlist.com/oauth/access_token, with JSON data as specified in: https://developer.wunderlist.com/documentation/concepts/authorization. Using cURL it would look like:
curl -H "Content-Type: application/json" -d '{ "code":"<CODE>", "client_id": "<CLIENT_ID>", "client_secret": "<CLIENT_SECRET>"}' https://www.wunderlist.com/oauth/access_token

how to get my twitter timeline entries

I have tried this and that.
But requesting this:
https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=monyetbego
keep giving me Bad Authentication data.
I don't know exactly how to get authenticated.
You need to register an application through Twitter's developer site. Once your application is approved you will be given a set of Oauth keys, which you can use within an API request to receive a response. Note that in API V1.1, you can no longer submit unauthenticated requests (i.e. send requests through a unauthenticated URL like the one you posted).
For example, once you have your authentication information, you can use curl to submit a show_timeline request (see your Application's OAuth tool on the Twitter Dev website for parameters specific to your authentication information):
curl --get 'https://api.twitter.com/1.1/user_timeline.json' --header 'Authorization: OAuth
oauth_consumer_key="XXXXXXXXXXXXXXXX", oauth_nonce="XXXXXXXXXXXXXXXXXXXXXXXX",
oauth_signature="XXXXXXXXXXXXXXXXXXXXXXXXXXX", oauth_signature_method="XXXX-XXXXX",
oauth_timestamp="XXXXXXXXXXX", oauth_token="XXXXXXXX-
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", oauth_version="1.0"' --verbose

Resources