Reputation: 103
I am developing a user page to allow managers to create users by selecting a new user from a drop down list. I will like to populate the drop down with company users from Google directory. So this user page will only be accessible after login.
As I read, Google Admin SDK accesses private user data and needs access token to work. I will like to use this Google directory API users.list method to retrieve users from Google directory. I have a look at the example from quick start for javascript. The issue is this script requires the user to login again, and this would confuse the admin users.
On the login page, I use the google the HTML sign-in button to render Login page, returning the JWT token to our webapp's login endpoint. The returned token credential contains login user's email profile but no access token.
Could someone please advise how to modify below on so that I can retrieve users on the user page.
async function initializeGapiClient() { await gapi.client.init({
apiKey: API_KEY,
discoveryDocs: [DISCOVERY_DOC],
});
await listUsers();
}
async function listUsers() {
let response; try {
const request = {
'customer': 'my_customer',
'maxResults': 10,
'orderBy': 'email',
};
response = await gapi.client.directory.users.list(request);
} catch (err) {
document.getElementById('content').innerText = err.message;
return;
}
const users = response.result.users;
}
Upvotes: 1
Views: 1478
Reputation: 116868
The main issue you are having is that you are using JavaScript. Client side JavaScript does not have the ability to store login information for future use. Which means that every time your users return they will need to login and authorize your application again.
I would suggest that you switch to a server sided language which will allow your users to login and for you to store a refresh token for them enabling you to request a new access token when ever you need to. node.js for example would work as well.
Remember though only users who have admin access on your workspace account are going to be able to do this the user will need to have access
The following is a quick example for node.js, its for an installed app but will show you how things need to be put together for refreshing your access token.
// npm install googleapis@105 @google-cloud/[email protected] --save
// npm install googleapis
const fs = require('fs');
const path = require('path');
const process = require('process');
const {authenticate} = require('@google-cloud/local-auth');
const {google} = require('googleapis');
// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/admin.directory.user.readonly'];
// Token File Name
const TOKEN_FILE = 'token.json'
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = path.join(process.cwd(), TOKEN_FILE);
const CREDENTIALS_PATH = 'C:\\Development\\FreeLance\\GoogleSamples\\Credentials\\Workspace-Installed-TestEverything.json';
// the workspace customer id found in admin on Google Workspace
const WORKSPACE_CUSTOMER_ID = '[REDACTED]'
/**
* Reads previously authorized credentials from the save file.
*
* @return {Promise<OAuth2Client|null>}
*/
async function loadSavedCredentialsIfExist() {
try {
const content = fs.readFileSync(TOKEN_PATH,{encoding:'utf8', flag:'r'});
const credentials = JSON.parse(content);
return google.auth.fromJSON(credentials);
} catch (err) {
return null;
}
}
/**
* Serializes credentials to a file compatible with GoogleAUth.fromJSON.
*
* @param {OAuth2Client} client
* @return {Promise<void>}
*/
async function saveCredentials(client) {
const content = fs.readFileSync(CREDENTIALS_PATH, {encoding:'utf8', flag:'r'});
const keys = JSON.parse(content);
const key = keys.installed || keys.web;
const payload = JSON.stringify({
type: 'authorized_user',
client_id: key.client_id,
client_secret: key.client_secret,
refresh_token: client.credentials.refresh_token,
});
await fs.writeFileSync(TOKEN_PATH, payload);
}
/**
* Load or request or authorization to call APIs.
*
*/
async function authorize() {
let client = await loadSavedCredentialsIfExist();
if (client) {
return client;
}
client = await authenticate({
scopes: SCOPES,
keyfilePath: CREDENTIALS_PATH,
});
if (client.credentials) {
await saveCredentials(client);
}
return client;
}
/**
* Lists the names and IDs of up to ten users on Google Workspace.
* @param {OAuth2Client} authClient An authorized OAuth2 client.
*/
async function listUsers(authClient) {
const service = google.admin({version: 'directory_v1', auth: authClient});
const res = await service.users.list({
customer: WORKSPACE_CUSTOMER_ID,
pageSize: 10,
fields: 'nextPageToken, users(id, name)',
});
const users = res.data.users;
if (users.length === 0) {
console.log('No users found.');
return;
}
console.log('users:');
users.map((user) => {
console.log(`${user.name.fullName} (${user.id})`);
});
}
authorize().then(listUsers).catch(console.error);
In google workspace under the user, You can check if they have admin access.
Upvotes: 1