Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Microsoft OAuth2 Authentication Not Returning Refresh Token

I am adding Microsoft OneDrive support to a product that my employer sells to other companies. When I went through my designing and prototyping stage, I was using an application ID that waw obtained through an application registration that I did using my personal account. Now, I'm working on actually adding the code into our product and am using an application ID that was obtained through an application registration that was done (by someone else) through our corporate Office365 account.

I am experiencing a difference in the results of the authentication queries between these two application registrations. I'm trying to track down the cause and I'm hoping someone here can help.

When I used the registration from my personal account, I was receiving all the data items from the /token url that were documented in the Microsoft online documentation. When I switched over to use the registration from our corporate account, changing nothing in the code except the application ID, I do not get the refresh_token value. I was using the same login credentials for both tests.

Here's the information when using my personal registration:

Url: https://login.microsoftonline.com/common/oauth2/v2.0/token

Request Body: grant_type=authorization_code&client_id={XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}&code=XXXXXXXXXXXXXX...XXXXXXXXXXXXXXXX

Request Response:

{
  "token_type":"Bearer",
  "scope":"https://graph.microsoft.com/files.readwrite.all",
  "expires_in":3599,
  "ext_expires_in":0,
  "access_token":"XXXXXXXXXXXXXX...XXXXXXXXXXXXXXXX",
  "refresh_token":"XXXXXXXXXXXXXX...XXXXXXXXXXXXXXXX"
}

Here's the information when using our corporate registration:

Url: https://login.microsoftonline.com/common/oauth2/v2.0/token

Request Body: grant_type=authorization_code&client_id={YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}&code=YYYYYYYYYYYYYY...YYYYYYYYYYYYYYY

Request Response:

{
  "token_type":"Bearer",
  "scope":"https://graph.microsoft.com/files.readwrite.all",
  "expires_in":3599,
  "ext_expires_in":0,
  "access_token":"YYYYYYYYYYYYYY...YYYYYYYYYYYYYYY"
}

Other than the values for client_id and code, the only thing that is different is the application registration (one using a personal account and the other using a corporate Office365 account). What could be the cause of this? Is there something missing from the registration through our corporate account?

I don't have permissions to view the corporate registration, so I can't compare what they put it versus what I had in my personal registration. I gave them all the pertinent information, but I don't know if they did everything I asked.

like image 367
ke4ktz Avatar asked May 09 '17 13:05

ke4ktz


People also ask

How do I get a new refresh token OAuth2?

Because OAuth2 access expires after a limited time, an OAuth2 refresh token is used to automatically renew OAuth2 access. Click the tab for the programming language you're using, and follow the instructions to generate an OAuth2 refresh token and set up the configuration file for your client.

Can not get refresh token?

Go to the page showing Apps with access to your account: https://myaccount.google.com/u/0/permissions. Under the Third-party apps menu, choose your app. The next OAuth2 request you make will return a refresh_token (providing that it also includes the 'access_type=offline' query parameter.

Does refresh token expire in OAuth2?

By default, access tokens are valid for 60 days and programmatic refresh tokens are valid for a year.


2 Answers

The Microsoft documentation is quite unclear. Their online services have gone through many iterations and this results in quite a bit of residual data lying around. When I revoked access to both applications from within Office365 and re-authenticated both of them from scratch, both calls were absent the refresh_token value in the response from the /token call.

I managed to put together the pieces from the Microsoft and OpenID documentation to find the answer. In the initial authorization request, the call to https://login.microsoftonline.com/common/oauth2/v2.0/authorize, adding offline_access to the scope query string parameter resolved the issue.

Nothing needs to be added or changed on the app registration side. When this new scope is added, the user will also be shown that the application is requesting access to the data offline. This sequence of steps turns on the return of the refresh_token value. Why it was there in the first place, without specifying offline_access still remains a mystery.

like image 91
ke4ktz Avatar answered Sep 20 '22 10:09

ke4ktz


2019 Update

First of all, thanks to ke4ktz (the accepted answer), worked perfectly.

However, I did not know initially how to add offline_access to the scope :) so in case someone has the same issue, you just add it after your scope string with space so let's say your scope was "Sites.FullControl.All" so now it will be "offline_access Sites.FullControl.All".

The reference from Microsoft can be found here

I hope it helps

like image 21
Abhay Maurya Avatar answered Sep 23 '22 10:09

Abhay Maurya