How to get Google profile info including custom fields from an Apps Domain user?

gdata, google-app-engine, google-apps, google-apps-script

Solution

Any non-admin user can access the GAL programmatically, see:

https://github.com/google/gfw-deployments/blob/master/apps/shell/gal/gal_feed.sh

I don't believe this API call is documented or supported officially but it works even with OAuth authentication rather than the example's ClientLogin (tested on the OAuth 2.0 playground with a non-admin user and the standard `https://www.google.com/m8/feeds/` Contacts scope).

Note that the Global Address List is a compilation of user profiles, groups and shared contacts. You'll need to parse it out to find the user(s) you wish to get department information for.

Problem

Using the user.profile and user.email scope and the /oauth2/v2/userinfo feed doesn't seem to return any custom fields (in my case Department) or phone numbers. These fields show up in the Domain Shared Contacts directory. Is there perhaps an Apps Domain specific feed URL something like /oauth2/{DOMAIN}/v2/userinfo ? Does the API/Service not support any custom fields yet? Is there a way to fudge this into working? Read access to your own Apps Domain Shared Contacts profile that's connected to your account shouldn't be so difficult. I'd prefer a non-admin solution because my domain uses Common Access Cards w/ SAML authentication so I can't just store admin credentials (user : password) in an App Engine app and access the /m8/ feed. If there's a flow to access Domain Shared Contacts (with custom fields) with a beforehand authorized consumer key and secret I'd be interested in the instructions for getting that to work. EDIT Jay Lee nailed it "https://www.google.com/m8/feeds/gal/{domain}/full" Here's the proof of concept script using Google Apps Script (I'll add the final OAuth2 version when I finish it) ``` function getGal(email, passwd, domain) { var res = UrlFetchApp.fetch("https://www.google.com/accounts/ClientLogin", { contentType: "application/x-www-form-urlencoded", method: "post", payload: { "Email": email, "Passwd": passwd, "accountType": "HOSTED", "service":"cp" } }); var auth = res.getContentText().match(/Auth=(.*)/i)[1]; Logger.log("Auth: " + auth); res = UrlFetchApp.fetch("https://www.google.com/m8/feeds/gal/" + domain + "/full", { method: "get", headers: { "Authorization": "GoogleLogin auth=" + auth, "GData-Version": "1.0" } }); Logger.log(res.getHeaders()); Logger.log(res.getContentText()); } ``` EDIT 2 OAuth version that returns JSON and only the info for the user accessing the script. ``` function googleOAuthM8() { var oAuthConfig = UrlFetchApp.addOAuthService("m8"); oAuthConfig.setRequestTokenUrl('https://www.google.com/accounts/OAuthGetRequestToken?scope=https://www.google.com/m8/feeds/'); oAuthConfig.setAuthorizationUrl('https://www.google.com/accounts/OAuthAuthorizeToken'); oAuthConfig.setAccessTokenUrl('https://www.google.com/accounts/OAuthGetAccessToken'); oAuthConfig.setConsumerKey('anonymous'); oAuthConfig.setConsumerSecret('anonymous'); return {oAuthServiceName:"m8", oAuthUseToken:'always'}; } function getGal(domain) { res = UrlFetchApp.fetch("https://www.google.com/m8/feeds/gal/" + domain + "/full?alt=json&q=" + Session.getActiveUser().getEmail(), googleOAuthM8()); Logger.log(res.getHeaders()); Logger.log(res.getContentText()); } ```

Original source