Use of OAuth 2.0 with Exchange Web Services - oauth-2.0

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>

Related

Microsoft Graph API Logic App Authentication

I am having a difficult time getting a Microsoft Graph API call to work. Specifically, I am having a hard time with the authentication process working. I followed the directions in this article
http://martink.me/articles/using-microsoft-graph-in-logic-apps
However, when I make the api call of https://graph.microsoft.com/v1.0/me/messages/{id}, I get the error:
Current authenticated context is not valid for this request. This occurs when a request is made to an endpoint that requires user sign-in. For example, /me requires a signed-in user. Acquire a token on behalf of a user to make requests to these endpoints. Use the OAuth 2.0 authorization code flow for mobile and native apps and the OAuth 2.0 implicit flow for single-page web apps.
I then added an oAuth token call to get a token. Then I used that token in the Authorization header when making the Microsoft Graph Api call. I still get the same error.
Can anyone provide guidance on how best to make an Graph Api call in LogicApps? Do I only need the authentication discussed in the article? Or, do I need to call the Graph Api with an Authorization token? Do I need to make an oAuth authorization call before I make the oAuth token call?
This exception is caused by the token acquired using the client credentials flow. In this flow, there is no context for /Me.
This type of grant is commonly used for server-to-server interactions that must run in the background, without immediate interaction with a user(no user logged in).
For your problem, you are using client credential flow and you are granting application permissions, so you should request /users.
GET https://graph.microsoft.com/v1.0/users/{id | userPrincipalName}/messages/{id}

Outlook add-in Rest Api token to get the SharePoint Rest Api Token

I am building a Outlook Add-in using Node JS and it needs get information from SharePoint Online using SharePoint Rest Api because Graph does`t have an option to get the required information.
Question?
I need a SharePoint online auth token to call SP Rest Api which I am getting using OAuth flow (implicit flow) after user enters credentials.
Is there a way to get the SharePoint online auth token using Outlook Rest Api returned by getCallbackTokenAsync() or getUserIdentityTokenAsync() or "getAccessTokenAsync()" method?
if you only need the SharePoint REST API Token (I assume you mean the one with URLs starting with _api/[...]) then your best bet is to get that token from the /_api/contextinfo endpoint for your site. You do not need the Outlook REST API to do so if I understand the question correctly. So you need to craft a POST request to:
http://yourspsite/_api/contextinfo
Headers:
accept: application/json
content-type: application/json
Get the token value from the returned JSON: e.g. jsonResponse.FormDigestValue
The FormDigestValue field contains the value you want.
There ya go, hope this helps.
Cheers,
Razvan
UPDATE regarding NodeJS in Outlook Add-in:
As you correctly pointed out I left out the requirement that the token be obtained from within the Addin itself. This is currently only possible from within SSO addins (preview). See the following link for how to implement it and use getAccessTokenAsync to get an Azure AD V2 token: https://learn.microsoft.com/de-de/office/dev/add-ins/develop/sso-in-office-add-ins
Make sure to have created the AzureAD V2 App beforehand using https://apps.dev.microsoft.com
Give the app the necessary permissions for the operation e.g. Sites.Read.All for reading items in all site collections.
The resource for the token should look like:
https://[yourtenant].sharepointonline.com/
Caveat: To create an SSO Addin you currently need to be part of the Office Insider Program at: https://products.office.com/de-DE/office-insider - signup required.
Finally: Use the token to call the regular SharePoint REST API, it should accept it if you stick to operations within the permissions you set in the Azure App above.

Can an MS Graph Bearer Token be used to access the Office REST API?

We've implemented Authentication in a .Net Core 2.0 app using Microsoft Graph to authenticate against Azure AD.
That works fine and we were aiming to use Microsoft Graph for accessing Office 365 data.
Unfortunately, on deeper review, we've found that Tasks are currently unsupported via Microsoft Graph and must be instead accessed via the Outlook REST API.
Important: APIs under the /beta version in Microsoft Graph are in preview and are subject to change. Use of these APIs in production applications is not supported.
I tried passing the Bearer Token retrieved via Microsoft Graph in the Outlook REST API headers but I get back an invalid token error.
I'm hoping that I'm simply doing something wrong and this is a valid approach.
Since MS Graph is the "unified" replacement for the Outlook REST API and others, can a Microsoft Graph token be used to access the Outlook REST API?
Yes, this is correct behavior. Tokens are only valid for a particular "audience", which is indicated by the aud claim inside the token.
If you obtained a token for the Microsoft Graph API, then the aud parameter would be set to https://graph.microsoft.com. This doesn't match the Office 365 API endpoint (https://outlook.office.com or https://outlook.office365.com), so the token validation fails. You have two options here.
Use the tasks APIs in Graph even though they are in beta.
Make sure that you obtain a refresh token when you request your Graph token (by including the offline_access scope in your auth/token requests). Then use that refresh token to obtain a second token with the proper audience.
You can use the refresh token to request an Office 365 API-compatible token by qualifying your scopes in the refresh request. For example, if you requested a Graph token with Tasks.Read, you would qualify Tasks.Read in your refresh request as https://outlook.office.com/Tasks.Read.
Just want to share how you can exchange Graph RefreshToken to a Outlook AccessToken using postman. (You can do this in whatever code language you wish)
First lets show how you use a RefreshToken to get a new Graph AccessToken:
Then use the Graph RefreshToken to get the new Outlook AccessToken:
Hope this might help some other people :)

Getting Access Token for Microsoft Graph from asp.net core2 Authentication web app

I have created a new asp.net core 2 web application. I'm using individual user accounts and added my Microsoft account for external authentication. All of this works like expected.
Now I want to use Microsoft Graph to read my .live profile and eventually read my mailbox and things like that.
I created an authentication provider and I'm able to get an access token back but why I try to use the access token, I'm getting an Authorization_IdentityNotFound error although my clientId and secret is correctly entered.
I think it's caused by the fact that I'm not using the proper parameters to request the access token. I think I'm missing the authorization response code that is normally returned when I sign into my .live account.
Does anyone know how to retrieve that response code or has a working example in asp.net core2. The only sample I can find is in .net core 1.1 and things have changed rather drastically since then.
You're confusing a few different systems here.
In order to access Microsoft Graph API you'll need to pass an Access Token in the authorization header of your call. This is used to both provide Microsoft Graph with your identification as well where you're data is stored (you're tenant).
The actual Access Token isn't issued by Microsoft Graph, it is issued by your tenant. For work/school accounts this is the Azure Active Directory tenant where your account lives. For personal account this is the Outlook.com tenant.
Prior to receiving an Access Token, you first retrieve an Authorization Code. This is returned to the redirect_url you passed to login.microsoftonline.com after you've entered your credentials. Your app then takes this Authorization Code and exchanges it for an Access Token that you'll use to call Microsoft Graph.
If you're looking for a authentication library to handle this process, you should use MSAL.NET. You can find instructions for using this library in the microsoft-authentication-library-for-dotnet repository on GitHub.
Once you have a token, you can either call Microsoft Graph directly or you can leverage the Microsoft Graph Client Library for .NET.

OAuth 2.0 Single-use Access Token for unauthenticated user via IdentityServer4

I apologies in advance for incorrect use of oauth terms.
I have 4 "parties" as follows (intentionally not using oauth terms where possible):
End-user in a browser (javascript)
Our website (aspnet)
Our web api (aspnet)
Our auth server (aspnet utilising identityserver 4)
My usage scenario is that we only want the API to be called by a browser that has requested a page from the website first. Whilst the API doesn't release sensitive information, we would like to introduce a layer of complexity with regards to the API being spammed.
Our end user's will not be logged in.
I imagine such a flow being akin:
Browser requests a certain page from the website (one that will likely lead to js making an api call)
Website requests token from auth server
Auth server verifies token request came from website (the server itself)
Auth server returns a token to the website
Website returns page including the access token
Browser is able to make a request to api using token
Although convoluted, I believe this is at least similar to the Client Access Grant flow?
These tokens could then be throttled either by website or auth server.
Yes, I'm aware that this doesn't protect the api from numerous other vectors, but it does eliminate the simplest of cases which is all we're looking to achieve for now. I'll add, I didn't define this requirement, I'm simply trying to find a way to achieve it utilising techs out there instead of making the mistake of rolling anything of my own.
Could someone confirm/deny that there is an oauth flow I could use here? Any sample projects using the given flow and IdentityServer?
IdentityServer3 / non-aspnet[core/5] examples are fine, I can translate.
What you describe is the Client Credentials Grant where your website (client) gets an access token from identityserver (auth server). That access token can then be used to call endpoints on your web API (resource server).
The token is a bearer token and can be used by anyone who has it, so if you are comfortable with your website passing it back to a browser on an HTTP response, then it will work just fine.
I'm not sure what you mean by throttling the tokens - once minted they are valid for their lifetime. I guess you can keep the time-to-live very short to achieve the single usage you want though.

Resources