I am building an email client, attempting to perform a search against the Graph API users endpoint, similar to what was possible in Exchange Web Services via SOAP.
In EWS with ResolveNames, the server would return details (i.e. job title, office, phone, etc.) from only the authenticated user's organization scope similar to an address book search from an email client (i.e. OWA).
Using the Graph API (which based on what I have found is the recommended API for next generation O365 email apps) the user details return null:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [],
"displayName": "John Smith",
"givenName": "John",
"jobTitle": null,
"mail": "john#contoso.com",
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": null,
"surname": "Smith",
"userPrincipalName": "john#contoso.com",
"id": "xxxx"
}
I have requested the following scopes: User.Read, User.ReadBasic.All, Calendars.Read, Calendars.ReadWrite, Calendars.Read.Shared, Calendars.ReadWrite.Shared, Contacts.Read, Contacts.Read.Shared, People.Read
I have attempted several calls, but just a simple request for organization users demonstrates the issue:
https://graph.microsoft.com/v1.0/users
Based on the documentation, it looks like this information is only visible with Directory.AccessAsUser.All granted--an Admin level scope which is prohibitive\impractical for a general use application.
Is there a way to perform a simple address book search with limited user details using the Graph API without admin consent? If not, is there another API or method I can use? Or, does Microsoft have plans to extend the Users endpoint to include this basic information?
If the user is authenticated, it seems appropriate to allow an address book\GAL\user search.
The User.ReadBasic.All scope only provides access to a (no pun intended) basic set of user properties:
Allows the app to read a basic set of profile properties of other users in your organization on behalf of the signed-in user. This includes display name, first and last name, email address, open extensions and photo. Also allows the app to read the full profile of the signed-in user.
In order to read the complete set of user properties, you need (at a minimum) to request User.Read.All:
Allows the app to read the full set of profile properties, reports, and managers of other users in your organization, on behalf of the signed-in user.
This is a lot more restrictive scope than the Directory.AccessAsUser.All scope you mentioned, but it does require Admin Consent before normal users can consent to it. There is no mechanism for getting around the Admin Consent prerequisite.
Related
Using the Microsoft Graph API v 1.0, how can I retrieve the user's MFA details?
For example, if I have an email based sign-in/sign-up policy with phone/SMS MFA, how can I see the phone number entered by the user? (and also set update it)
I know if I select 'identities' in the GET /users method I can see the email they've signed up with, but not the phone number they set for MFA. (https://learn.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0)
Of course I'm looking for all the mfa settings: mfa phone number, mfa email address, is mfa set, etc.
Hopefully there is some kind of extension attribute that contains this that I can select, and set on creation, but I cannot find documentation on this.
[UPDATE]
In the Azure portal, I can see the entered data if I go to user > profile > authentication methods. So I tried accessing the authentication relationships on the user. but it didn't provide any details (all empty arrays) https://learn.microsoft.com/en-us/graph/api/resources/authentication?view=graph-rest-1.0
There's a write-up here.
e.g:
GET https://graph.microsoft.com/beta/users/objectID/authentication/methods
I have a Google Spreadsheet and I need to get the current user's email address in it.
I can't use GAS + Session.getActiveUser().getEmail() since that requires auth/permissions.
So my thought is to use one of the IMPORT functions to import data from some URL/API that'll return the current user's email address.
People api and user profile info
The direct way to get a users email address is to request the email scope and go though the people api.
The people get method will return the users email address if you have authroized the user with the email scope.
Again the draw back to this method is you need to request permission of the user to see their email address.
Drive api current users email
Some of the Google apis actually return the email without requiring that you ask the users permission to see their email.
If you are requesting one of the google drive scopes which you may be if your using a google sheet api. Calling about get will return the users email address
{
"kind": "drive#about",
"user": {
"kind": "drive#user",
"displayName": "Linda Lawton",
"photoLink": "https://lh3.googleusercntent.com/a-/AOh14GhroCYJp2P9xeYeYk1npchBPK-zbtTxzNQo0WAHI20=s64",
"me": true,
"permissionId": "030588225573437243",
"emailAddress": "XX#gmail.com"
When using the Graph Explorer, I could use the 'List People' API like so:
https://graph.microsoft.com/beta/users/<user id>/people
Where <user id> can be any user in the organization.
However, when I build my own app, I could only call the List People API on the logged in user. Calling it on another user gets me a permission denied response.
What Scope should I use so I can use List People on any users?
According to the documentation for the List People API
"The following scopes are required to execute this API: People.Read; People.ReadWrite"
But People.Read only "Allows the app to read a ranked list of relevant people of the signed-in user." and People.ReadWrite doesn't exist on the list of Permission scopes.
Try using the scope User.ReadBasic.All which allows you to get all users in the organization - but not all properties however.
Some resources:
https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/users
https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/user_list
https://msdn.microsoft.com/en-us/library/azure/ad/graph/howto/azure-ad-graph-api-permission-scopes
This call type needs People.Read.All which must be Admin consented for your app in order to call it.
Docs are here: MS Graph : List People
Using the Google+ api I am able to fetch all the information about user profile and the way I'm doing it is by calling a GET on the following address:
https://www.googleapis.com/plus/v1/people/11812536713708...432
?key=AIzaSyC_bs...gds353le
Here I'm putting user profile id (google id of the user) and my api key.
Now there are two cases:
1) user set up a google+ profile before and then I'm getting a json file with all necessary data (such as his profile photo, name, etc.)
2) user didn't set up a google+ profile before and then I'm getting json file as follows:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "notFound",
"message": "Not Found"
}
],
"code": 404,
"message": "Not Found"
}
}
So in a situation when user doesn't have a google+ account currently I'm unable to fetch his photo. Is there a way of obeying it and somehow fetching his profile details not from google+?
In my ios app I'm using a google sign in feature and they provide a possibility of fetching data for the signed in user (here are some details https://developers.google.com/identity/sign-in/ios/people#retrieving_user_information ) and when I use it and log in to my app with the account that does not have the google+ activated, I'm still able to fetch that user's name, photo, etc. It does not come from google+, in this case it comes from the GIDGoogleUser object. But I can construct this object only when user provides me his username and password.
So is there a way of fetching that data from any Google Api by providing a google user id and api key?
Try using:
https://www.googleapis.com/userinfo/v2/me
you can test this using API Explorer. At minimum, your OAuth token needs the profile scope.
There is an API provided by http://www.avatarapi.com/ which returns the user's name and profile pic based on Google's public info.
It can be called via SOAP or HTTP at this API endpoint:
http://www.avatarapi.com/avatar.asmx
One of the benefits of this API is that it does not require the user to be authenticated with Google, so this could get around your issue where the user does not have a Google+ account.
I'm following the client side authentication as described at https://developers.google.com/accounts/docs/OAuth2UserAgent
I am routinely signed on to multiple Google accounts. Normally, the flow will prompt me to choose which account I want to authenticate with. However there are sometimes instances where it assumes the first account I signed in with, which is not the account I wish to use.
When users register with my service, they do so with a specific email address (and google id).
How do I qualify the oauth dialogue such that it will always take place using only the specified user?
On https://developers.google.com/drive/about-auth I can see a comment...
Note: If you want to use the user_id parameter to select the current user from
(potentially) multiple logged-in accounts,
also add https://www.googleapis.com/auth/userinfo.email.
The implies that there is a user_id parameter I can include in the oauth call, but I can't see it documented anywhere, and there is nowhere in the Javascript API where I can inject a user_id.
Add the user_id parameter to your Authorization URI.
gapi.auth.authorize({..., user_id: 'ali#gmail.com'}, handleAuthResult);