Office 365 vs. Outlook OAuth2 offline_access inconsistencies with refresh_token requests - oauth-2.0

I am developing a web app that is supposed to access contact and other information for users with their Outlook or Office 365 accounts and I am having some issues with offline_access to Office365 accounts.
Upon initial authentication the code works fine and I am able to access all I need for both Outlook and Office 365 accounts.
The inconsistency shows up after the initial access token had expired. For Outlook accounts I can always refresh the access token, while for Office 365 accounts the exact same code fails with "400 Bad Request" error.
It feels like there should be something different done for the Office 365 accounts when refreshing access toke but I cannot figure out what.... I am not even sure how to tell if the users have used Otlook vs. Office 365 account I can figure this out later.
The authority URL I use is https://login.microsoftonline.com/common/oauth2/v2.0/token and I thought that perhaps it should be different for Outlook and Office 365 but everything else appears to be working for both account types except for the refresh_token request.
Appreciate your help!
Thanks!

This is weird but the solution to the problem is in making sure the redirect_url parameter used in the refresh token request matches exactly the registered redirect url including the host name.
Amazingly this is true only for Office 365 accounts and only for refresh token requests. It looks like all other APIs for both Outlook and Office 365 accounts do not care about the supplied redirect URL and use whatever was registered for the app instead.

Related

Microsoft's REST API's

I am working on integrating Outlook's calendar REST API with my personal system.
Using the authorization code grant flow, I am able to get a user to login to an application that I have registered in https://apps.dev.microsoft.com. Once a user has logged in successfully, I receive a code on my redirect URL. Using the code, I fetch his bearer token (basic oAuth code flow).
Now, the confusion is with their documentation. They have 3 types of API, o365, outlook.office and graph. I am using their graph API for the calendar resource.
I'm using https://graph.microsoft.com/v1.0/me/calendarview to fetch events from the primary calendar, https://graph.microsoft.com/v1.0/me/events to create events in the primary calendar and https://graph.microsoft.com/beta/$batch for batch requests.
There are some scenarios that I want to cover here. When a user changes his/her outlook password, I need the user to re-login to the app so I can use a valid bearer token. From outlook documentation, it looks like the refresh token becomes invalid as soon as the user changes the password (search for refresh tokens become invalid); which means, at the worst case, I can use the bearer token for an hour (default) to authenticate the API's.
Is this normal of an oAuth flow? I always thought the bearer token would become invalid when a user changes the password.
Since I am working in an organization, I want my application to only be accessible by AD users in my organization.The application manifest has a field called availableToOtherTenants, which is defaulted to true. I changed the field to false so that only the users belonging to the organization AD can access it. But it looks like I am able to login to the application with my personal outlook account as well; in spite of this change.
What am I doing wrong here? Am I doing the right this by registering
an application in https://apps.dev.microsoft.com?

should office addin sign out O365 Account When it is authenticated base on O365 authentication?

We are publishing an outlook add-in to office store, and this add-in is authenticated based on the O365 authentication, so once customer logins his o365 account, he could go to our service directly via our add-in. The question is whether we sign out the o365 account or not since we have failed for Add-in validation. There are two screenshots:
[Failed if not sign out o365 account]
[Failed if sign out o365 account]
We are a little confused about what we should do next step, could we just keep signing out of O365 account and add a note: we are authenticated by O365 authentication or could we just remove the Signout since our add-in is O365 authentication based?
Thanks very much in advance for your help.
Removing the sign out might not be a good idea, unless you actually don't want that feature available to your users. I guess your problem might be that a session or local identifier is stored on the client and it is automatically being logged in when the add-in opens again when sign-out was pressed ( from what i understand ).
If you are using OAuth 2.0 standard, what you should try: Find the stored session either locally or server side and remove it when the user logs out. Also you could log out the user out with the Microsoft sign-out url see: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-openid-connect-code
If you are using the SSO of Office, what you'd want to do is just remove the local side storage that holds the tokens, and then show the user the log in page ( with a button to log them in again ) for info about SSO see:
https://learn.microsoft.com/en-us/office/dev/add-ins/develop/sso-in-office-add-ins
Goodluck!

Azure AD / Microsoft Graph Tokens - What to use for a multi-client app

I need to be able to monitor a user's Hotmail or Outlook account in the offline mode via a backend. But the user can sign up and authorize the account access either from a web app e.g. Laravel or Lumen or from a Cordova mobile app or another SPA interface such as Angular. Basically, the app is configured on https://apps.dev.microsoft.com for an implicit flow.
Since the app requires a backend offline processing lets say few times a day - I will need a refresh token to renew the access_token. There are two ways to get consent from the Azure AD.
authorize = id_token + token (But the limitation is that id_token is only client specific). This approach is more suitable for fetching the emails when client is running and user is online.
authorize = code and then generate access_token and refresh_token.
Question - would option 2 work for both hotmail/outlook.com and O365? If the access and refresh tokens are generated by the client - would they work for both online and offline access of a user's account and email.
Of course you can. But if you want to receieve a refresh token in token response, your app must request and be granted the offline_acesss scope.
The offline_access scope gives your app access to resources on behalf
of the user for an extended time. On the work account consent page,
this scope appears as the "Access your data anytime" permission. On
the personal Microsoft account consent page, it appears as the "Access
your info anytime" permission. When a user approves the offline_access
scope, your app can receive refresh tokens from the v2.0 token
endpoint. Refresh tokens are long-lived. Your app can get new access
tokens as older ones expire.
REQUEST EXAMPLE:
// Line breaks for legibility only
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&response_mode=query
&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
&state=12345
Actually, if you use code grant flow to sign in AAD, you will see this Page:
If you click Yes, you will consent offline_access scope.NOTE: This works for both MSA and AAD Account.
You can see more details about offline_access sope in this documentation.

Office 365 oAuth verify user is member of organization

I am building a web application for a client and logging in with Office 365 is a requirement for the client. I am having a difficult time deciphering what exactly I need to do to make it so that only users with an email address belonging to their Office 365 organization can authenticate with my app using oAuth.
Is there a way to do this? Or am I going to have to implement the AD 1.0 endpoints? Being able to pull the users' groups and other enterprise-related data would be great but for simplicity's sake, all I really need to do is verify that they are apart of an organization.
How would I do this using the AD 2.0 endpoints?
The tenant id (tid) claim in the identity token would identify which organization (tenant) they belong to. But even easier than just checking the tid for every user would be to use the tenant-specific logon URL. So instead of the /common/oauth2/v2.0/authorize endpoint, use /<tenantid>/oauth2/v2.0/authorize.

office365/azure oauth using delegated user id

My goal is to write some code to enable an Office 365 user to access files in OneDrive for business via REST API. I have registered an application in Azure AD (Web App/single tenant) and have a redirect URI to receive the OAuth token. I want to use the "delegated user identity with OAuth" scenario. To see how it works, I use the "Office 365 OAuth Sandbox" here: https://oauthplay.azurewebsites.net/. When I "Authorize using own account" and enter any valid Office 365 user credentials, I get an access token back. When I replace the client ID and redirect URI in the authorization URL with the info of my registered app, I can only get the token when I enter a user registered in my app (otherwise I get an error 50012 during sign-in). What do I have to change in my configuration to allow any Office 365 user to get an authorization token (like the Sandbox does) ?
You need to mark your web application as multitenant, or Azure AD will constrain all callers to be from the tenant in which you provisioned the application.
Take a look at https://github.com/AzureADSamples/WebApp-WebAPI-MultiTenant-OpenIdConnect-DotNet for an example of a web app that is multitenant and invokes a Microsoft API. Note that you don't necessarily need to validate issues as shown in the sample, just do what makes sense for your scenario (which might mean even not validating).

Resources