Why is Microsoft Oauth2 API changing the scope of authorization requests? - oauth

I'm creating an application which needs to request user authorization from a Microsoft Work account. And stumbled into this twice.
At first, I just wanted to read the user e-mail, so I requested the following scopes:
User.Read
Mail.Read
Mail.ReadWrite
Mail.ReadWrite.Shared
Mail.Read.Shared
However, I kept getting "scope has changed" errors, and noticed that the authorized response from microsoft was automatically including the Mail.Send scope to the requests, even if I didn't request it and it was not present on the authorization web page.
My users don't care about that extra auth, so I just added Mail.Send to my request and moved on. Fine.
I am now required to include the offline_access to the scope list, so I can get Refresh Tokens and keep the app running in background. But when I do it, Microsoft replies me with an authorization request missing the 'offline_access' grant, even if the authorization page showed "Access your data offline" and no errors occur during authentication, yet my Oauth2 flow is broken with a "scope has changed" error:
Scope has changed from "mail.readwrite mail.read.shared mail.read
mail.readwrite.shared mail.send offline_access user.read" to "mail.readwrite
mail.read.shared mail.read mail.readwrite.shared mail.send user.read"
So is this a bug in Microsoft Oauth flow, or am I doing anything wrong?
EDIT: I reviewed the application permissions on https://apps.dev.microsoft.com/ and the 'offline_access' scope is not listed there, or any other scope seemingly related. Maybe this means Graph does not yet support that scope, despite it being heavily documented?

I found this issue annoying as well. Read on if you are using Python & oauthlib to process the authentication request -
In Python 3 and requests_oauthlib library this generates a Warning, rather than an Exception. If you see the source code then you will find these lines in oauthlib/oauth2/rfc6749/parameters.py:
if not os.environ.get('OAUTHLIB_RELAX_TOKEN_SCOPE', None):
w = Warning(message)
w.token = params
w.old_scope = params.old_scopes
w.new_scope = params.scopes
raise w
So all you have to do is set the OAUTHLIB_RELAX_TOKEN_SCOPE variable to True in your environment, to ignore this warning.

There is file /lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py.
[1]
As you can see in the image there is an environment variable "OAUTHLIB_RELAX_TOKEN_SCOPE". Just add this to your environment with value 'True' or 1.

Related

Cas 6.1.x OAuth client_credentials with scope

It does not appear that I can setup scope in a service config for grant_type of client_credentials.
Is this possible? When requesting a token, I do get back an empty "scope" value. The only way I can get a value to appear is if I pass a query parameter of &scope=foobar. But this does not make sense that the client application is setting the scope.
I want to grant a token with permission to read from API1 and write to API2 but not read/write to API3. It seems I should be able to have a config as scope: [ "java.util.HashSet", [ "api1_read", "api2_write" ] ] basic on clientId config on the cas authorization server.
Then I would image that the resource service, when validating the token would also get a list of scopes allowed.
What am I missing?
You are not missing anything. This capability does not exist and could possibly be added to CAS 6.3 assuming time and sponsorship would be available. Support for scopes are only available as of this writing for OpenID Connect. For OAuth, they would need to be added to the codebase and released.

Is it possible to obtain a Mail.ReadWrite scope access token from the microsoftonline oauth2 endpoint using grant_type=password?

I have an application registered with https://apps.dev.microsoft.com with Microsoft Graph Permissions including: Mail.ReadWrite, Mail.ReadWrite.Shared, and User.Read. Ultimately, I need to read mail and move it to other folders using a daemon task. I am using the Microsoft OAuth2 endpoint to obtain an access token using grant_type=password. This call is working in that I get back a token with scope=Mail.Read, but I need Mail.ReadWrite. Is it possible to obtain a Mail.ReadWrite token using grant_type=password?
My call looks like this:
resource=<myresource>&client_id=<myclientid>&grant_type=password&username=<myusername>&password=<mypassword>&scope=openid
I have also tried altering the scope to include Mail.ReadWrite, but that does not seem to work.
I managed to get this working. After editing permissions for the application, there must have been a window of time where the settings did not yet take effect. I manually signed into my app a few more times and was eventually prompted to accept the new permissions. The next time I made the OAuth request, I got back a Mail.ReadWrite token.

Using immediate=true in Salesforce OAuth flow

Previously asked this question in the Salesforce StackExchange which they considered off-topic so asking here to see if I can get an answer.
Background
I am attempting to use the immediate parameter to check if a Salesforce user has already approved access when going through the Web Server OAuth Flow as documented on OAuth 2.0 Web Server Authentication Flow. My reasoning for this is that I do not want the login or consent prompts to appear so I can reject access if they have not already approved.
Once the callback page is hit, I am always receiving the parameter error=immediate_unsuccessful even if the user has approved the application before and is logged in.
I have attempted to check this via a customised Google OAuth 2 Playground and setting immediate=true or immediate=false to the end of the authorize endpoint. On =false, the consent prompt shows and then you can grant access. On =true, this returns the same error as listed previously.
The Connected App that has been set up has api and refresh_token as the available scopes, users are able to authorize themselves and there are no ip restrictions set. The client id and secret from this app is then passed into the OAuth 2 Playground.
Below is a brief example on how my proper application redirects to the auth url using Java and the Google OAuth client library. We initially authorize the client without the immediate and then later on call the same code with immediate=true (shown in example)
AuthorizationCodeFlow authorizationCodeFlow = new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(),
httpTransport,
GsonFactory.getDefaultInstance(),
new GenericUrl("https://login.salesforce.com/services/oauth2/token"),
new ClientParametersAuthentication(CLIENT_ID, CLIENT_SECRET),
CLIENT_ID,
"https://login.salesforce.com/services/oauth2/authorize")
.setCredentialDataStore(StoredCredential.getDefaultDataStore(MemoryDataStoreFactory.getDefaultInstance()))
.build();
AuthorizationCodeRequestUrl authUrl = authorizationCodeFlow.newAuthorizationUrl()
.setRedirectUri("https://72hrn138.ngrok.io/oauth/callback")
.setScopes(ImmutableSet.<String> of("api", "refresh_token"))
.set("prompt", "consent")
.set("immediate", "true");
response.redirect(authUrl);
Question(s)
Are there any settings that I may have missed in Salesforce that would alleviate the error?
Is there any other option in the OAuth 2 spec that has to be set for the immediate option to work?
Does the immediate setting work?
I managed to solve this issue in the end. To allow the immediate=true option to work, the scopes have to be removed from the request. In the example provided you would amend the authUrl to the following:
AuthorizationCodeRequestUrl authUrl = authorizationCodeFlow.newAuthorizationUrl()
.setRedirectUri("https://72hrn138.ngrok.io/oauth/callback")
.set("prompt", "consent")
.set("immediate", "true");
I believe the theory is that defining a scope means you are asking for permissions to use those scope and therefore requires approval for those permissions. This clashes with the immediate option which states that the user must be logged in and the client id already been approved for it to succeed.

Instagram API: do scopes work with OAuth2 implicit authentication flow?

I'm making requests against the Instagram API from a mobile app. Currently, I'm just directing the user to the Instagram auth url and specifying the response type to be "access_token". Specifying this response_type is known as implicit auth.
Explicit auth: response_type=code
Implicit auth: response_type=access_token
I'm trying to get around needing to stand up a web service to facilitate explicit auth. This would be necessary because in explicit auth flow, the Instagram API needs to make a call to a redirect URL and pass in a "code" parameter. The code would then be used by my server-side code to make a final request to Instagram for an access token.
It's much more efficient for a mobile app to use implicit flow because no extra privately-maintained auth service needs to be stood up to handle it.
Instagram supports the following scopes:
basic - to read any and all data related to a user (e.g.
following/followed-by lists, photos, etc.) (granted by default)
comments - to create or delete comments on a user’s behalf
relationships - to follow and unfollow users on a user’s behalf
likes - to like and unlike items on a user’s behalf
When I make any other type of scope specification besides "basic", I get the following response when the user provides the credentials at the auth URL:
{"code": 400, "error_type": "OAuthException", "error_message": "Invalid scope field(s): basic+likes"}
Any combination of scopes other than "basic" gives the same response.
So, my question are these:
Is explicit auth required in order to specify scopes beyond "basic"??
Do I need to specify response_type=code in order for extended scopes to work?
Is this an Instagram limitation, or is it a limitation of OAuth 2.0?
Thanks in advance.
I just tried with implicit oauth flow with my client_id and scope=basic+likes and it worked. Replace the url below with your client_id and redirect_uri, and try.
https://instagram.com/oauth/authorize/?client_id=CLIENT_ID&redirect_uri=REDIRECT-URI&response_type=token&scope=basic+likes
May be Instagram is not allowing scope other than basic with new client accounts...
The answer here is that YES, scopes can be requested by implicit auth flow just fine. My problem was related to an OAuth component that I was using. The component was silently URL-encoding the value of the scope param, which was rejected by the Instagram auth endpoint. I updated the component (Xamarin.Auth) to accomodate a non-encoded scope param and issued a pull request.
Thanks to #krisak for providing a working URL that I could test.
So I had similar issues regarding the encoding of the + when trying to get permission for multiple scopes (basic, likes, comments). The solution I found was to use spaces between the individual scopes:
In the config/initializers/omniauth.rb file:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :instagram, 'TOKEN', 'SECRETKEY' , {:scope => "basic likes comments"}
end
Unfortunately starting from April 14th 2015 new clients cannot get access for any scope but basic. Official message could be found at the client configuration page:
Starting April 14th 2015, new clients need to request access to be able to post likes, follows, and comments. For more information please read the Developer Blog at http://developers.instagram.com.
The message refers following blog entry: http://developers.instagram.com/post/116410697261/publishing-guidelines-and-signed-requests
Instagram requires personal request to be sent to enable scopes for your application (client ID), but your app has to meet certain conditions described in the blog entry.
i have the same problem i found this solution and works fine
Go to Manage clients under instagram/developer. Then click edit under your app and uncheck Disable Implicit OAuth. It will now work as intended.
Instragram changed this for a reason though, so should probably think twice before going public with your app: http://instagram.com/developer/restrict-api-requests/
At this time, May 2015, YES.
As explained on instagram documentation about authentication:
The Instagram API uses the OAuth 2.0 protocol for simple, but
effective authentication and authorization. OAuth 2.0 is much easier
to use than previous schemes and developers can start using the
Instagram API almost immediately. The one thing to keep in mind is
that all requests to the API must be made over SSL (https:// not
http://).
You first need to register your app here and then, with CLIENT ID provided by instagram, you can do this request:
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code
Where you have to put your client_id and redirect_uri.
Just for information, in redirect_uri field you can insert also
http://localhost
you must be add "+" between scopes like that is "basic+comments+follower_list+likes+public_content+relationships"

Revoking OAuth Access Token Results in 404 Not Found

I'm working on an application that integrates with GitHub and am having issues "logging out" a user that was previously authenticated. When I attempt to revoke the authorization token for the user, I get a 404 Not Found response from the API.
According to the documentation, it looks like I should just be able to make a DELETE request to https://api.github.com/authorizations/[authTokenId]. I have tried a couple of different things including:
Ensuring the Authorization header is set with the current auth token
Ensuring the UserAgent header is set with what I use for the rest of the API calls
Nothing seems to result in anything but a 404 though. I have validated that the token is valid and has that the Id matches with what is expected (id property from the authorization response and from the "check an authorization" response as well). Anyone have another thought on something I could be missing?
Looks like currently you need to include a basic authentication header (including a base64 encoded string of your username/password).
Not ideal for my purposes since I want to revoke the token when a user "logs out" of my application and I don't want to store their username/password. I've sent GitHub support an email about it to see if they have any other ideas.
Update 6/12/2013
GitHub support has stated that the above is expected at this juncture, but they are considering updating to allow revoking an authorization using the authorization as the means of authentication.
For now I'm going to require the user to enter their username/password a second time to revoke the authorization.

Resources