Cas 6.1.x OAuth client_credentials with scope - oauth-2.0

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.

Related

Google oauth2Client.getToken is not returning id_token for other users

I'm implementing Google's 'code model' of Oauth2 and having trouble getting users' email - I wonder if this is a scopes problem or my misunderstanding about how to set up the code model. This sequence of events is already working:
Client loads https://accounts.google.com/gsi/client
Client starts call to google.accounts.oauth2.initCodeClient
Client gets code
Client passes code to one of my server endpoints
Server has an oauth2Client set up using the config with client_id, client_secret, and redirect URL = 'postmessage'
Server exchanges the code from the client for tokens
Server does oauth2Client.setCredentials(tokens) - this contains an access_token, which is enough for the client to make API calls to, e.g., retrieve the user's Google Calendar
Server is able to do oauth2Client.getTokenInfo(tokens.access_token);
There are various places along the way that involve scopes; I am probably getting something confused here. The client's initial call (step 2 above) uses
scope: 'https://www.googleapis.com/auth/calendar',
My code path on the server does define scopes anywhere.
In GCP, my project is set up with scopes
calendar.calendarlist.readonly, calendar.readonly and calendar.events.readonly
openid
/auth/userinfo.email
Here's the problem I'm encountering: when I go through this flow as a user and oauth with the account that owns the GCP project (this is a Google Workspace email, in case that matters), the tokens object that the server receives (step 6 above) has access_token, refresh_token and id_token - the id_token can be decoded to yield the user's email, and the user's email is also in the response to oauth2Client.getTokenInfo(token.access_token).
However, when I go through the flow with my other (personal) Gmail account, the tokens object that the server receives is missing the id_token but has the access and refresh tokens. Question 1: why are the responses different?
Question 2: How can I get the email of the user on the server in the personal Gmail account case? I've tried having the server make a call to https://www.googleapis.com/oauth2/v2/userinfo?fields=id,email,name,picture with the access_token, but this fails. I am not sure if I'm supposed to declare scopes for oauth2Client somehow, or tap a Google API using a different method on the server.
I think I've had a breakthrough: in step 2 in my original post, when I did "Client starts call to google.accounts.oauth2.initCodeClient", I had set the scope of initCodeClient to just the calendar scope. When I changed it instead to scope: 'https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/userinfo.email openid', (scope takes a space-delimited list in this case), it allowed my server call to get the id_token for this user and oauth2Client.getTokenInfo to get a response with the user's email in it.
When I updated the scopes like that, the popup asking for authorization also updated to request all the scopes I wanted - previously, it was only asking for the Calendar scope, so it makes sense Google didn't want to return the email.
What I still don't understand is why my previous setup was working for the account that owns the GCP project. In other words, when I was first building it out with that owner account, the client was only noting the Calendar scope while the server was asking for all three scopes (ie there was a mismatch), and the server was still able to get an id_token and the user's email in getTokenInfo. Maybe the owner account has some special privilege?

AADSTS50146 error when attempting to retrieve Oauth access_token

Looking for some AzureAD help with this error -
"error": "invalid_request", "error_description": "AADSTS50146: This
application is required to be configured with an application-specific
signing key.\r\nTrace ID:
6fb978c1-0d74-478c-991c-3ad48ca65f00\r\nCorrelation ID:
81c05804-175c-456b-8d45-d5365818b599\r\nTimestamp: 2019-12-17
19:28:29Z",
I get the error above in one AzureAD env. when trying to do a OAuth2.0 token request. I have another test AzureAD where the same request works fine.
Doing a POST to https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token with clientId, clientSecret and grant_type=client_credentials.
Found this via google - https://github.com/MicrosoftDocs/azure-docs/issues/5394 but wanted to understand how does one go about configuring the "scope" parameter in AzureAD.
You probably have additional/mapped claims.
If you do not want to bother with creating application-specific signing keys,
you need to set "acceptMappedClaims": true in the manifest.
Setting "accessTokenAcceptedVersion": 2 can also help.
The api permissions in Azure AD portal is the value of scope.
You can also expose an API, then you can add your own scope.

Is it possible to retrieve an OAuth2 access token from Google with client secret file of Google Apps Script project?

I want to reuse the OAuth2 client-secret of a Google Apps script project to access Google APIs on behalf of this script (e.g. via Sheets API reading a spreadsheet where the script has access). Users with a Google account granted the necessary scopes to the script. Now I'd like to replace the script with a new app without asking the users again for user consent. Typically, when the script (or the app) runs the users would be offline.
My first question would be, if this scenario is a supported OAuth2 use-case with Google API authorization, and if so, what would be the best way to implement it, especially to prevent security issues?
Client secrets of the script
OAuth2 client-secret file of the script from Google API Console, under Credentials. Also see Credentials, access, security, and identity and Setting up OAuth 2.0
The client-secrets.json looks like this:
{"web":{
"client_id": "57...1t.apps.googleusercontent.com",
"project_id": "project-id-95...70",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "K2...y1",
"redirect_uris": ["https://script.google.com/oauthcallback"]
}}
The file would be deployed with the app code (App Engine). But an alternate location such as Cloud Storage would be possible.
OAuth2 access token
In absence of the user, I would like to use the client ID and secret with the same scopes that were granted to the script originally, for getting an access token from the Google authorization server, something like this:
HTTP 200 OK
Content-type: application/json
{
"access_token": "987tghjkiu6trfghjuytrghj",
"scope": "foo bar",
"token_type": "Bearer"
}
I would like to use the access token in the HTTP Bearer header for the requests to the Sheets API on behalf of the old script.
Client_credentials request to authorization server
My (limited) understanding is, that I can use the grant-type client_credentials to get the access token from the authorization server. The request would look like this:
POST /o/oauth2/token
Host: https://accounts.google.com
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Authorization: Basic Base_64_string
grant_type=client_credentials&
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets
Where the Basic HTTP authorization is client_id:client_secret values, separated by a colon, and base64 encoded.
If I ditch grant_type or scope in the body, I will get corresponding errors.
The version as above resulted in: {\n "error" : "invalid_request"\n} response, no specifics provided. I have tried with client_id and client_secret in the body in combination with and without the Authorization header, all with the same error.
First Off let me start by saying that i am not an expert in app script or sheets i have used both a few times but i dont consider myself an expert in the subject.
When you authenticate someone their authentication is granted based upon the client id from within a project. They are granting you access to their data and approving the credential request. Think of it as a recored in Googles database someplace.
User 321 has granted consent to client 123 to access their sheets data.
So you have a project Super Script App which has client id 123 you are asking for access to edit sheets. If i approve it i am giving Super Script App with client id 123 access to my sheets. While i am sitting at my machine your app will run accessing my data. Now when i log off Super Script App with client id 123 cant access my data unless you have offline access and have a refresh token. With that refresh token you will be able to access my data when i am not there by requesting a new access token.
Now you want to make a new app. If you take the client id 123 and use it in your new app I am going to have to login to my google account but it will not popup and request that i give you permissions to access my data I have already granted client id 123 access to my sheets. Unless you have a refresh token your not going to be able to access this data without me being there.
If at anytime you ask for an extra scope I am going to have to approve that.
Now comes the fun part. I haven't actually tried this in a while. If you go to Google Developer console and create client id 321 under the same project as client id 123, and then use that in your new Super Script App V2 will i still have to grant it permission to access my data? I am going to lean towards probably not. Note a refresh token created with client id 123 will not work with client id 321 they are locked to a client unless its mobile and there is some magic their.
I am not exactly sure what you are doing with your second app so i hope this helps clear things up.

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

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.

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"

Resources