Gmail Forwarding api says forbidden - gmail-api

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

Related

Google Calendar with G Suite account insert get 403

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

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.

Azure AAD and Graph API: Insufficient privileges to complete the operation

Context: I've a console app which wants to use Graph API to talk to AAD to check if a particular userId exists in the tenant or not.
I've been following the guidelines here: https://learn.microsoft.com/en-us/graph/auth-v2-service?view=graph-rest-1.0
I'm able to generate a token using this:
https://login.microsoftonline.com/common/oauth2/v2.0/token
client_id=x
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=x
&grant_type=client_credentials
But when I call the graph API I get this ERROR:
https://graph.microsoft.com/v1.0/users/12345678-73a6-4952-a53a-e9916737ff7f
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"request-id": "x",
"date": "x"
}
}
}
My AAD App has all the permissions from:
1. Microsoft Graph
2. Windows Azure Active Directory
I tried changing the scope to
scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
But this is the error I get while generating token:
The provided value for the input parameter 'scope' is not valid. The scope https://graph.microsoft.com/user.read is not valid.
I've tried combinations of "User.Read", "User.Basic.Read", etc. but nothing works.
The most likely reason why this is not working is because the permission which you have configured your app registration to require have not actually been granted by an administrator of your organization.
In your code, your app is authenticating as an application only. There is no signed-in user involved, and it requires your app to use and keep confidential a key used to authenticate (the client_secret parameter).
In this scenario, requesting the scope https://graph.microsoft.com/.default is the correct approach. What you're saying to Azure AD is: "please provide an access token for all the application permissions this app has been granted". Requesting the scope https://graph.microsoft.com/User.Read is not the correct approach because there is no application permission with that name.
Does the app you created have delegated permissions or application permissions to that scope?
Most likely the former. Delegated permissions don’t apply to client credentials flow.

How to get Azure tenant name from graph.microsoft.com?

I need to discover user's tenant name, since the service endpoint, resourceId that I'll be using an Azure service that requires me to specify the tenant name:
service endpoint: https://[tenantnamme].api.crm.dynamics.com/...
resource Id: https://[tenantname].crm.dynamics.com
I was hoping Unified Microsoft Graph API can discover this for me. I looked at the documentation, the closest I can see is to use
graph.microsoft.com/v1.0/organization
which will give me back:
verifiedDomains : [
....
"name" : "contoso.onmicrosoft.com"
]
But, I'm not sure if this is the right approach. What if an org has multiple verified domains? Does verified domain name is the same as tenant name?
Update: This is my real scenario. I have a web app that allows user to authenticate to Azure AD via OAuth2. I have no problem obtaining refresh token and access token from OAuth interactions. However, in other to use other service, it requires [azure-ad-tenant-name] in their service end point. That's my question coming from.
I believe that you're on the right track with the graph.microsoft.com/v1.0/organization endpoint. You should be able to find the tenant name in the verifiedDomains list. The entry that should contain domain with the tenant name is the initial domain:
{
...
"isInitial": true,
"name": "contoso.onmicrosoft.com",
...
}
Same. When you create a AD, you will obtain a domain name and a tenant id without tenant name, they are both the unique identifier of a AD. Use Get-AzureRmTenant to get all tenantid and domains in your subscription.

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