Google Calendar with G Suite account insert get 403 - calendar

I need to use G Suite account to insert a calendar include a hangout meet
but I can't even insert the event, I always get the 403 response
403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "calendar",
"message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority.",
"reason" : "forbiddenForServiceAccounts"
} ],
"message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority."
}
I use the GCP p12 file and the service account to do the calendar.
I also click the Enable G Suite domain-wide delegation box and add my clientId and scope of
https://www.googleapis.com/auth/admin.directory.resource.calendar,
https://www.googleapis.com/auth/calendar.events
at G Suite Admin console
What may be the problem!?
By the way, do I need to set the OAuth consent screen!? I already save it, but not been approve by google.
Can anyone help pls!!
In the begining I get credentials by the following code
credentials = new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(JSON_FACTORY)
.setServiceAccountId(CalendarEntity.CALENDARID)
.setServiceAccountPrivateKeyFromP12File(new File(P12FILEPATH))
.setServiceAccountScopes(Collections.singleton(CalendarScopes.CALENDAR)).build();
And then I add (my G Suite account)
.setServiceAccountUser("xxx#xxx.com.tw")
it response
401 Unauthorized
How can I slove this!? thx

You are missing impersonation.
The purpose of granting domain-wide authority to a Service Account is for these accounts to be able to access data on behalf of users in the domain.
If you grant it domain-wide authority but are not "impersonating" any account, the Service Account is acting as if you hadn't granted this authority: it is trying to access its own Calendars, Drive files, etc., or in this case, trying to insert an Event: something which the Service Account cannot currently do, as I guess you already know.
When the Service Account impersonates another user in the domain (that is, when it acts on behalf of the user), the Service Account can access the resources this user can access. Nothing more, nothing less. What makes delegation useful is that it can do this with any user in the domain.
To impersonate another user, you have to specify this user's email address. I don't know which library you are using, if any, but here you can see how to impersonate another user with Python, Java, and plain HTTP/REST. Refer to this answer if you need to do it in the Node.js library. If you are using another library, look for the corresponding method in the library documentation.
Reference:
Delegating domain-wide authority to the service account

Related

Microsoft OAuth authorization for specific user roles

I have to limit which users can access an Azure App. For now, only Global Admins can access using this link:
login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=client_id_goes_here&scope=user.read.all&response_type=code&redirect_uri=https://myredirectbacklink.com/aad/auth&response_mode=query&state=portal&prompt=consent
After redirect back I get Token using
https://login.microsoftonline.com/common/oauth2/v2.0/token and the query contains the same scope as the authorized link.
The flow of the app is the same as documented in Microsoft identity platform and OAuth 2.0 authorization code flow.
My problem is that client wants to allow Billing Admins to access their app. I went through all Graph Permission Scopes, but could not find any related to Billing Admin.
My knowledge of Microsoft's authorization is somewhat limited. I do know that limitations are done by scope. But if it's just link change or is it in Authentication App in Azure (there is one but I don't know how it's related to actual login permissions).
Should I look in a different direction or is it just simply changing the link? Microsoft's documentation didn't help a lot because it's mostly about calendars and other simple stuff.
Careful, requesting a permission that normally requires admin consent and causing the user consent prompt is not the proper way to ensure the user signing in is actually an admin. A non-admin user could simply modify the URL to scope=User.ReadBasic.All and remove prompt=consent. If the user is allowed to consent for User.ReadBasic.All (which is true in many organizations), they'd be able to continue the sign-in. (Or if the organization had granted admin consent for "User.Read.All", the non-admin user would only need to remove prompt=consent.)
If you need to ensure the user is an administrator, you need to explicitly check for directory role assignments.
You can choose from one of three different ways to do this:
You can configure your app to receive the wids claim, which will include the role template IDs of the directory roles for which the user has an active assignment. This is probably the simplest approach.
Using the Azure portal, you can do this under App registrations > (choose your app) > Token configuration > + Add groups claim. You must include "Directory roles" in your selection:
Another option is to a Microsoft Graph API request to check which of a given list of directory roles the user has been assigned:
POST https://graph.microsoft.com/v1.0/me/checkMemberObjects
Content-type: application/json
{
"ids": [
"fdd7a751-b60b-444a-984c-02652fe8fa1c",
"b0f54661-2d74-4c50-afa3-1ec803f12efe"
]
}
A third option is to make a Microsoft Graph API request to list the directory role assignments granted to the user:
GET https://graph.microsoft.com/beta/roleManagement/directory/roleAssignments
?$filter=principalId eq '{id}'
All three of these approaches involve using directory role template IDs to identify the directory role you are checking for. They're all listed here: https://learn.microsoft.com/azure/active-directory/roles/permissions-reference
Some examples you may be interested in:
Application administrator: 9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3
Cloud application administrator: 158c047a-c907-4556-b7ef-446551a6b5f7
Global administrator: fdd7a751-b60b-444a-984c-02652fe8fa1c
Privileged role administrator: e8611ab8-c189-46e8-94e1-60213ab1f814
Billing administrator: b0f54661-2d74-4c50-afa3-1ec803f12efe
(I included the first four because those are the directory roles which would, by default, be allowed to grant consent for User.Read.All.)
If someone needs solution and uses php:
You can use https://github.com/microsoftgraph/msgraph-sdk-php
$accessToken = 'token from redirect back, called access_token';
$body = [
"ids" => [
"fdd7a751-b60b-444a-984c-02652fe8fa1c",
"b0f54661-2d74-4c50-afa3-1ec803f12efe"
]
];
$graph = new Graph();
$graph->setAccessToken($accessToken);
$user = $graph->createRequest("post", "/me/checkMemberObjects")
->attachBody($body)
->execute();

Gmail Forwarding api says forbidden

I was going through the api doc for setting forwarding address via gmail Apis
https://developers.google.com/gmail/api/reference/rest/v1/users.settings.forwardingAddresses/create
I am getting the following error when trying to access this api.
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Access restricted to service accounts that have been delegated domain-wide authority",
"reason" : "forbidden"
} ],
"message" : "Access restricted to service accounts that have been delegated domain-wide authority",
"status" : "PERMISSION_DENIED"
}
If there is a way to access this api? Few other doubts I have:
Can this be used for any personal #gmail.com accounts?
Can this be also used for any gsuite domains like #example.com?
This is not possible
At least for accounts outside a domain that you administrate
If I understand correctly, you wish to make an app that will ask for a users permission to allow your app to set up email forwarding for them via the API.
The listing in the docs for the scope: https://www.googleapis.com/auth/gmail.settings.sharing which is required for that endpoint says:
Operations guarded by this scope are restricted to administrative use only. They are only available to Google Workspace customers using a service account with domain-wide delegation.
This is as much as security measure as anything. Which means that what you are trying to do is not possible, unless it was for members of your domain only.
It will not work for gmail accounts or other domains. You need to authorise it properly.
If you wanted to get it working for your domain, your first step needs to be getting a service account working, this is a good starting point.
References
OAuth Scopes
Service Accounts

How to solve "NoPermissionsInAccessToken" returned by Microsoft Graph when reading calendar or sending mail

Within our department we have a Classic ASP website that has been using our corporate Google accounts for authentication and to insert events into our Google Calendars. The organisation has just switched from Google to Office 365 and I'm trying to switch the code to use Outlook instead - with no success.
I can use the access token to GET https://graph.microsoft.com/v1.0/me and see the basic profile, but if I try to read calendar events or send an e-mail I see the message:
"error": {
"code": "NoPermissionsInAccessToken",
"message": "The token contains no permissions, or permissions can not be understood."
I created an Azure account with my personal Microsoft account and added an application. I added my colleagues and my corporate account as guest users. I set the permissions required and did the admin consent thing:
I then followed the steps on this page.
I first visit https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/authorize, including the following query items:
client_id={client id}
response_type=code
redirect_uri={our URL}
response_mode=query
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
state={number}
This returns a "code", which I send to https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/token, including:
grant_type=authorization_code
client_secret={client secret}
client_id={client id}
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
state={same number as above}
redirect_uri={same URL as above}
code={code returned from /authorize}
This returns the id, access and refresh tokens. If I decode the access token using https://jwt.ms/, it seems to contain the appropriate audience and scope:
"aud": "https://graph.microsoft.com"
"scp": "Calendars.ReadWrite email Mail.Send openid profile User.Read"
...although I notice that there is no "roles" entry, which I see in some of the documentation. Is that an issue?
I then send the access token to https://graph.microsoft.com/v1.0/me with the following headers:
"Authorization", "Bearer {access token}"
"Host", "graph.microsoft.com"
"Content-Type", "application/json"
"Prefer", "outlook.timezone Europe/London"
That will return my e-mail address, etc., but if I change the URL to anything else, such as /me/photo/$value, /me/calendar/events, or try to send an e-mail I'm told that there are no permissions in the token.
I see that there are other similar questions, but they are mostly for the client_credentials flow (I'm not sure that makes any difference), and none of the answers has helped me resolve my problem.
Can someone please let me know if I've obviously missed anything - or I'm going about this in the wrong way to access Graph data on the client side? It seemed so straightforward with Google, but I'm finding the Microsoft documentation and examples a bit less detailed.
Adding guest users is meaningless.
What you have done is Admin consent for the Azure AD with your personal Microsoft account.
What you actually need to do is Admin consent for the target Azure AD/ O365 tenant.
Construct a consent link as following:
https://login.windows.net/{tenant ID of the target Azure AD}/oauth2/authorize?response_type=id_token&client_id={client ID}&redirect_uri={reply url}&response_mode=form_post&nonce=a4014117-28aa-47ec-abfb-f377be1d3cf5&resource=https://graph.microsoft.com&prompt=admin_consent
Access it in a browser and log in with an admin account of target Azure AD.
Another issue is that you are using Get access on behalf of a user. So you have to assign Delegated permissions rather than Application permissions in the Azure AD app.

How to select some users for impersonalize Gsuite service account

I have 3 email directions (in GSuite) for automatic send email, let's say:
emai1#domain.com
email2#domain.com
email3#domain.com
Actually I use a Service Account with Domain-wide Delegation enable, and with Gmail API Scope: https://www.googleapis.com/auth/gmail.send
I use service account for upload documents to Drive.
My code works as expected, I can send emails with Gmail API with this auth code:
credentials = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: f,
scope: g_scope
)
credentials.sub ='email1#domain.com'
credentials.fetch_access_token
My problem is that I want to restrict the users to only three. There is a way to select users for Service Account Delegation?
My problem is that I want to restrict the users to only three. There
is a way to select users for Service Account Delegation?
No, you cannot restrict the service account to being authorized for only certain user accounts. You can restrict the service account to specific permissions (read email, send email, etc.).
From a security posture, you want to be careful with delegated accounts.
Note: Although you can use service accounts in applications that run
from a G Suite domain, service accounts are not members of your G
Suite account and aren’t subject to domain policies set by G Suite
administrators. For example, a policy set in the G Suite admin console
to restrict the ability of G Suite end users to share documents
outside of the domain would not apply to service accounts.

Gmail API - Delegating domain-wide authority to the service account to single user

I am trying to access emails of an email address in custom domain(my.name#example.com) in google apps. I created service account but I get following error message when trying to read e-mails:
Error:"unauthorized_client", Description:"Unauthorized client or scope
in request.", Uri:""
I found that I have to delegate domain-wide authority to the service account. According to my understanding, after delegating, the service account will have access to all e-mail addresses in the domain(eg; john#example.com, sam#example.com ...). Is my understanding correct. If yes, is there a way that service account has access (can be impersonated) to only one e-mail address in the domain?
Have you authorized the Client Name and the API scopes in the GSuite admin console? It is required for the service account to work and the error you received seems to be related to the API access permissions.
More info at:
https://support.google.com/a/answer/162106?hl=en

Resources