How to send an email on behalf of a Google Group with the GMail API - google-app-engine

We would like our application to send emails with a google group email in the FROM header.
This is possible in the GMail interface, assuming that the Google Group is correctly configured.
But when we try with the GMail API here's the error we got :
403 Forbidden
cache-control: private, max-age=0
content-encoding: gzip
content-length: 175
content-type: application/json; charset=UTF-8
date: Thu, 04 Sep 2014 11:05:36 GMT
expires: Thu, 04 Sep 2014 11:05:36 GMT
server: GSE
{
"error": {
"errors": [
{
"domain": "global",
"reason": "forbidden",
"message": "XXX.XXXX#XXXXX.XXX does not have privileges to XXX.XXXX#XXXXX.XXX mailbox."
}
],
"code": 403,
"message": "XXX.XXXX#XXXXX.XXX does not have privileges to XXX.XXXX#XXXXX.XXX mailbox."
}
}
Is there a way to circumvent this, either with the GMail API or with App Engine's mail features ?

You need to add the group as an owner to the project.

Don't try to put the group in the URL, just use "me", the authenticated user as normal. If that user really does have the group configured as a valid From address in the gmail web interface (they have to have completed a verification flow to confirm they own the address by clicking on a link--they can send emails "From" that group using the web interface) then you should simply be able to send an email with the "From" header being that group and it will be accepted.

Related

http-only cookie not being set on React client in Azure

I've seen several similar issues reported on here, but none of the solutions or specific setups seem to be quite matching mine.
I have a React client that is calling a backend Framework Web API via apollo, which is setting an http only cookie that I am expecting to be sent back in all subsequent requests. The backend service is configured to accept the client domain as CORS origin and locally as well as when deployed to a test server this is all working fine.
I have now deployed both the client and back end service to separate Azure App Services and the cookie 'appears' to not be getting set on the client.
In the initial response headers I can see the cookie being set in set-cookie, but it is not then included in subsequent requests and does not appear in the applications tab in chrome tools.
My Apollo calls are specifying withCredentials: true
Any idea what the reason for this may be?
Edit.
The response headers coming back from the initial API request are:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://my-app-service.azurewebsites.net
Cache-Control: no-cache
Content-Encoding: gzip
Content-Length: 256
Content-Type: application/json; charset=utf-8
Date: Fri, 29 Oct 2021 12:04:27 GMT
Expires: -1
Pragma: no-cache
Server: Microsoft-IIS/10.0
Set-Cookie: {Cookie-Name}={JWT-Token}; expires=Fri, 29-Oct-2021 12:24:27
GMT; path=/; HttpOnly
Vary: Accept-Encoding
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET

AAD microsoft graph, client credentials

I have setup an Office 365 E3 trial account. I registered two apps in AAD.
The first one uses the "authorization code flow" and does work as expected (can access the logged in users calendar).
The second app uses the "client credentials flow" and does not work.
login in Browser (Edge)
GET /OAuthTest3 HTTP/1.1
HTTP/1.1 302 Found
Location: https://login.microsoftonline.com/<tenant>/adminconsent?client_id=<app_id>&redirect_uri=http://localhost:1234/OAuthTest3
GET /OAuthTest3?admin_consent=True&tenant=<tenant> HTTP/1.1
HTTP/1.1 200 OK
connect to https://login.microsoftonline.com/
POST /<tenant>/oauth2/token HTTP/1.1
Host: login.microsoftonline.com
client_id=<app_id>&
client_secret=<client_secret>&
grant_type=client_credentials&
redirect_uri=http://localhost:1234/OAuthTest3&
resource=https://graph.microsoft.com/&
scope=https://graph.microsoft.com/calendars.readwrite
HTTP/1.1 200 OK
{
"token_type": "Bearer",
"expires_in": "3600",
"ext_expires_in": "0",
"expires_on": "1504333342",
"not_before": "1504329442",
"resource": "https://graph.microsoft.com/",
"access_token": <token>
}
connect to https://graph.microsoft.com/
GET /v1.0/users/<user>/calendars HTTP/1.1
Host: graph.microsoft.com
Authorization: Bearer <token>
HTTP/1.1 403 Forbidden
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"request-id": "e7228de4-2b27-4779-abef-ccab0d88970a",
"date": "2017-09-02T05:22:27"
}
}
}
In order to use Client Credentials flow in AAD V2.0, you need to first object Admin Consent for your application. This is true even if you wouldn't need consent for the same scope using Authorization Code grant.
Take a look at v2 Endpoint and Admin Consent for a walk-through on obtaining consent.
UPDATE:
Scopes work differently with Client Credentials. Rather than dynamically requesting the scopes using a space delimited list (https://graph.microsoft.com/user.read https://graph.microsoft.com/calendars.readwrite), you need to define them in your app's registration.
This is done using the https://apps.dev.microsoft.com portal. In your app's registration, find the "Application Permissions" section and click the "Add" button. This will pop a dialog where you can select the permissions you need:
In your application, you also need to change your scope parameter so the system knows to use the scopes from your registration. This is done by passing https://graph.microsoft.com/.default for the scope:
POST /<tenant>/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
client_id=<app_id>&
client_secret=<client_secret>&
grant_type=client_credentials&
redirect_uri=http://localhost:1234/OAuthTest3&
resource=https://graph.microsoft.com/&
scope=https://graph.microsoft.com/.default
Important: Any time you make a change to your scopes, you will have to re-execute the Admin Consent flow before those new scopes will consented.

InvalidAuthenticationToken - CompactToken parsing failed with error code: -2147184105

I am using V1 in order to have a token from Microsoft REST API. (We have Office 365 tenant and I used to successfully get all resources without any problem but not anymore.
clientId =8a67......de4b6
clientSecret =J58k8....5EU=
redirectUri =http://example.com...
resourceUrl =https://graph.microsoft.com
authority = https://login.microsoftonline.com/f02633....a603/oauth2/token
https://login.microsoftonline.com/f0263...0be3/oauth2/authorize?client_id=8a6..b6&redirect_uri=http://example.com&response_type=code&scope=mail.read
It gave me a token structured as follows on JWT. It says invalid signature but not sure what is wrong.
Once I have the token, I tried the following curl call
curl -i https://graph.microsoft.com/v1.0/me/messages -H 'Content-Type: application/x-www-form-urlencoded' -H 'Authorization: Barer eyJ.[TOKEN]...UNa6nfw'
Instead of the messages, I received the following error:
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8Cl23
Server: Microsoft-IIS/8.5
request-id: af2390b1-a9b...5ab9
client-request-id: af2390,....a615ab9
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"West US","Slice":"SliceA","ScaleUnit":"000","Host":"AGSFE_IN_4","ADSiteName":"WST"}}
X-Powered-By: ASP.NET
Date: Thu, 19 Jan 2017 23:55:43 GMT
Content-Length: 268
{
"error": {
"code": "InvalidAuthenticationToken",
"message": "CompactToken parsing failed with error code: -2147184105",
"innerError": {
"request-id": "af2390b1-...5ab9",
"date": "2017-01-19T23:55:44"
}
}
}
I looked at similar questions on SO but couldn't find any solution.
First, the Barer of authorization header is a typo. The correct parameter should be like authorization: bearer {access_token}.
Second, it seems that you were mixing using the Azure V1.0 endpoint and V2.0 endpoint. If you were developing with V1.0 endpoint which apps were resisted from Azure portals, when we acquire the access token we need to specify the resource parameter instead of scope.
The scope parameter is used for Azure V2.0 endpoint which apps are resisted from here.
And the authorization endpoint for Azure AD likes below:
V1.0:
https://login.microsoftonline.com/{tenant}/oauth2/authorize
V2.0:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
More detail about the code grant flow with Azure AD, you can refer links below:
Authorize access to web applications using OAuth 2.0 and Azure Active Directory
v2.0 Protocols - OAuth 2.0 Authorization Code Flow

Google Cloud Storage access denied and MapReduce. Cannot add Service Account into developers list

I'm running a MapReduce job on Google App Engine with a configuration similar to this:
MapReduceSettings.Builder()
.setBucketName("my-bucket")
.setWorkerQueueName(QUEUE_NAME)
.setModule(MODULE)
.build();
The bucket is used for temporary data by App Engine itself.
The problem is that when I run the job, it fails with the following stacktrace:
com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
java.lang.RuntimeException: Writeable Bucket 'my-bucket' test failed. See http://developers.google.com/appengine/docs/java/googlecloudstorageclient/activate for more information on how to setup Google Cloude storage.
at com.google.appengine.tools.mapreduce.MapReduceSettings.verifyAndSetBucketName(MapReduceSettings.java:134)
at com.google.appengine.tools.mapreduce.MapReduceSettings.<init>(MapReduceSettings.java:89)
at com.google.appengine.tools.mapreduce.MapReduceSettings.<init>(MapReduceSettings.java:31)
at com.google.appengine.tools.mapreduce.MapReduceSettings$Builder.build(MapReduceSettings.java:83)
at
...
...
Caused by: com.google.appengine.tools.cloudstorage.NonRetriableException: java.lang.RuntimeException: Server replied with 403, verify ACLs are set correctly on the object and bucket: Request: DELETE https://storage.googleapis.com/my-bucket/2f249469-c77a-4540-bbbd-45fcd27d7600.tmp
User-Agent: App Engine GCS Client
no content
Response: 403 with 111 bytes of content
Content-Type: application/xml; charset=UTF-8
Content-Length: 111
Vary: Origin
Date: Tue, 12 Aug 2014 18:20:20 GMT
Expires: Tue, 12 Aug 2014 18:20:20 GMT
Cache-Control: private, max-age=0
Server: UploadServer ("Built on Jul 31 2014 18:25:34 (1406856334)")
Alternate-Protocol: 443:quic
X-Google-Cache-Control: remote-fetch
Via: HTTP/1.1 GWA
<?xml version='1.0' encoding='UTF-8'?><Error><Code>AccessDenied</Code><Message>Access denied.</Message></Error>
I already tried to add the Service Account Name (name-of-my-app#appspot.gserviceaccount.com) as a team member but beside the user it keeps saying
Invitation sent. Waiting for response.
How can I add the Service Account into the developers list so I can give it access to my bucket?
Thanks
I solved it using the gsutils command line tool:
gsutil acl ch -u name-of-my-app#appspot.gserviceaccount.com:WRITE gs://my-bucket
According to Google Storage documentation, sometimes it's not possible to add the service account into the developers list, even if they don't say why
Note: In some circumstances, you might not be able to add the service account as a team member. If you cannot add the service account, use the alternative method, bucket ACLs, as described next.

Cannot GET Google Realtime API resource

I'm playing with the Google Drive API. I've managed to authenticate successfully and retrieve file listings and other things, but my goal is to write an alternative (if limited) editor for documents held in Google Drive. Unfortunately the downloadUrl referred to in the docs (https://developers.google.com/drive/v2/reference/files) does not exist, only exportLinks. It seems in order to deal with the native formatting of documents in Google Drive, it's necessary to use the realtime API.
Very well, I tried to retrieve the undocumented (but hinted at) realtime resource hinted at by the documentation, found at: https://www.googleapis.com/drive/v2/files/FILEID/realtime -
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=UTF-8
Date: Tue, 05 Aug 2014 03:02:51 GMT
Expires: Tue, 05 Aug 2014 03:02:51 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Alternate-Protocol: 443:quic
Transfer-Encoding: chunked
{
"error": {
"errors": [
{
"domain": "global",
"reason": "lockedDomainCreationFailure",
"message": "The OAuth token was received in the query string, which this API forbids for response formats other than JSON or XML. If possible, try sending the OAuth token in the Authorization header instead."
}
],
"code": 400,
"message": "The OAuth token was received in the query string, which this API forbids for response formats other than JSON or XML. If possible, try sending the OAuth token in the Authorization header instead."
}
}
An odd error message. Authenticating with a header instead of an access_token parameter doesn't make it work. I used the API explorer found for the realtime resource (https://developers.google.com/drive/v2/reference/realtime/get) and it didn't work either. It gives the following message when used with the same file:
400 Bad Request
- Hide headers -
cache-control: private, max-age=0
content-encoding: gzip
content-length: 123
content-type: application/json; charset=UTF-8
date: Tue, 05 Aug 2014 03:14:42 GMT
expires: Tue, 05 Aug 2014 03:14:42 GMT
server: GSE
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalid",
"message": "Invalid Value"
}
],
"code": 400,
"message": "Invalid Value"
}
}
I know the file is fine because the rest of the API calls I've made against it have worked (exploring the comments functionality and other things). It's frustrating issue I've run against, but hopefully someone can help. I would like to be able to edit collaborative documents outside of the canonical browser based editor in a non-destructive way!
Small update:
GET https://www.googleapis.com/drive/v2/files/1s8NArXPG0CWRHaA9HQ-zND086Uh5CoUFC2p3b3NI3Ek/realtime?key={YOUR_API_KEY}
Is the URL the API explorer (found here https://developers.google.com/drive/v2/reference/realtime/get) shows itself using to get the 400 error message above. As it turns out, I'd only set up an OAuth2 client ID - a "Simple API Key" is needed for the realtime API. A server side API key will not work either - it must be an API key for an Android application, iOS application or a browser based application. This is horrendously inconvenient because I'm not interested in browser based anything, but maybe there's some way to write a small hosted shim to make my dreams come true. Why must you do this, Google??!?
You cannot use the realtime API to access existing documents. It is for creating your own custom data, collaborative data models.

Resources