Can the permission to access user's profile picture be removed in Facebook login oauth? - permissions

I can request for permissions specifying the scope like this:
facebook:
type: facebook
client_id: ''
client_secret: ''
scope: "email, user_birthday"
and when logging in, I get asked for permissions for name, profile picture, email and birthday.
I would like to remove the permission for profile picture, since I don't need it in my app. From what I read, name and picture are default permissions, so does that mean they cannot be overridden?

Related

Clarification on Google Authentication and Authorization, with OAuth in 2022

I am writing an App and am trying to leverage Google for A&A. The app itself relies on access to the users Google Calendar, and so initially I leveraged their updated OAUTH2 library for A&A.
Here is my flow:
User goes to the index.html which has "https://accounts.google.com/gsi/client" script and google.accounts.oauth2.initCodeClient is called with my client_id, scopes, redirect url
<script src="https://accounts.google.com/gsi/client"></script>
<script>
let client;
function initClient() {
client = google.accounts.oauth2.initCodeClient({
client_id: 'xxxxx-xxxx.apps.googleusercontent.com',
scope:
'https://www.googleapis.com/auth/userinfo.profile \
https://www.googleapis.com/auth/userinfo.email \
https://www.googleapis.com/auth/calendar.readonly \
https://www.googleapis.com/auth/calendar.events',
ux_mode: 'redirect',
redirect_uri: 'http://localhost:5000/oauth2callback',
});
}
// Request an access token
function getAuthCode() {
client.requestCode();
}
The user clicks the login button, which kicks off requestCode() and they begin the login flow. They login or select their google account, then besides the unapproved app screen, they get to the consent screen with my requested scopes.
After, they are redirected to my expressjs endpoint and using the "googleapis" library I exchange with id_token for the access and refresh tokens.
...
const { tokens } = await oauth2Client.getToken(req.query.code); //exchange code for tokens
const userInfo = (
await oauth2Client.verifyIdToken({
idToken: tokens.id_token,
audience: config.google.clientID,
})
).payload;
if (!indexBy.email[userInfo.email]) { // check if user exists
const newUser = {
name: userInfo.name,
email: userInfo.email,
o_id: userInfo.sub,
picture: userInfo.picture,
r_token: tokens.refresh_token,
};
...
Ok, all good.... but not quite. The problem is, that next time the user wants to login to the app, they go through the entire flow again, including the consent screen (again).
So, after going through more docs, even looking at examples from google. I was surprised and I noticed that many of those apps used the passport oauth2 plugin :( Something i've done in the past, but was hoping to avoid that with the recently updated Google client and nodejs libraries.
Ok, how to not prompt for consent screen on subsequent logins?
Maybe separate A&A, so first I use "Sign In With Google" for Authentication, then when I get the user info, check if the user is already registered (hence I have already saved the refresh token) and they start the app.
On the other hand, if they are new (not in existing app user collection), after authenticating, I will then call the OAUTH2 authorization redirect, so again they on Googles site, this time to do the scopes api confirmation.
So, first question, is that the best practice with most apps with leverage a Google API via OAuth? To first Authenticate, then possibility Authorize (as needed). Hopefully this will still work ok when things come up with expired/invalid refresh token (fingers crossed the default google library handles that).
When doing the Authorize for consent, can I pass something from the previous Authenticate flow so they don't need to do that again.
Or maybe when doing the Authenticate process (Google Identity Service), there is some flag or param so that if they have already consented, they don't have to do that again on subsequent logins.
Incase I wasn't clear, in a nutshell the question is: should I be doing Authenticate for login, separately from Authorization (oauth2 token). Or should I go right into the Authorization flow, which first Authenticates the user, and can I skip the Authorization consent screens if they've already done that. Or maybe there's another way which is the best practice.
Thanks for your attention.
Background info
Authentication is the act where by a user logs in into a system using their login and password. With authentication we know that the user is behind the machine. For this we use Open id connect, which was built on top of Oauth2. Open id connect returns and id_token which can be used to identify the user, it is often a jwt containing some claims to identify the subject or the user behind the Authentication.
The scope used for open id connect is profile and email. open id connect grants you consent to access a users profile information.
This is an example of the decrypted id token returned by google from a simple call using profile scope only. All this id token is telling you is who the user behind the machine is.
{
"iss": "https://accounts.google.com",
"azp": "4074087181.apps.googleusercontent.com",
"aud": "4074087181.apps.googleusercontent.com",
"sub": "1172004755672775346",
"at_hash": "pYlH4icaIx8PssR32_4qWQ",
"name": "Linda Lawton",
"picture": "https://lh3.googleusercontent.com/a-/AOh14GhroCYJp2P9xeYeYk1npchBPK-zbtTxzNQo0WAHI20=s96-c",
"given_name": "Linda",
"family_name": "Lawton",
"locale": "en",
"iat": 1655219027,
"exp": 1655222627
}
In the same call google also returned an access token. Now my call contained only the scope for profile, due to the fact that its open id connect. This means that I will only have access to the data that the profile scope would grant access to. In this case most of what is behind the Google people api.
Note: The user does not see a consent screen with open id connect, even though they are consenting to profile scope. It is assumed by signing into your account that the system you are logging into would have access to your profile info.
Authorization
Authorization is the process by which a user grants your application authorization to access their private user data. The user is shown a consent screen where they consent to your application accessing data defined by some scopes.
In the case of google calendar api there are serval
https://www.googleapis.com/auth/calendar See, edit, share, and permanently delete all the calendars you can access using Google Calendar
https://www.googleapis.com/auth/calendar.events View and edit events on all your calendars
https://www.googleapis.com/auth/calendar.events.readonly View events on all your calendars
https://www.googleapis.com/auth/calendar.readonly See and download any calendar you can access using your Google Calendar
https://www.googleapis.com/auth/calendar.settings.readonly View your Calendar settings
In this case you are only given an access token this is again Oauth2 it is authorization to access the users calendar data it is not authentication this is not related to login.
Your question
So, first question, is that the best practice with most apps with leverage a Google API via OAuth? To first Authenticate, then possibility Authorize (as needed).
You would do both at the same time.
When you authencation your user make sure to include your google calendar scope then the access token and refresh token returned will grant you access to google calendar.
I am going to assume that you have some kind of user system. When you store the user be sure to store the refresh token that is returned.
As far as Authentication goes i will assume you either have a remember me system which will set a cookie on their machine and remember the user so that you can then get the refresh token from their system the next time they come back.
If they did not chose to select a remember me option then will then have to login every time they visit your site but part of the login will return the "sub": "1172004755672775346", this is the users id on google system so you can use that in your database to match the user when they come back.
Your question is quite complex and will depend upon the type of system you have what it is designed to do as well as what programming language you are using. That being said I hope this very long answer clears things up a bit.

Google SSO not asking for scope for just one user (other users OK)

I'm seeing a strange problem with google SSO and one of my users.
I'm requesting the following scopes using the oauth:
const url = oauth2Client.generateAuthUrl({
access_type: 'offline', // we want refresh tokens
scope: ['email'],
state: '{...}', //state object
prompt: 'consent',
hd: 'example.com', // restrict to just our domain
include_granted_scopes: true,
});
For every other user redirected to url, they are given a consent screen after authenticating that looks like this:
EXCEPT for one user. For this user - when they authenticate, there is no consent screen, and they are logged in with the bare minimum scope.
When the user looks at their account security page, they see our webapp as authorized with no scope. I've asked the user to revoke the app permissions and to try logging in again, but the same thing happens. They are logged in with no consent screen and no scope. Again, the strange thing is that it is only occurring for this one user.
The culprit in this case was:
include_granted_scopes: true,
The other users for whom the consent screen was shown had at some time in the past been given the correct scope, and granted permission. Therefore, on any subsequent grant, the consent screen showed the previously granted scopes. The source code, at some point, changed and removed those particular scopes (and thus, we were only left with the email scope as shown in the question.
Interestingly, the email scope does not have to be consented to, and is automatic so it returned the user to our app with that granted scope, having never showed the consent screen to that one user.
Changing the scope to actually include the correct scopes now allows all users to see the consent screen and grant the proper scopes:
const url = oauth2Client.generateAuthUrl({
access_type: 'offline', // we want refresh tokens
scope: ['email',
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.labels',
'https://www.googleapis.com/auth/gmail.modify',
],
state: '{...}', //state object
prompt: 'consent',
hd: 'example.com', // restrict to just our domain
include_granted_scopes: true,
});

get the photo URL of the user with (Apple sign in)

I implemented google sign in and stored information about each user (name, email, photoURL).
now I want to implement the same with apple sign in, so far everything works but I don't know how I can get the photo URL, does apple even provide that?
these are the Scopes that I request from the user:
['email', 'full_name',]
what is the scope name for the photo URL?
thanks
apple's sign-in doesnt provide a picture

JWT and Uploading Images

I am wondering about some strategies regarding a particular issue I am facing. Let's imagine that there's an authentication system implemented using JWT.
Users sign-in, they get a token which has the following payload:
{ username: 'John', email: 'john#example.com', photo: null }
(they payload is generated based on a database query, say SELECT * FROM user WHERE id = 1)
When (and only when) the user is logged in, they can upload an image. The image gets stored somewhere, the user entry is updated in the database.
The problem I am facing is that now they need to login and log-back in again to see the profile photo updated since the profile information is displayed based on the token payload which will still not contain the photo. The next time they login of course it'll be updated:
{ username: 'John', email: 'john#example.com', photo: 'john-img.jpg' }
So the question is - how to handle the situation when the profile data is show from a token and there's a file upload procedure and I wish to display the image?
I know that the client shouldn't (and cannot) update the token, because that will automatically cause the token to be invalidated.
Are there any strategies out there that are acceptable? Should I rethink the logic of doing file uploads while logged in? Should this not be tied to a JWT? Should the profile page not be built up from the token?
#Tamas you should never keep user photo in JWT Token, as this is not the ideal or recommended way, instead you can keep this in User(database) table and always update user data on profile update,
But if they really want to go with this option only? you can still do this by keeping user image info in localstorage, by the time user login and logout you can get image info from localstorage.
hope this could help.

Add user email scope to Google OAuth

I completed the process to allow the users to login to Google OAuth but the Oauth Consent Screen do not ask the email/userinfo permission/scope to the user and so the access token I get do not have access to the user information.
At console.cloud.google.com > My project > Credentials > Oauth Consent Screen the following scopes are visible but seem added by default and I can not edit them: email (googleapis.com/auth/userinfo.email), profile (googleapis.com/auth/userinfo.profile), openid (openid)
But when I test it I get this dialog window:
Instead I should get this:
So with the text "To continue, Google will share your name, email address, language preference, and profile picture with Support Board."
My app is not verified by Google and maybe this is the issue, but after checking everywhere I do not see any docs about it.
I found the answer, the URL must include; scope=email
For instance:
https://accounts.google.com/o/oauth2/auth?scope=email&response_type=code&access_type=offline&redirect_uri=[URL]&client_id=[CLIENT-ID]&prompt=consent
^^^^^^^^^^^