How I can get user info profile from Google API? - node.js

I have to implement signIn by google account.
I want to some suggestions.
I created project in google console. Added scope user info.profile
I'm following course instruction on internet, but I still cannot get userinfo ( email, name, age ... ).
Step:
Get code in url redirect_uri by client_id
Get token https://accounts.google.com/o/oauth2/token by code, client_id, client_secret ...
Try call to https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=accessToken to get info but only object
{
"azp": "155122683461-51hq2n932svo4ajbt98ic0q67m4tuj5o.apps.googleusercontent.com",
"aud": "155122683461-51hq2n932svo4ajbt98ic0q67m4tuj5o.apps.googleusercontent.com",
"sub": "108865940357700877124",
"scope": "https://www.googleapis.com/auth/userinfo.profile",
"exp": "1554094721",
"expires_in": "3326",
"access_type": "offline"
}
Can you guys give me an example :(
Thanks

people api
The infomration you are looking for can be found on people.get
GET https://people.googleapis.com/v1/{resourceName=people/*}
tip send Field mask with no space - person.emailAddresses,person.birthdays It reads form person info so the user will have had to fill in this information
However you will need to add the scopes to get the information you want
https://www.googleapis.com/auth/profile.emails.read
https://www.googleapis.com/auth/user.birthday.read
You can test it here Google Apis explorer
A node.js quick start for google people api can be found here
userinfo endpoint
The userinfo endpoint can also be used but it does not return the information you are looking for
You need to request the email scope to have seen email in the below response the user must grant you permission to see their email the following is standard response for profile scope only.
GET /oauth2/v2/userinfo HTTP/1.1
Host: www.googleapis.com
Content-length: 0
Authorization: Bearer ya29.GlveBiwp4-NTPLU9VN3rn1enty11KOdQHGcyfZd1xJ1Ee9eGS2Pw2nJ7KDUBQPa-uT-AoKDQdoVigU6bruVIB1a3fiBu1n
response
{
"picture": "https://lh5.googleusercontent.com/-a1CWlFnA5xE/AAAAAAAAAAI/AAAAAAAAl1I/UcwPajZOuN4/photo.jpg",
"name": "Linda Lawton",
"family_name": "Lawton",
"locale": "en",
"gender": "female",
"link": "https://plus.google.com/+LindaLawton",
"given_name": "Linda",
"id": "117200475532672775346"
}
scopes
You should consult the node tutorial for how to work with scopes. Remember you will need to request access of the user again if you change the scope in your code.
const SCOPES = ['profile', 'email'];

Related

How to get email from Microsoft graph api oidc/userinfo endpoint

I have setup oauth via azure, i have received an authorization_code which i have exchanged for an access_token. I am then attempting to use that access token to get userinfo data including the email as described in the docs (https://learn.microsoft.com/en-us/azure/active-directory/develop/userinfo). However in the response it does not return to me the email.
{
"sub": "<redacted>",
"name": "John Doe",
"family_name": "John",
"given_name": "Doe",
"picture": "https://graph.microsoft.com/v1.0/me/photo/$value"
}
The documentation suggests that in order for email to be returned in the response it requires the email scope. https://learn.microsoft.com/en-us/azure/active-directory/develop/userinfo#userinfo-response
However i believe i am already specifying that i want the email scope.
App Permissions
/oauth2/v2.0/token (the scope shows profile, openid, email and user.Read)
What am i missing?>
I tried to reproduce the same in my environment and got the below results:
I created one Azure AD application and added API permissions as below:
Now I generated the access token with same scope as you like below:
POST https://login.microsoftonline.com/common/oauth2/v2.0/token
client_id:app_id
grant_type:authorization_code
scope:https://graph.microsoft.com/User.Read
client_secret:secret
code:code
redirect_uri:redirect_uri
Response:
I used the above token to get user info data and got response without email like below:
GET https://graph.microsoft.com/oidc/userinfo
Response:
This is because the email field in user's profile is not set. So, I updated email field by editing user's properties.
Now I generated access token again and used it to get user info data and got response with email like below:
GET https://graph.microsoft.com/oidc/userinfo
Response:

Google OAuth2 cannot get profile info

I'm using the https://accounts.google.com/o/oauth2/auth? endpoint to obtain the id_token.
The scopes are openid profile email.
The problem is that when I try to verify that id_token I get iss, azp, aud, sub, email, email_verified, iat, exp, jti. And as you can see there is no any profile info like given_name, family_name, picture.
The official doc says that it should contain profile info:
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
All permissions are granted.
UPDATE
So in case anyone ever needs it.
As Vladimir Serykh mentioned, to get profile info we need to hit the /userinfo endpoint. But this endpoint takes access_token as a Bearer token in a Authorization header, so you need obtain that too.
So basically we need to call the OAuth2 with the response_type='id_token token' query parameter. After that the responseUrl will contain access_token too.
Next you just need to call the https://openidconnect.googleapis.com/v1/userinfo endpoint with a Authorization header set to Bearer your_access_token. You will get a response wiht the profile info:
"sub": "user_id",
"name": "Name Lastname",
"given_name": "Name",
"family_name": "Lastname",
"picture": "pic_url",
"email": "example#gmail.com",
"email_verified": true,
"locale": "en"
Thank you again, Vladimir Serykh
It's not very clear how old the documentation is (by the link you provided) and is it relevant to your case.
I know that different Identity Providers can work slightly different. And I know cases when you should make a separate call with obtained ID token to /userinfo endpoint to get user info.
There is some different Google documentation for Google Identity Platform.
It has description of ID tokens.
https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo
Google ID Tokens may contain the following fields (known as claims):
Notice that it doesn't have always in Provided column. I think that it could be different for different APIs.
The same docs have section "Obtaining user profile information"
It explains where to get the /userinfo endpoint URL and how to call it. In the response you should receive the info you need.
My guess why it's not working in your case is that you are using /tokeninfo endpoint. It's not a part of OpenID Connect standard. It just validates the token and parses it (does the same job as https://jwt.io). And the original ID token doesn't contain that claims for some reason. Therefore /tokeninfo endpoint doesn't return them to you.
But according to Google's documentation and you should use /userinfo endpoint to obtain user info claims.
You can find description of this endpoint in OpenID Connect specification:
https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
5.3 UserInfo endpoint
The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the authenticated End-User. To obtain the requested Claims about the End-User, the Client makes a request to the UserInfo Endpoint using an Access Token obtained through OpenID Connect Authentication.

OAuth: why principal id is different when authenticated in Browser and WinPhone App

I am trying to use Google OAuth authentication for Mobile App hosted in Azure, but getting user ID (SID) in different formats.
When I access the API from browser directly, I'm redirected to Google login page, and after authentication the next request to my API comes with the headers:
"x-ms-client-principal-name":"pavlolissovtest#gmail.com",
"x-ms-client-principal-id":"108491597139717511334",
"x-ms-client-principal-idp":"google",
"x-ms-token-google-access-token":"ya29.Ci9-A-oE8p4vVelYhRKqjMKY6KGxeW4OtXT-KGtBO3AxsiBqiCawn8sxL-qg4msWrw"
In Windows Phone App (authentication with WindowsAzure.MobileServices.MobileServicesClient), when logged with the same account, request comes with different headers:
"x-ms-client-principal-id":"sid:3fc89f071b7cb8f18919614ac46d3636",
"x-ms-client-principal-idp":"google",
"x-ms-token-google-access-token":"ya29.Ci9-AxC3kfrYrV8ssLUkbwFJJYDPsklsUH7r3HG0f6KB_wWzXV9AqE_wGPASiYxcWQ"
So now I have different principal ids for the same user account.
If now I call https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=, for both tokens I get the same result:
{
"azp": "1083509260178-cntp3794bggcs5dtkse0mtbvpqigoa78.apps.googleusercontent.com",
"aud": "1083509260178-cntp3794bggcs5dtkse0mtbvpqigoa78.apps.googleusercontent.com",
"sub": "108491597139717511334",
"scope": "https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
"exp": "1476643317",
"expires_in": "3161",
"email": "pavlolissovtest#gmail.com",
"email_verified": "true",
"access_type": "online"
}
This allows me to identify the user whatewer login option is used, but is it really correct to call googleapis for each request? What is the proper way of identifying the user from headers, or maybe converting one value into another?
And what is the meaning of having these values different?
Thanks for your advice!

Are email, address, and phone scope types supported in AdalJS/openid/oauth2?

I am using the AdalJS v1.0.8 library to authorize users against an Azure AD endpoint, and was wondering if the &scope types for email, address, and phone are supported in AdalJS/openid/oauth2.
My authorization endpoint URL:
https://login.microsoftonline.com/{tenant id}/oauth2/authorize?response_type=id_token&client_id={client id}&redirect_uri={my redirect uri}&state=2af81ff1-89ca-4f23-825d-ca29177c3df5&client-request-id=2f82e417-630b-4318-88ed-c35103046249&x-client-SKU=Js&x-client-Ver=1.0.7&nonce=4c03cbca-03b2-4a53-acc6-1177f499969a&prompt=login&scope=openid+profile+email+address+phone
After the login page appears and the user enters their credentials, the token comes back successfully and I can see the user's profile object when calling AuthenticationContext.getCachedUser(). However, I do not see email, address, or phone information being returned even though these scope types are requested in the &scope query string parameter.
Look inside the profile object. You might find the additional information in there.
{
"sub": "248289761001",
"name": "Jane Doe",
"given_name": "Jane",
"family_name": "Doe",
"preferred_username": "j.doe",
"email": "janedoe#example.com",
"picture": "http://example.com/janedoe/me.jpg"
}

Authenticating to BigQuery REST API via OAuth2 from Node.js

Newbie trying to figure out how to get a Node.js application to authenticate and query Google BigQuery, trying to adapt this CodeLab tutorial from Java. What step might i be missing?
First I create this Oauth2 URL using my clientid:
https://accounts.google.com/o/oauth2/auth?
client_id=1047877053699-den6kbs4v3f2bft6clonsirkj1pc7t6j.apps.googleusercontent.com
&scope=https://www.googleapis.com/auth/bigquery
&redirect_uri=http://localhost:3000/oauth2callback
&access_type=offline
&response_type=code
This successfully reaches Google, which prompts
A third party service is requesting permission to access your Google Account.
Agreeing that generates a second prompt:
Nodejs_Test is requesting permission to:
View and manage your data in Google BigQuery
Agreeing to that, the callback URL is called, with a parameter accessToken.
I think the following url should list tables in my BigQuery project/dataset:
https://www.googleapis.com/bigquery/v2/projects/1047877053699/datasets/visits&accessToken=4%2FC196NizZwlNgWSt5oNqQwendmLNW.0vgUrlGJ6kMRshQV0ieZDApig3NfcgI
But calling with or without the accessToken returns the following message that "Login Required".
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}
I know you can't repeat the code because of permissions, expired tokens, etc. But I wonder what step I might be missing conceptually.
Have you tried sending the accesstoken as an authorization header rather than as a url parameter?
as in
https://www.googleapis.com/bigquery/v2/projects/1047877053699/datasets/visits
Authorization: OAuth Your-access-token-here-not-urlencoded
FYI - looks like you originally used the parameter accessToken in the URL. It should instead by access_token, which looks like it works fine. Of course, Jordan's suggestion of using a Header is better if you're able to do it though-- it's more secure as it's unlikely to get logged in access logs, proxy server logs, etc.

Resources