G Suite Service Account Fails Requests But Delegation Works? - oauth-2.0

I have followed the documentation for creating a G Suite Service Account. The following works fine to emulate a given user in my domain:
def create_directory_service(user_email):
credentials = ServiceAccountCredentials.from_json_keyfile_name(
SERVICE_ACCOUNT_FILE_PATH,
scopes = SCOPES)
credentials = credentials.create_delegated(user_email)
return build('admin', 'directory_v1', credentials=credentials)
However, I want to be able to just use the service account to access domain information without needing to emulate a particular user. But if I pass in the service account's email address (as given in its key file), I just get HttpError 503: "Service unavailable. Please try again".
I've added the service account's email address as a Service Account Admin, but it still doesn't work. Again, delegation works fine, but not using the service account directly.
Does anyone know what I'm missing?

To use Directory API, you must use delegation to impersonate a user in the domain, that can use Directory API (so usually an admin).

Related

Getting Meeting IDs from Events in an M365 Group

I've been tasked with a project to get attendance information from specific types of Teams. I have a service account that is already a member of these Teams, however it is unable to access an endpoint needed to resolve JoinWebUrls to meetingIDs (See example #3, 'Retrieve an online meeting by JoinWebUrl').
I have done the following thus far:
Create a new App Registration and assigning it 'OnlineMeetings.Read.All' as an Application permission (this process needs to run as a script, meaning that Delegate permissions won't work here)
Create a new Application Access Policy, assigned the aforementioned App Registration's App ID to it, and granted it to the service account.
Signed into MS Graph as the service account (using the 'password' grant_type) and retrieved the 'events' within the Team (via /v1.0/groups/$GroupID/events)
Extracted the JoinWebURL parameter from each of those events.
Step 5 would be to resolve the meetingID from the JoinWebURL, however when I all of the following requests fail:
GET /v1.0/me/onlineMeetings?$filter=JoinWebUrl eq '$JoinWebURL' (as the service account, which should be able to interact with the meeting)
GET /v1.0/users/$ServiceAccountObjectID/onlineMeetings?$filter=JoinWebUrl eq '$JoinWebURL' (as the service account to access it's own object's meetings, however this does seem to be the endpoint for Application permissions rather than Delegate permissions)
GET /v1.0/users/$ServiceAccountObjectID/onlineMeetings?$filter=JoinWebUrl eq '$JoinWebURL' (using the App Registration mentioned earlier, signing in with the 'client_credentials' grant_type)
GET /v1.0/me/onlineMeetings?$filter=JoinWebUrl eq '$JoinWebURL' (as the App Registration trying to access any meeting, however this does seem to be the endpoint for Delegate permissions rather than Application permissions)
Basically, I'm stuck. Is there something obvious that I'm missing? I'm also considering raising a support call with Microsoft, to see if the behaviour I'm experiencing is merely a bug.
Thanks in advance.
Events and online meetings are two different API's, you have created an event and trying to get online meeting details. That's the reason you are getting those errors. If you want to get event details please try this document.

Upsource with GitLab as Oauth

I'm running GitLab on local address http://192.168.0.18/. Upsource is running on http://192.168.0.11/.
I've added Upsource application as admin on GitLab. I've set client id and secret token as GitLab said. Authorization is set to http://192.168.0.18/oauth/authorize, token to http://192.168.0.18/oauth/token and user data to http://192.168.0.18/api/v4/user (according to GitLab documentation). In field mappings, I've set User ID to "id" and both e-mails to "email".
Then, on logging page of Upsource, I've oath authentication icon. After clicking on it, GitLab requires logging and user has to authorize application for its account:
Authorization required
Authorize Upsource to use your account?
You are an admin, which means granting access to Upsource will allow them to interact with GitLab as an admin as well. Proceed with caution.
This application will be able to:
Access your API
Read user information
Hovewer, after clicking authorize button, Upsource displays info: Authentication failed. Check your credentials and try again.. What have I set wrong? Field mappings?
Oh, I've found the answer. As happens often, I was fighting with this a good amount of hours and just after I asked this question, I've got idea to run this on my own. Rubber duck method, I guess...
As I suspected, the problem was in field mappings.
I looked in Network tab in Chrome and there was this response:
http://192.168.0.11/hub/auth/login?response_type=token&client_id=[CLIENT_ID]&redirect_uri=[REDIRECT_URI]&message=hub-auth-failed&developer_message=getValueByPath%28json%2C+aut%E2%80%A6userIdPath%29%21%21.textValue%28%29+must+not+be+null
I've manually went through all Gitlab workflow and then I could log in - and after running http://192.168.0.18/api/v4/user endpoint, I've got user data:
{"name":"username","username":"username","id":3,"state":"active","avatar_url":"http://www.gravatar.com/avatar/94232f2d1f8bb2fe940de439a4df1014?s=80&d=identicon","web_url":"http://debian/username","created_at":"2017-03-25T22:28:21.375Z","is_admin":true,"bio":null,"location":null,"skype":"","linkedin":"","twitter":"","website_url":"","organization":null,"last_sign_in_at":"2017-03-25T22:28:21.487Z","confirmed_at":"2017-03-25T22:28:21.376Z","email":"username#username.username","color_scheme_id":1,"projects_limit":100000,"current_sign_in_at":"2017-03-25T22:36:31.853Z","identities":[],"can_create_group":true,"can_create_project":true,"two_factor_enabled":false,"external":false}
The problem was in setting ID field name. As we can see in above JSON data, id field should be mapped to name/username, not id itself.
After this change I could sucessfully login into Upsource.

How to change the google API "service account" name/email address

I am using the Google API to create a spreadsheet on google drive.
My app has a link that says 'Download To Google Doc'
The app sends a file to google docs and shares it with the user.
The user can then see it in google docs.
This all works good.
The problem is the identity of the service account sharing the doc.
It is a generated id. I want it to be branded to my app.
Is this possible?
-
You can't change the service account email address, nor can you supply a real world user name to it. The service account email address is created by Google in the Google Developer console.
The only way to change the email address would be to delete it and create a new one but again you would be stuck with the one Google Created. I suspect that the client id and email address are a pair used for identification of your application. Similar to client id and client secret, but I cant verify that.
I do see your point it would be nice if we could.
Google Service Accounts do allow you to impersonate an existing user account (for some services). I haven't tested it on Google Drive, but I have used it with the Webmaster tools API. The instructions can be found here: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
To sum them up, when creating the service account credentials you can specify the "sub" parameter with "The email address of the user for which the application is requesting delegated access." The account you're requesting access for must exist and have permission to access to the services you're requesting.
In the link above Google provides examples for Java, Python and HTTP/REST, here's the Python example:
credentials = SignedJwtAssertionCredentials(client_email, private_key,
'https://www.googleapis.com/auth/sqlservice.admin',
sub='user#example.org')
I'm using the Ruby google-api-client gem (0.9.pre3) and the ServiceAccountCredentials constructor does not pass the 'sub' parameter to its parent class so it has to be specified in another step:
client = Google::Auth::ServiceAccountCredentials.new(json_key_io: json_key_io, scope: scope)
client.update!(sub: 'user#example.org')
client.fetch_access_token!
service = Google::Apis::WebmastersV3::WebmastersService.new
service.authorization = client
Using this code I can authenticate using my service account and I have access to the sites

Using Email Settings API from app engine with service account

I'm trying to use the Email Settings API from within a google marketplace app. Because I need all the logic to happen offline (in a cron job). I'm using an app engine Service Account, but when I'm trying to actually change the email settings for the users of the domain that installed it I'm getting this error:
You are not authorized to access this API.
Error 403
this is the scope: https://apps-apis.google.com/a/feeds/emailsettings/2.0/
I'm probably missing something, but I couldn't find the right docs to show me the way. How would I go about implementing an app that accesses the email settings even when the admin is offline?
You need to set the prn attribute to address of an admin account.
Examples for the directory API are at:
https://developers.google.com/admin-sdk/directory/v1/guides/delegation#instantiate_an_admin_sdk_directory_service_object
In terms of accessing the Email Settings API, you're really unlikely to get people to give you Service Account access to their domain.
On the other hand, if it's your domain (and thus you can add Service Account access), couple of pointers below:
What is important is that you add the following to the header:
"Authorization" = "Bearer <your_token>"
(note the very specific syntax - "Bearer+<1 space>+", as per https://www.rfc-editor.org/rfc/rfc6750 section 2.1)
"Content-Type" = "application/atom+xml"
(important for POST/PUT/DELETE requests, doesn't matter for GET)
that should get you up and running.

Creating Admin Accounts for Domains Created from Reseller API

I am trying to automate the entire process of creating a google apps account through my company's reseller account with google, without any human having to manually enable anything.
Here's a quick scenario of what I am doing.
Create Customer (Domain) with Reseller API
Create Subscription with Reseller API
Create Admin Account for the Sold Domain
I am having trouble automating step 3.
There are 2 different APIs that can accomplish this tast, Provisioning (depricated) and Directory.
I have already successfully created user accounts with the Directory API, but this step requires you to enable API access for that domain, and that can only be done manually by a human - So thats a break in automation flow, and wont work for what I am trying to accomplish.
I was instructed by google tech support to use the Provisioning API, wich is deprecated, because it supposedly allows you to create an admin user without the need to enable the API access manually per domain. When I attempt to do this, I face this error:
Uncaught exception 'Zend_Gdata_App_HttpException' with message 'Expected response code 200, got 403 <HTML> <HEAD> <TITLE>You are not authorized to perform operations on the domain mydomain.com</TITLE>
Here's the code im attempting to run:
// .....
$customerid = "somedomain.com";
$client = Zend_Gdata_ClientLogin::getHttpClient("mylogin#foo.com", "mypassword",Zend_Gdata_Gapps::AUTH_SERVICE_NAME);
$gdata = new Zend_Gdata_Gapps($client, $customerid);
$gdata->createUser('Admin', 'Firstname', 'Lastname', 'somerandompassword', TRUE);
//......
When I consulted google tech support, they told me I needed to enable the provisioning api following the same instruction I posted earlier (enable api access per domain). I have done this on both my reseller domain, and the customer domain Im trying to provision on (just to test, becasue the entire point is to be able to make an admin account WITHOUT enabling it on the customer domain.) - But it still returns this error.
Here's my settings -- as you can see, its enabled.
In google's docs, under "Enabling the Provisioning API", it has some instructions, but they appear to be out of date and dont really reflect sections available in the current google apps admin panel.
Im at a loss. Am I missing something obvious, or is it just not possible to do at this time?
Just for reference, I have found a few other people asking a similar question, but with less detail:
Google Reseller Customer Admin User Creation Admin SDK How
How to create the domain administrator of a Google Apps domain purchased via the reseller API
EDIT: Added image showing settings, and code sample.
try to delete "TRUE" parameter in createUser , it's works for me.
$customerid = "sampledomain.com";
$client = Zend_Gdata_ClientLogin::getHttpClient($email, $password, Zend_Gdata_Gapps::AUTH_SERVICE_NAME);
$gdata = new Zend_Gdata_Gapps($client, $customerid);
var_dump($gdata->createUser('trial', 'Firstname', 'Lastname', 'somerandompassword'));
in Google app console
domain settings ->user settings
check the box "enable API access"
in Google app console --> advanced tools --> Manage third party OAuth Client access
Add the scope :
https://apps-apis.google.com/a/feeds/user

Resources