Successfully using the graph endpoint with Azure AD v2 authentication. All working perfectly.
Graph endpoint does not support outlook tasks so need to use the outlook api endpoint outlook.office.com/api.
Am establishing scope at authentication with scope parameter. Using identical code, just different endpoint e.g.
https://graph.microsoft.com/beta/me/messages - works
https://outlook.office.com/api/beta/me/messages - 401 Unauthorized
What am I missing? What does outlook.office.com need different from graph endpoint to work?
Outlook and MS Graph are related but different services. You cannot interop tokens between the two services. You should get different tokens for each service with proper scopes for each one of them.
Resolved this and answer posted here for anyone else looking.
Graph accepts unqualified scopes e.g. Mail.Read Mail.Send but these do not work for outlook.office.com/api which requires scopes to be qualified with endpoint i.e. https://outlook.office.com/mail.read
It is the qualified scopes that makes a token not interoperable across endpoints i.e. scope requested is for graph or outlook.office.com
Related
I am using Microsoft Graph API and Microsoft Dataverse Web API in a single applications. Due to this, I have to get 2 different access tokens for each by addding different value of resource key. Is it possible to generate a single token that can be used for both ?
This might also be achieved through RefreshToken to get an AccessToken to the individual endpoints with the same scopes as authorized when you requested the graph access (scopes).
E.g. If you requested Mail.Read (https://graph.microsoft.com/mail.read) you can get back to the token issuing endpoint with the refresh_token with scope="https://outlook.office.com/mail.read" and get an accesss_token for this endpoint.
you can use the On-Behalf-Of Grant to exchange the token with a new one, only this time addressed for the resource you need. Please refer this Document.
Could anyone explain how a MSFT Oauth2 client scope with a URI of https://outlook.office.com (needed for SMTP AUTH or IMAP, for example) can be specified in a corresponding AAD permission when outlook.office.com is not listed in the resource API list ?
MSFT push Graph (which does have e.g. an SMTP AUTH permission), but they have confirmed that SMTP AUTH and IMAP are implemented only in the outlook resource API. Testing confirms this: if the client uses a scope of https://graph.microsoft.com/SMTP.Send and an AAD Microsoft Graph permission of SMTP.Send, authentication fails. The acid test lies is the ‘aud’ claim in the Access token: if it is “00000003-0000-0000-c000-000000000000” (aka Graph) authentication fails whereas an ‘aud’ of https://outlook.office.com will succeed (other things being equal).
I would have thought naively that the client scopes and AAD permissions resource API should have the same URI.
I can’t see how granular permissions – where the AAD permissions are a superset of the client’s scopes and clients ask for the minimum they need at the time they need it – can work if I cannot specify the superset in AAD!
I have asked MSFT for enlightenment but no response.
=====
Additional tests:
If AAD Graph permissions are null and the client scope is just https://outlook.office.com/SMTP.Send, the access token has an ‘aud’ of https://outlook.office.com and an ‘scp’ of SMTP.Send, and authentication is OK.
But if the client scope also contains a Graph scope such as Mail.Send, ‘aud’ changes to 00000003-0000-0000-c000-000000000000 (aka Graph) and subsequent authentication fails with ‘incorrect credentials’. I would have expected a “scope asking for one token for two different resources” type error message from the token endpoint.
And, as would be expected, if the client scope is just SMTP.Send (or https://graph.microsoft.com/SMTP.Send; the Graph URI prefix being now the default) authentication fails with ‘incorrect credentials’
These are using the V2 authorisation and token endpoints – as recommended by MSFT.
====
Further comments in response:
#Allen Wu - I cannot find IMAP.AccessAsUser.All, POP.AccessAsUser.All and SMTP.Send listed under Exchange (API permissions => + Add a permission => Request API permissions /Microsoft APIs => Exchange or under Office 365 Exchange Online (API permissions => + Add a permission => Request API permissions / APIs my organization uses => Office 365 Exchange Online) . They are only listed under Graph. This leads to the weird situations that:
if a client uses (e.g.) SMTP.Send (or https://graph.microsoft.com/SMTP.Send) scope, authentication fails even though MSFT instruct (vide your last link) that the corresponding permission must be registered in Graph
if a client uses (e.g.) https://outlook.office.com/SMTP.Send scope (as instructed by MSFT), the client cannot add further https://outlook.office.com permissions (because the resource API is not listed) or use additional Graph scopes (because authentication fails and it would appear to be asking for one token to cover two APIs anyway)
Vide your comment “We see that the permissions are under Microsoft Graph in the Azure portal, but in fact the same has been added to the outlook endpoint”, MSFT could pre-empt much confusion (other StackOverflow posters have logged similar problems) if they simply listed the outlook.office.com API in AAD API permissions until Graph accessed a complete set of endpoints as well as permissions. I realise they want developers to use Graph, but the present situation is akin to being half-pregnant!
In this case, you just need to select the Microsoft graph permissions (SMTP AUTH or IMAP).
Currently when you need to get an access token, you can specify the scope as https://outlook.office.com/{SMTP AUTH or IMAP permission}.
I think the permissions are still in change. The Outlook permissions should be included in Microsoft Graph in the future.
I would like to get some clarification on whether or to what degree OAuth 2.0 can be used with EWS applications. Here is my situation: I maintain an application that accesses Office 365 data. It uses EWS with Basic authentication. In response to the plan to no longer support Basic authentication and to deprecate EWS, I developed a new version of the application that uses Microsoft Graph and OAuth 2.0. I had no problem getting OAuth to work. However there are still some significant shortcomings in Graph (for our needs) so what I would like to do now is support OAuth in our original EWS application.
My hope was that I could just take a token generated in the same way I do in the Graph application, and feed it into my EWS calls in the "Authorization: bearer ..." header of the http call. (I am not using the EWS managed API or any kind of authentication library, just making direct http calls using libcurl). Unfortunately this results in http error 401 Unauthorized.
Here is how I am obtaining the token:
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
with data:
client_id={client_id}&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret={client_secret}&grant_type=client_credentials
This produces http 200 and a returned token:
eyJ0eXAiOiJKV1QiLCJub25jZSI6...
As I said, using this token in the Authorization header of the EWS call fails with http 401. However, using the same token with a Graph call works. I did try replacing the scope with ""https://outlook.office365.com/.default" but it produced the same results.
I have looked at the API permissions granted to my application in the Azure portal. They are all of type Microsoft Graph. I don't see any "EWS" permissions available to request. Could this be my problem?
Any help on this issue will be appreciated, thank you.
Update: I did go ahead and add all the "Legacy Exchange" API permissions, and re-authorized my test tenant for the application. Still no luck. I am trying to execute the "GetFolder" EWS API. Only the graph.microsoft.com scope works to get a token, so maybe that needs to change?
I would suggest you start with https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
For EWS if you are using the Client Credentials grant (which is what you using in you example) then the only permission that will work is the full_access_as_app which is under the legacy Exchange Application permissions. The scope you need to use is https://outlook.office365.com/.default . You can check the token your generating in https://jwt.io/ . Eg the Audience should be for outlook.office365.com and the scope should have full_access_as_app.
The one last thing you need to do in your EWS code is to include the EWS impersonation header set to the Mailbox you want to impersonate (or access) eg
<soap:Header>
<t:ExchangeImpersonation>
<t:ConnectingSID>
<t:PrimarySmtpAddress>alisa#contoso.com</t: PrimarySmtpAddress>
</t:ConnectingSID>
</t:ExchangeImpersonation>
</soap:Header>
On a project, I'm using app-only tokens and Graph API to perform various operations on data in Office 365 (this is how the app is registered). When it comes to SharePoint, certain operations are not available through the Graph API but are available through SharePoint REST API.
My question is: is there a way to use Graph API tokens with SharePoint REST API?
The closest answer I could find is this:
To access the http:///site/_api/lists endpoint, Graph API token wont work.
Taken from here.
However, the answer is about a specific endpoint and is pretty old, so I wonder whether this is (still) true.
Update
Here's how I'm calling the various endpoints.
The token you are using to access the graph is in fact an azure active directory token. Lots of other APIs accept those in office 365.
The procedure is more or less the same expect instead of selecting the Microsoft graph API when requesting the scopes, you have to select the SharePoint API.
Also note that some actions (mostly the tenant related things) do require you to present a token generated with a client id + certificate and not client id +secret.
EDIT: if you are using AAD v2 endpoints the requested scope has to be https://tenantName.sharepoint.com/.default when requesting an access token for SharePoint REST API
According to this documentation, the on-behalf-of flow is not supported in B2C:
Web API chains (On-Behalf-Of) is not supported by Azure AD B2C.
Many architectures include a web API that needs to call another downstream web API, both secured by Azure AD B2C. This scenario is common in native clients that have a web API back end, which in turn calls a Microsoft online service such as the Azure AD Graph API.
This chained web API scenario can be supported by using the OAuth 2.0 JWT Bearer Credential grant, otherwise known as the On-Behalf-Of flow. However, the On-Behalf-Of flow is not currently implemented in Azure AD B2C.
Can't I just pull out the JWT from the first Web API request and pass it along to the next Web API? I know technically, I can, but is there a reason I wouldn't want to?
This approach would only work if both Web API's are configured for the same B2C App. Maybe that is the difference. Is the documentation referring to 2 separate B2C apps maybe?
Reference: Access the JWT bearer token when using the JWT middleware in ASP.NET Core
The OAuth 2.0 On-Behalf-Of flow is related to a first resource, "https://resourceserver1", receiving an access token from a client; then exchanging this access token for another access token for access by the delegated identity to a second resource, "https://resourceserver2" without any user interaction; and then sending that access token to the second resource.
This Azure AD documentation explains the On-Behalf-Of flow.
Given this, two different applications are necessary for two different resources, which in turn can require two different scopes.
You can vote for this feature at B2C Support for on-behalf-of flow.