SCRT-HQ / PSGSuite

Powershell module for Google / G Suite API calls wrapped in handy functions. Authentication is established using a service account via P12 key to negate the consent popup and allow for greater handsoff automation capabilities
https://psgsuite.io/
Apache License 2.0
234 stars 68 forks source link

Can we use Admin API with OAuth? #345

Open nickycupcakes opened 3 years ago

nickycupcakes commented 3 years ago

We are trying to implement a streamlined user creation process where a Powershell script handles both AD and Google user creation. However, we don't want to provide our Helpdesk staff with SuperAdmin privileges - so using Domain Wide delegation and a .p12 file are out (because we can just change the "user" to a SuperAdmin in the command line).

We have been trying to use OAuth in order to lock down privileges a bit - however we cannot access any calls to the Admin API when we use this method. We CAN access the GMail API without issue, so we do not believe that we have anything configured incorrectly. I do see that the Admin API is excluded from OAuth setup on the initial setup page: https://psgsuite.io/Initial%20Setup/

I'm just wondering if anyone HAS had success doing this, and if so, what modifications did you have to make in order to get it working?

phatmandrake commented 3 years ago

Hmm.

What do you mean by the Admin API, what endpoint are you referring to? It sounds like you're not using the PSGsuite module maybe? Or are you trying to use the New-GoogleService Cmdlet for an endpoint that isn't supported by the Modules default cmdlets?

And when you say you are trying to use OAuth, are you saying you are not using a service account, but are trying to authenticate with a normal user account? (both technically use OAuth).

Trying to clarify. I just got done with going to the API rabbit hole so I'm hoping I can help 😄

nickycupcakes commented 3 years ago

Thanks for the response, I appreciate any type of assistance!

We are definitely trying to use the PSGsuite module - specifically the Get-GSUserLicense and New-GSUser functions (so the Admin SDK and the Enterprise License Manager API). We can make it work if we use a .p12 file with domain-wide delegation - that works just fine.

However, we'd like to lock it down so we don't need to use domain-wide delegation. We have switched to trying to authenticate using a normal user account over OAuth. This should allow us to granularly control the admin functions that can be performed using Admin Roles in Gsuite Admin panel (can't delete accounts, for example). However when we move away from .p12 and domain-wide delegation, we lose access to ALL functions that call the Admin SDK or the License Manager API - they start failing no matter which Admin Role we grant in the Admin Console in GSuite. (This is explained on the Initial Setup page, where the "whithout Super Admin Access" APIs are listed - so I'm aware it's a limit of the current functionality of PSGSuite).

We are wondering if there are ways to get around this? Do we have to build a New-GoogleService Cmdlet, like you hinted? (I'm not terribly familiar with that yet, I haven't dug in as deep as you it seems!) If so, what do those look like?

Thanks - and apologies if I'm still not clear enough. I'm not a developer by trade - so my terminologies might be missing the mark.

phatmandrake commented 3 years ago

So I got it working. When you do the initial authorization. It does not prompt you to authenticate all the scopes.

To fix this you will need to:

  1. Revoke the application

This can be done either in the user's profile in the admin panel or here https://myaccount.google.com/permissions if you are the user.

When you do this restart your terminal and it should prompt you to reauthorize:

image

When you go to that link. You pick the user you want to authenticate as and it shows you this list:

image

Notice that there are no scopes for viewing users and managing the domain!

So we just add https://www.googleapis.com/auth/admin.directory.user to the URL.

Which cuz I'm just such a good guy I already did for you below. Just inject your client ID

https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=<CLIENTID_HERE>&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=https://www.googleapis.com/auth/admin.directory.user%20https%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds%20https%3A%2F%2Fmail.google.com%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.settings.basic%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.settings.sharing%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Ftasks%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Ftasks.readonly

image

Much better.

Finish copying the authorization code back to the terminal et voila!

P.S I got this working with a Cloud Identity account so you don't even have to burn a business license if you don't want.

Foggy2 commented 3 years ago

I have just had a need to do this myself.

I found that I was able to modify the New-GoogleService function to include the extra scopes.

I simply added them to the $ClientSecretsScopes array on Line 109.

FISHMANPET commented 2 years ago

This is intriguing to me, but I think implementing some kind of fix might upend a lot of the assumptions that currently exist around user authentication and the New-GoogleService function.

I'm not an admin of our Google org, but it just occurred to me that we might have a test domain I could use to play around.

From @Foggy2's comment, I'm wondering if maybe we need to store some scopes along with the oauth information? I'm not sure what the impact would be of adding that particular admin scope there for everyone, especially when their oauth client isn't granted the permission in the API.

Foggy2 commented 2 years ago

I should add to this that I did do some further testing on my end a few months ago using a regular user account that has delegated access to only a couple OUs.

I found that I was unable to list all of the required scopes in the $ClientSecretsScopes array as this caused the browser window to fail. I assume this is due to the OAuth request being a HTTP GET and the query string was too long. When I limited the scopes to only the ones required for the commands I was testing it did work quite well.

So you would definitely need some kind of logic to handle specifying and tracking only the required scopes. This seems like a rather large change and has the potential to cause significant issues.