Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how do i add more scopes to fetch phone numbers? #10

Closed
sarunmrzn opened this issue Mar 3, 2023 · 26 comments
Closed

how do i add more scopes to fetch phone numbers? #10

sarunmrzn opened this issue Mar 3, 2023 · 26 comments

Comments

@sarunmrzn
Copy link
Contributor

No description provided.

@zgid123
Copy link
Owner

zgid123 commented Mar 3, 2023

I think you can do

passport.use(new GoogleOauthTokenStrategy({
  clientID: GOOGLE_CLIENT_ID,
  clientSecret: GOOGLE_CLIENT_SECRET,
  scope: [''],
}, (accessToken, refreshToken, profile, cb) => {
  User.findOrCreate({ googleId: profile.id }, (error, user) => {
    return done(error, user);
  });
}));

For typescript, I will update the typing later

@sarunmrzn
Copy link
Contributor Author

sarunmrzn commented Mar 3, 2023

Doesn't work :(

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import * as Strategy from 'passport-google-oauth-token';

@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
  constructor() {
    super({
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      scope: [
        'profile',
        'email',
        'https://www.googleapis.com/auth/user.phonenumbers.read',
      ],
    });
  }

  async validate(
    _accessToken: string,
    _refreshToken: string,
    profile: any,
    done: any
  ): Promise<any> {
    const { id, name, emails, photos } = profile;

    const user = {
      provider: 'google',
      providerId: id,
      email: emails[0].value,
      firstName: name.givenName,
      lastName: name.familyName,
      photo: photos[0].value,
    };

    done(null, user);
  }
}

@zgid123
Copy link
Owner

zgid123 commented Mar 3, 2023

I see, lemme try to debug it

@zgid123
Copy link
Owner

zgid123 commented Mar 3, 2023

because I am busy recently, so it will take time

@zgid123
Copy link
Owner

zgid123 commented Mar 6, 2023

@sarunmrzn I tried to debug, but I couldn't get the phone number from this https://developers.google.com/oauthplayground. Can you test the scope here and lemme know the result?

@zgid123
Copy link
Owner

zgid123 commented Mar 7, 2023

it seems to get the phone number, you should change the profileURL to https://people.googleapis.com/v1/people/me instead of default value https://www.googleapis.com/oauth2/v3/userinfo. But if you change the profileURL, the response schema is not incorrect, I am thinking a solution to pass the parser

@zgid123
Copy link
Owner

zgid123 commented Mar 7, 2023

@sarunmrzn please help me to confirm, so I can provide a solution for this package. Thank you

@sarunmrzn
Copy link
Contributor Author

@zgid123 changing profile URL to https://people.googleapis.com/v1/people/me doesn't work either, I'm getting

InternalOAuthError: Failed to fetch user profile
    at /home/sarun/g-oauth/node_modules/passport-google-oauth-token/lib/index.js:126:23
    at passBackControl (/home/sarun/g-oauth/node_modules/oauth/lib/oauth2.js:132:9)
    at IncomingMessage.<anonymous> (/home/sarun/g-oauth/node_modules/oauth/lib/oauth2.js:157:7)
    at IncomingMessage.emit (node:events:525:35)
    at endReadableNT (node:internal/streams/readable:1359:12)
    at processTicksAndRejections (node:internal/process/task_queues:82:21)

@zgid123
Copy link
Owner

zgid123 commented Mar 8, 2023

@sarunmrzn I mean you should check using the https://developers.google.com/oauthplayground first. The current version may not fetch that url

@zgid123
Copy link
Owner

zgid123 commented Mar 8, 2023

I checked for myself, and it does not respond phone number using the current url that this package is using. Only this one https://people.googleapis.com/v1/people/me responds the phone number. So I will add an option for parser, you can pass the parser to format the response schema

@zgid123
Copy link
Owner

zgid123 commented Mar 8, 2023

ok, so basically, you cannot get the phone number via https://www.googleapis.com/oauth2/v3/userinfo. Ref here. As you can see, there is no phone number in the interface.

So for the current version, when validate the accessToken successfully, you can use that token to fetch the phone number using people/me url that I suggested above.

I am rework this package to typescript and try to pass the custom parser, so you can parse it to whatever schema you want

@sarunmrzn
Copy link
Contributor Author

I tried in the playground, I still can't get the phone number with the url you specified, but if it works for you, please update the package, I'll try it out after. Thank you

@zgid123
Copy link
Owner

zgid123 commented Mar 8, 2023

make sure you choose this scope

image

you can get the phone number

image

for the current url

image

It will take time for new version. Because I need to fix the typing

@zgid123
Copy link
Owner

zgid123 commented Mar 8, 2023

@sarunmrzn you can test with new version 1.0.5. Check my example for nestjs here

@sarunmrzn
Copy link
Contributor Author

make sure you choose this scope

image

you can get the phone number

image

for the current url

image

It will take time for new version. Because I need to fix the typing

I did this exact same thing but I still dont get phoneNumbers key you're receiving, maybe it's got to do something with account itself, I'm going to test this on my other accounts and see if I can get the field.

@sarunmrzn you can test with new version 1.0.5. Check my example for nestjs here

I upgraded the version and copied interface types but still throws me InternalOAuthError: Failed to fetch user profile I'll test it once again after couple of hours

@zgid123
Copy link
Owner

zgid123 commented Mar 8, 2023

@sarunmrzn is your phone number public? If not, googleapis won't respond it for you. Also please provide me the code that you are using, I will have a look at your code

@sarunmrzn
Copy link
Contributor Author

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import Strategy from 'passport-google-oauth-token';
import type { IGoogleUserProps, IProfileProps } from './interface';

@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
  constructor() {
    super({
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_SECRET,
      profileURL: 'https://people.googleapis.com/v1/people/me',
      scope: [
        'email',
        'profile',
        'https://www.googleapis.com/auth/user.phonenumbers.read',
      ],
      profileParser: (user: IGoogleUserProps): IProfileProps => {
        const { names, photos, phoneNumbers, emailAddresses, ...rest } = user;
        const [name] = names || [];
        const [phoneNumber] = phoneNumbers || [];
        const [email] = emailAddresses || [];
        const { metadata, displayName, familyName, givenName } = name || {};

        console.log(emailAddresses);
        console.log(rest);

        return {
          provider: 'google',
          id: metadata.source.id,
          displayName,
          name:
            familyName || givenName
              ? {
                  givenName,
                  familyName,
                }
              : {},
          emails: [
            {
              value: email.value,
              verified: email.metadata.verified,
            },
          ],
          phoneNumbers: [phoneNumber.value],
          photos: [{ value: photos[0]?.url || '' }],
          _raw: JSON.stringify(user),
          _json: user,
        };
      },
    });
  }

  async validate(
    _accessToken: string,
    _refreshToken: string,
    profile: any,
    done: any
  ): Promise<any> {
    console.log(profile);
    const { id, name, emails, photos } = profile;

    const user = {
      provider: 'google',
      providerId: id,
      email: emails[0].value,
      firstName: name.givenName,
      lastName: name.familyName,
      photo: photos[0].value,
    };

    done(null, user);
  }
}

"passport-google-oauth-token": "^1.0.5"

I will test with other google accounts and let you know if this works

@zgid123
Copy link
Owner

zgid123 commented Mar 8, 2023

how did you get the refresh_token + access_token?

@sarunmrzn
Copy link
Contributor Author

sarunmrzn commented Mar 8, 2023

I'm using https://www.npmjs.com/package/@react-oauth/google for implicit grant code generation

@zgid123
Copy link
Owner

zgid123 commented Mar 8, 2023

can you provide a codesandbox project? I will have a look tonight. I think it is because you missed some config for @react-oauth/google

@sarunmrzn
Copy link
Contributor Author

sarunmrzn commented Mar 8, 2023

here. I didn't do anything fancy on it, just used the hook button and called the nestjs api and attached access_token to the body

this works very well with your package, it just doesnt fetch phone numbers, I'm strongly suspecting its just my account that isn't fetching phone numbers because I cant even get those in the playground, I'll test it with some other accounts later today and let you know the update for it

@sarunmrzn
Copy link
Contributor Author

I just tested with a friend's google account to fetch phone number on playground, it works on his account, just not mine for some reason.

Does the 1.0.5 fetches phone numbers for you? I think we can mark this as solved if it does.

@sarunmrzn sarunmrzn reopened this Mar 8, 2023
@zgid123
Copy link
Owner

zgid123 commented Mar 8, 2023

I tried to use your code to test, but my google app always rejects my request. I still not find out why.

For the package, the example code for nestjs from this repository can work and can get the phone number (url: /google-with-phone). You can use that app and your FE to test again.

@zgid123
Copy link
Owner

zgid123 commented Mar 9, 2023

@sarunmrzn ok, I think I found out the problem in your case.

To fix your issue, you will need to do

  1. you need to add scope for @react-oauth/google (1)
  2. access to https://console.cloud.google.com/apis/library/people.googleapis.com?project=
  3. enable the people service
  4. follow the example from this repository, I already updated the code (2)

(1) code example

  const login = useGoogleLogin({
    scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/user.phonenumbers.read openid https://www.googleapis.com/auth/userinfo.profile',
    flow: 'implicit',
    onSuccess: (codeReponse) => {
      console.log(codeReponse);
      //axios post call backend login api and I attached access_token: codeResponse.access_token
    },
  });

(2) for more info about the personFields, you can check here

@zgid123
Copy link
Owner

zgid123 commented Mar 9, 2023

Lemme know if you have another issue. Feel free to close this issue when your problem is fixed. If not, please provide me the error that you are facing. I will have a look. It would be better if you provide an example repository. I will have a look at your repository

@sarunmrzn
Copy link
Contributor Author

We gave up on this, apparenlty even when there are phone numbers on authorization code flow it doesn't show up phone numbers, we just moved to manually adding phone number verification after sign up. Thanks for all effort you put into this, I will however try your solution on my a separate project. For now I'll close this.

Thanks agian.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants