Google OAuth2 is missing scope that was requested - oauth-2.0

We have OAuth2 on our website, and according to our logs, we redirect users to URL like this:
https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=xxxx&prompt=consent&redirect_uri=xxxx/callback&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&state=Y38pUwFTAqbaHsU6oa4q
The next log entry is redirect callback from Google, which is missing www.googleapis.com/auth/youtube.readonly scope:
https://ourapp.com/oauth2/callback?state=xxxx&code=xxx&scope=email%20profile%20openid%20https://www.googleapis.com/auth/userinfo.profile%20https://www.googleapis.com/auth/userinfo.email&authuser=0&prompt=consent
What may be a reason for this behavior? It happens only to some users, and very inconsistent. I wasn't able to reproduce it by myself.
The application is approved by Google and the scope usage is verified.

For apps that request more than one scope (you are asking for identity scopes email, profile and YouTube), you must be able to handle partial consent where the user may choose on the consent page to not grant access to one or more non-identity scopes.
https://developers.google.com/identity/protocols/oauth2/policies#unbundled-consent
You can encourage your users to grant access to the scope needed by separating the sign-in moment (asking for email, profile) information from the moment of asking for YouTube access. This is called incremental authorization.
You can also tell your users before you redirect to the OAuth flow why you are asking for the data you need to let them make a more informed choice.

Related

How to restrict access with Oauth 2

New to Oauth and had a general question. Is there a way to restrict who can log into your site with Oauth 2? Similar to AD groups or something so I could control who I want to be able to log in based on group or user name? I would like people to use google or facebook but only let certain people actually log in.
You can filter users in a code that handles the redirect_uri. If you use the Auth code grant, that will be some backend code and if you use the Implicit flow, it will be a code in a browser application. But the JavaScript security restrictions should have their equivalent somewhere at the backend too, since the JavaScript code can be altered by the browser user.
To be able to do that (to have info about an authenticated user), you should either request an ID token or an access token with a scope that authorizes you to get user info at the /userinfo endpoint.

OAuth2 not for authentication

What is the main reason OAuth2 is not enough for authentication?
I can see that if userA logs into evil.com, then owner of evil.com can submit userA's access_token to good.com (or any other login with fb website) and pretend to be userA.
But if good.com checks if access token was intended for it, then I don't see any possibility of attacks..
I can't see the fuss about this. For example facebook gives me the App id when I get the access_token details. How is an attack possible if I am checking this?
Is it not a security vulnerability but lack of standards? like which scope or which field email is in etc.?
The access token you receive just represents an authorization issued to the client. It just allows the client to access on protected resources, but it does not give you any information about the resource owner.
In your example, evil.com can get those resources that own the userA, but cannot know who userA is.
Please loook at this excellent video about OAuth2 and the Authorization/Authentication terms. It helped me a lot.
The access token does give you information (possibly) information about the Resource Owner but it does not give you information about whether the Resource Owner is present and/or how he/she authenticated even if you'd be able to identify whether the token was meant for you in some undefined non-standard way (the latter being another advantage of OpenID Connect over OAuth 2.0 as the OP already mentions).

OAuth2 Requesting Additional Scopes

Using the Google Sign In SDK, a user can sign in via OAuth2 with some default scopes requested. It can be beneficial to not request every scope an app may need up front, and instead to request additional scopes at a later time so as to not overwhelm the user at sign up.
Google outlines the process for doing this here.
The issue is that, after a user has signed in with Google, upon requesting additional scopes the user has the ability to switch Google accounts and authorize those scopes using a different account before returning to my application.
Is there a way, similar to calling -[GIDSignIn signIn], to explicitly specify which user I want to signIn and not allow the option of changing accounts?
I am not familiar with Google Sign in SDK. Most of what I have done has been written myself so I don't know how that SDK really works. However that being said the Authentication server does support something called Login_hint which should allow you to force them to use a specific user.
login_hint email address or sub identifier When your application
knows which user it is trying to authenticate, it can provide this
parameter as a hint to the Authentication Server. Passing this hint
will either pre-fill the email box on the sign-in form or select the
proper multi-login session, thereby simplifying the login flow.
More info
login_hint can be the user's email address or the sub string,
which is equivalent to the user's Google ID. If you do not provide a
login_hint and the user is currently logged in, the consent screen
includes a request for approval to release the user’s email address to
your app. (Read more at login_hint.)
If memory services Google Sign in SDK does work with openId connect so it should be possible.

Performing Google Federated Login/oAuth2 after initial Authentication

I am trying to support "Hybrid" Federated Login and oAuth2 (using logic from this document) for a webservice which will:
support Sign in using your Google account on my site. That is, from the documentation: You can also choose to use Google's authentication system as a way to outsource user authentication for your application. This can remove the need to create, maintain, and secure a username and password store.
Access the user's Google Analytics.
Here are the steps I have done.
I form my request to https://accounts.google.com/o/oauth2/auth with the scopes (Google Analytics) I want access to.
I Get redirected to google where it has my icon and which scopes I am requesting access to. I grant access.
I get redirected back to the callback page.
I get the tokens (access and refresh), as well as a huge id_token string (which I don't know) and store all of this information in my database.
I then make a call to https://www.googleapis.com/oauth2/v1/userinfo?access_token=xxxyyyzzz to get the user's email and name and store this information in my database too. I also notice it returns a id field which to my knowledge never changes and I presume is some sort of unique identifier. I store this too.
Question: If I go to Authorized Access to your Google Account section in my Google account, it shows that my site has access to "Google Analytics. BUT, it does not say Sign in using your Google account. This is what I am trying to accomplish. I would have thought using the logic would enable Sign in using your Google account. What am I doing wrong? And what would be the applicable call to google so that users can sign in to my site?
If your site has access to something like your Contacts or Analytics using OAuth, you'll never see "Sign in using your Google account". I'm pretty sure that's only if you use OpenID (not OAuth) only for sign-in.
Specifically, OAuth is used for giving you access to APIs to create/update/delete data, while OpenID is for signing in.
If you are asking how to identify user for future logins, you have two options:
Mix OAuth with OpenID, that is called Hybrid. I have described it on this answer.
Use userinfo scope and request userinfo (email, etc.) after successful OAuth authorization. It is described on Google OAuth 2 documentation.
If you mean automatically login to your web site in future visits you can use OpenID "immediate mode" (openid.mode parameter).
When the user is redirected back, you call the second request from your own (server-side?) code, and get their email address. When you successfully get it, that means that the user is logged on. You can add it to the session (e.g. as cookie), and as long as you have it, the user is logged on. You make the user log out by forgetting the email address, so by clearing the session/cookies.
Add this paramter to the https://accounts.google.com/o/oauth2/auth URL call: approval_prompt=force and then the Sign in using your Google account will always show regardless of whether the user was already signed into that or any other account.
So the call would be like this https://accounts.google.com/o/oauth2/auth?client_id=<client id>&redirect_uri=<uri>&scope=<scope>&access_type=<online or offline>&response_type=code&approval_prompt=force

Twitter Oauth question

I've read through documentation where possible but unable to figure out this basic question. When using Oauth with Twitter in my web application, does it require the user to be logged into Twitter everytime?
For example, if a user authorises their account with my website, in future sessions, if they complete an action that posts to their twitter stream, will this occur without any problems, or would they need to re-sign in via Twitter?
Thanks guys!
The OAuth authorization actually allows your application to access their account whenever it wants. So the users do not even need to be there doing something with your web application to allow it to tweet something or such.
Your application is then able to use the key and token which it received in the authorization process to tell Twitter any time "hey, I am authorized to use this account" and basically works as the application's personal login credentials for that account.
No, they only need to be logged into Twitter when they go through the initial OAuth authorization. After that, your site talks directly to the Twitter API using tokens that it saved from earlier.
Ok I've setup a test-case and it looks like I was a bit wrong:
oauth_token, oauth_token_secret are unique for each user and they never change, so if you store them in your database you can reuse them. No matter if the user is logged in to twitter or not.
No, they will normally not need to re-authorize. If the token is revoked, however, they will, and your application needs to be able to handle this (by allowing them to do so). In general, this is true for any SSO system.
A twitter user can explicitly revoke an application's token at the provided page.

Resources