ServiceForbiddenException Linking Channel - youtube-api

I have an application that creates and uploads videos for customers. Before attempting the upload the customer grants authorization and the resulting access and refresh tokens are saved. It sometimes happens that the customer does not have a YouTube channel associated with their Google Account. I detect this and create a channel for them. This normally works fine. But not always. Here's an example of where creating the channel failed:
Obtaining access token for Customer
post https://accounts.google.com/o/oauth2/token
HTTP Response: 200
{
"access_token" : "_new_access_token_",
"token_type" : "Bearer",
"expires_in" : 3600
}
Uploading video '_video_name_' for Customer
post http://uploads.gdata.youtube.com/feeds/api/users/default/uploads
Authorization: Bearer _new_access_token_
GData-Version: 2.1
X-GData-Key: key=_GData_Key_
Slug: n3n1xs.mp4
Content-Type: multipart/related; boundary="51d366cb05b71"
Content-Length: 255958407
Connection: close
HTTP Response: 403
<?xml version='1.0' encoding='UTF-8'?><errors><error><domain>yt:service</domain><code>youtube_signup_required</code></error></errors>
Obtaining channel names for Customer
get https://gdata.youtube.com/feeds/api/suggest/username?hint=CustomerNameVT&fields=entry%2Ftitle
GData-Version: 2.1
X-GData-Key: key=_GData_Key_
HTTP Response: 200
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom'><entry><title>CustomerNameVT</title></entry><entry><title>VTCustomerName</title></entry><entry><title>VTNameCustomer</title></entry><entry><title>CustomerVTName</title></entry><entry><title>CustomerNameVT1</title></entry><entry><title>NameCustomerVT</title></entry><entry><title>NameVTCustomer</title></entry></feed>
Linking YT channel for Customer (CustomerNameVT)
put https://gdata.youtube.com/feeds/api/users/default
Authorization: Bearer _new_access_token_
Content-Type: application/atom+xml
GData-Version: 2.1
X-GData-Key: key=_GData_Key_
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:yt='http://gdata.youtube.com/schemas/2007'><yt:username>CustomerNameVT</yt:username></entry>
HTTP Response: 403
<errors xmlns='http://schemas.google.com/g/2005'><error><domain>GData</domain><code>ServiceForbiddenException</code><internalReason>Forbidden</internalReason></error></errors>
Notice that the requested name is the first one suggested by the suggest username api. As far as I can see this should work. It usually does. What's wrong this time?

The API for linking a Google Account to a new channel is deprecated.
Our current recommendation is to explicitly take users through a web-based linking process, starting at https://youtube.com/create_channel (or the m.youtube.com equivalent).

Related

Request returns AccessDenied when trying to save in SQS

I have an API Gateway that publishes the request in SQS. This Gateway has SQS SendMessage policy, and this issue I am describing here does not happen when I use the Test option of the gateway.
I am using Insomnia to make requests to the server, with these headers:
Content-Type: application/x-www-form-urlencoded
x-api-key: <My API Key>
Basically the configuration was done following this tutorial:
https://medium.com/#pranaysankpal/aws-api-gateway-proxy-for-sqs-simple-queue-service-5b08fe18ce50
The only difference I included the MessageGroupId on the Mapping template for deduplication:
Action=SendMessage&MessageBody=$input.body&MessageGroupId=$context.resourcePath
The response I am getting is vey weird, because it is a Http 200, with header:
date: Mon, 12 Apr 2021 13:05:53 GMT
content-type: application/json
content-length: 377
x-amzn-requestid: xxxxxxxxxxxxxxxxxxx
x-amz-apigw-id: xxxxxxxxxxxxx
x-amzn-trace-id: Root=xxxxxx
And the body:
<?xml version="1.0"?>
<ErrorResponse
xmlns="http://queue.amazonaws.com/doc/2009-02-01/">
<Error>
<Type>Sender</Type>
<Code>AccessDenied</Code>
<Message>Access to the resource https://sqs.xxxxxxx.amazonaws.com/arn:aws:sqs:us-xxxx-x:xxxxxxxx:xxxxxxxxx.fifo is denied.</Message>
<Detail/>
</Error>
<RequestId>xxxxxxxxxxxxxx</RequestId>
</ErrorResponse>
x's are used to hide information I am not sure are sensible.
I am not sure how to proceed, it seems to an issue while publishing in the queue.
In my inexperience, I was not aware that API Gateway requires Deploy for most of the changes.

Added/Posted contacts not showing up in google contact list?

I am using Google APIs to perform various operations on my contacts. I wanted to add a contact to my contact list for this I used:
POST:
https://www.google.com/m8/feeds/contacts/default/thin?alt=json&max-results=500&v=3.0
With the header
Authorization: Bearer "access_token"
Content-Type: application/json
data:{title: "BATMAN", phonenumber: "3333", email:"tdk#gmail.com"}
The get the response alright:
HTTP/1.1 201 Created
This response was recorded by both Google OAuth 2.0 playground as well as Postman.
However when I wish to fetch the contact it is nowhere to be found. To fetch I my request is:
GET:
https://www.google.com/m8/feeds/contacts/default/thin?alt=json&max-results=500&v=3.0
With the header
Authorization: Bearer "access_token"
I get all contacts but the one just created. Would like to know where I'm going wrong?

401 - Token invalid when requesting video feed

I'm at a loss for what's wrong. I'm always getting com.google.gdata.client.GoogleService$SessionExpiredException: Token invalid Token invalid when making API requests.
I have the following flow:
link user account
use credentials to get video upload entries
The code I use to link the user (get permission for my application) uses the JdoDataStoreFactory to persist user tokens and refresh info between API calls.
I used the following scopes when I ask the user to authorize my apps:
https://www.googleapis.com/auth/youtube.upload
https://www.googleapis.com/auth/youtube.readonly
Using GoogleAuthorizationCodeFlow I do a loadCredentials passing in the userId from my application that I used when requesting their auth token. I then feed those credentials to YouTubeService's getFeed method, requesting the url for video feeds: http://gdata.youtube.com/feeds/api/users/default/uploads
It looks like this:
service.setOAuth2Credentials(credentials)
videoFeed = service.getFeed(new URL(USER_FEED_PREFIX + DEFAULT_USER
+ UPLOADS_FEED_SUFFIX), VideoFeed.class)
After this executes, I always get the stacktrace:
com.google.gdata.client.GoogleService$SessionExpiredException: Token
invalid Token invalid Token invalid Error
401
at
com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:570)
at
com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:560)
at
com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:538)
at
com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:536)
at com.google.gdata.client.Service.getFeed(Service.java:1135) at
com.google.gdata.client.Service.getFeed(Service.java:998) at
com.google.gdata.client.GoogleService.getFeed(GoogleService.java:645)
at com.google.gdata.client.Service.getFeed(Service.java:1017)
The way I'm initiating my request to my service is via curl, my command looks like this:
curl http://localhost:8080/user/someUserId/content
Using Wireshark I see the following in my request:
GET /feeds/api/users/default/uploads HTTP/1.1
Authorization: Bearer <the_auth_token_for_the_user>
User-Agent: MyApp YouTube-Java/1.0 GData-Java/null(gzip)
X-GData-Client: MyApp
Accept-Encoding: gzip
GData-Version: 2.0
Cache-Control: no-cache
Pragma: no-cache
Host: gdata.youtube.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
I'm stuck.
Ok, I figured this out. I was trying to query the user's uploaded videos, and apparently for an app to do that it has to be authorized for the https://www.googleapis.com/auth/youtube scope, not the scopes I had configured

Asana server returning error code 500 on OAuth 2 request with GTMOAuth 2

I'm using the GTMOAuth-2 library to implement an OAuth 2 Authorization Code Grant flow to the Asana API, but consistently getting back a server error 500. The GTMHTTPFetcher log is as follows (selectively redacted):
fetch tokens for app.asana.com
2013-05-08 16:46:58 +0000
Request: POST https://app.asana.com/-/oauth_authorize
Request headers:
Content-Type: application/x-www-form-urlencoded
User-Agent: gtm-oauth2 <user-agent>
Request body: (199 bytes)
client_id=<client-id>&client_secret=_snip_&code=<client-secret>&grant_type=authorization_code&redirect_uri=http%3A%2F%2Fwww.google.com%2FOAuthCallback
Response: status 500
Response headers:
Cache-Control: no-store
Content-Length: 303
Content-Type: text/html; charset=UTF-8
Date: Wed, 08 May 2013 16:46:56 GMT
Pragma: no-cache
Server: nginx
Set-Cookie: <cookie>
X-Asana-Content-String-Length: 303
X-Asana-Preferred-Release-Revision: 20130508_073846_310cafc985fd5fb43121784b58d5dcd2503ffffe
Response body: (303 bytes)
<html>
<head>
<title>Error</title><script>__FILE__="(none)";var config = {
"CLUSTER": "prod",
"PRETTY_JS_CODEGEN": false,
"ENABLED_FEATURES": ""
};</script><link rel="shortcut icon" href="/-/static/luna/browser/images/favicon.ico" />
</head>
<body>
<h3>Error</h3><pre>Server Error</pre>
</body>
</html>
I've double-checked the auth and token URLs, client ID and secret, made sure the redirect URIs match on Asana and in-app. Interestingly, the authorization flow seems to get as far as authorizing the app (and the Asana site records the app as authorized), but it then never seems to return the authorization token. Is there anywhere I might be going wrong, or is this truly an internal server error?
(I work at Asana). I'm unsure where in the flow this request is being made, but it doesn't look correct. Once you've obtained the authorization code (by having the user interact with the Asana form), the library should then make a request to our /-/oauth_token endpoint, and pass us the code. So it's possible that you just need to be using the /-/oauth_token endpoint instead of the /-/oauth_authorize endpoint as you're doing.
If you look at our OAuth examples you'll note that there are two different URLs, one for authorization and one for token exchange.
Asana is probably returning a 500 because it's not expecting this and we're not doing a good enough job catching the problem.

How do I post adaptive payment information to paypal?

I've managed to get an adaptive payments script to work in the apigee console, here is the request:
X-PAYPAL-REQUEST-DATA-FORMAT: JSON
X-PAYPAL-APPLICATION-ID: APP-80W284485P519543T
X-HostCommonName: svcs.sandbox.paypal.com
Host: svcs.sandbox.paypal.com
Content-Length: 428
X-PAYPAL-DEVICE-IPADDRESS: 127.0.0.1
X-Forwarded-For: 10.203.10.109
X-PAYPAL-REQUEST-SOURCE: APIGEE-CONSOLE-1.0
X-Target-URI: https://svcs.sandbox.paypal.com
X-PAYPAL-RESPONSE-DATA-FORMAT: JSON
Content-Type: text/plain; charset=ISO-8859-1
Connection: Keep-Alive
"{
"actionType":"PAY",
"currencyCode":"USD",
"receiverList":{"receiver":[{"amount":"5.00","email":"cam_1315509411_per#btinternet.com"}]},
"returnUrl":"http://apigee.com/console/-1/handlePaypalReturn",
"senderEmail":"qwom_1315508825_biz#btinternet.com",
"feesPayer":"SENDER",
"cancelUrl":"http://apigee.com/console/-1/handlePaypalCancel?",
"requestEnvelope":{"errorLanguage":"en_US", "detailLevel":"ReturnAll"}
}"
How do I actually post this information to the https://svcs.sandbox.paypal.com/AdaptivePayments/Pay url? I can't find the easiest way to do it, should I use cURL and what are the variables names for each post value?
That depends on the rest of your application. PHP with cURL is fairly straightforward, but it's not too much of a hassle in other languages either.
PayPal has sample code online at https://www.x.com/developers/PayPal/documentation-tools/code-sample/78
If you were to do this yourself, you'd need to (in a nutshell):
- Send a proper HTTP header with the X- headers as shown above including the application ID.
- Send the API call via JSON, SOAP or NVP as POST or GET to the API endpoint
- Decode the response and act accordingly

Resources