Tweepy: tweepy.errors.Unauthorized: 401 Authorization Required - python

I am looking forward to extract some data from my profile in Twitter by using the following Tweepy code:
import tweepy
client = tweepy.Client(consumer_key=consumer_key, consumer_secret=consumer_secret,
access_token=access_token, access_token_secret=access_token_secret)
client.get_tweets(ids=[user_id], tweet_fields=["public_metrics"], expansions=["attachments.media_keys"],
media_fields=["public_metrics"])
The issue is that for some reason, I get the following error: tweepy.errors.Unauthorized: 401 Authorization Required, and I know my credentials are valid because I pass tests successfully like the following:
lookup_users = api.lookup_users(screen_name=screen_name)
The issue here is that I have to authorize the account/app/project to get this data, but I haven't found the documentation related to give those authorizations.
How can I authorize my app to get this info from the account??

Since the GET /2/tweets endpoint Client.get_tweets uses allows authentication via bearer token, that's what the method uses by default.
If you want to authorize with user context, you'll have to pass user_auth and set it to True, as it defaults to False, e.g.:
client.get_tweets(
ids=[user_id],
tweet_fields=["public_metrics"],
expansions=["attachments.media_keys"],
media_fields=["public_metrics"],
user_auth=True
)

Related

How Can I get an ID Token while validating using Username and Password?

I am using Python ADAL library to Authenticate a user using Azure Active Directory. I successfully receive the access token post authentication. Now, I want to verify the validity of the access token. I need the ID_TOKEN in this case. How do I get it?
import adal
auth_context = adal.AuthenticationContext("https://login.microsoftonline.com/{{tenant_id}}")
token_response = auth_context.acquire_token_with_username_password("https://management.core.windows.net/", username, password, client_id)
In the token response, I get the access_token and refresh_token but I do not receive the id_token. Following a similar question, How to verify JWT id_token produced by MS Azure AD? I used the code to validate the access token but I need the ID_TOKEN.
Any thoughts on getting this would be great.
No need to get the ID_TOKEN, try the code as below.
import adal
import jwt
auth_context = adal.AuthenticationContext("https://login.microsoftonline.com/{{tenant_id}}")
token_response = auth_context.acquire_token_with_username_password("https://management.core.windows.net/", username, password, client_id)
token_header = jwt.get_unverified_header(token_response['accessToken'])
For more details, you could refer to this similar issue and this doc.

Azure Active Directory get token request http error

I'm using Active Directory Authentication library for python following the documentation. Earlier on I managed to get the access_token through the Acquire Token with Client Credentials sample:
import adal
RESOURCE_URI = 'https://<mydomain>.crm.dynamics.com'
AUTHORITY_URL = "https://login.microsoftonline.com/<tenant_id>"
CLIENT_ID = 'xxxx' #application_id
CLIENT_SECRET = 'xxxx'
context = adal.AuthenticationContext(AUTHORITY_URL)
token = context.acquire_token_with_client_credentials(
RESOURCE_URI,
CLIENT_ID,
CLIENT_SECRET)
print token
But I get an error message when I tried the Acquire token and Refresh token sample
context = adal.AuthenticationContext(AUTHORITY_URL)
token = context.acquire_token_with_username_password(
RESOURCE_URI,
USERNAME,
PASSWORD,
CLIENT_ID)
print token
>>> adal.adal_error.AdalError: Get Token request returned http error: 401 and server response: {"error":"invalid_client","error_description":"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.........."correlation_id"......}
adal.adal_error.AdalError: Get Token request returned http error: 401 and server response: {"error":"invalid_client","error_description":"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.........."correlation_id"......}
There are two kinds of app we can register on Azure, native or web app. Based on the error message, it seems that you have register a confident app which requires provide its client secret to acquire the access token.
For this issue please register a native app instead of web app. Also the resource owner password credentials flow should be consider used carefully since this may leak the credentials. Refer the flows from link below:
The OAuth 2.0 Authorization Framework - Authorization Grant
I suffered from the same error.
In app registration section in azure active directory I registered the app as web host/api.
When I changed it to native app everything started to work fine.

How to use a refresh_token for youtube python api?

So i got a refresh token in this way and can I keep it?
And if so, how do I use it next time, so that there is no need for me to open browser?
Right now I'm thinking about creating OAuth2Credentials object directly, is this the right way?
from urllib.parse import urlparse, parse_qs
from oauth2client.client import flow_from_clientsecrets, OAuth2Credentials
from oauth2client.file import Storage
from oauth2client.tools import argparser, run_flow
from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.contrib import gce
import httplib2
import webbrowser
CLIENT_SECRETS_FILE = "bot_credentials.json"
flow = client.flow_from_clientsecrets(
CLIENT_SECRETS_FILE,
scope=scope,
redirect_uri='http://127.0.0.1:65010')
flow.params['include_granted_scopes'] = 'true'
flow.params['access_type'] = 'offline'
auth_uri = flow.step1_get_authorize_url()
webbrowser.open(auth_uri)
url = input('Please enter the redirected url with code')
code = get_url_param(url, 'code')
if code is None:
print('there is an error in your redirect link with code parameter, check if it exists')
exit()
print(code)
credentials = flow.step2_exchange(code[0])
print(credentials.to_json())#refresh_token here!!!
If the user consents to authorize your application to access those resources, Google will return a token to your application. Depending on your application's type, it will either validate the token or exchange it for a different type of token. Check this documentation.
For example, a server-side web application would exchange the returned token for an access token and a refresh token. The access token would let the application authorize requests on the user's behalf, and the refresh token would let the application retrieve a new access token when the original access token expires.
Basically, if your application obtains a refresh token during the authorization process, then you will need to periodically use that token to obtain a new, valid access token. Server-side web applications, installed applications, and devices all obtain refresh tokens.
It is stated here that at any time, your application can send a POST request to Google's authorization server that specifies your client ID, your client secret, and the refresh token for the user. The request should also set the grant_type parameter value to refresh_token.
The following example demonstrates this request:
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
client_id=21302922996.apps.googleusercontent.com&
client_secret=XTHhXh1SlUNgvyWGwDk1EjXB&
refresh_token=1/6BMfW9j53gdGImsixUH6kU5RsR4zwI9lUVX-tqf8JXQ&
grant_type=refresh_token
The authorization server will return a JSON object that contains a new access token:
{
"access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
"expires_in":3920,
"token_type":"Bearer"
}
You can check this sample on GitHub to generate a refresh token for the YouTube API. Note that this will will also create a file called generate_token.py-oauth that contains this information.

YouTube API without user OAuth process

I am trying to fetch captions from YouTube video using YouTube Data API (v3)
https://developers.google.com/youtube/v3/guides/implementation/captions
So, first I tried to retrieve a captions list using this url:
https://www.googleapis.com/youtube/v3/captions?part=snippet&videoId=KK9bwTlAvgo&key={My API KEY}
I could retrieve the caption id that I'd like to download (jEDP-pmNCIqoB8QGlXWQf4Rh3faalD_l) from the above link.
Then, I followed this instruction to download the caption:
https://developers.google.com/youtube/v3/docs/captions/download
However, even though I input the caption id and my api key correctly, it shows "Login Required" error.
I suppose I need OAuth authentication, but what I am trying to do is not related to my users's account, but simply downloading public caption data automatically.
My question is: Is there any way to process OAuth authentication just once to get an access token of my own YouTube account and then reuse it whenever I need it in my application?
I can't speak to the permissions needed for the captions API in particular, but in general, yes, you can OAuth to your app once using your own account and use the access and refresh tokens to make subsequent OAuth'd requests to the API. You can find the details of generating tokens here:
https://developers.google.com/youtube/v3/guides/auth/server-side-web-apps#Obtaining_Access_Tokens
To perform the steps manually (fortunately, you only need to do this once):
If access has already been granted for an app, it needs to be removed so that new auth credentials can be established. Go to https://security.google.com/settings/security/permissions (while logged into your account) and remove access to the app. If the client ID or secret change (or you need to create one), find them at https://console.developers.google.com under API Manager.
To grant access and receive a temporary code, enter this URL in a browser:
https://accounts.google.com/o/oauth2/auth?
client_id=<client_id>&
redirect_uri=http://www.google.com&
scope=https://www.googleapis.com/auth/youtube.force-ssl&
response_type=code&
access_type=offline&
approval_prompt=force
Follow the prompt to grant access to the app.
This will redirect to google.com with a code parameter (e.g.,
https://www.google.com/?code=4/ux5gNj-_mIu4DOD_gNZdjX9EtOFf&gws_rd=ssl#). Save the code.
Send a POST request (e.g., via Postman Chrome plugin) to https://accounts.google.com/o/oauth2/token with the following in the request body:
code=<code>&
client_id=<client_id>&
client_secret=<client_secret>&
redirect_uri=http://www.google.com&
grant_type=authorization_code
The response will contain both an access token and refresh token. Save both, but particularly the refresh token (because the access token will expire in 1 hour).
You can then use the access token to send an OAuth'd request manually, following one of the options here, essentially:
curl -H "Authorization: Bearer ACCESS_TOKEN" https://www.googleapis.com/youtube/v3/captions/<id>
or
curl https://www.googleapis.com/youtube/v3/captions/<id>?access_token=ACCESS_TOKEN
(When I tried the second option for captions, however, I got the 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.")
You can also use the refresh token in your code to create the credential needed when building your YouTube object. In Java, this looks like the following:
String clientId = <your client ID>
String clientSecret = <your client secret>
String refreshToken = <refresh token>
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(transport)
.setJsonFactory(jsonFactory)
.setClientSecrets(clientId, clientSecret)
.build()
.setRefreshToken(refreshToken);
try {
credential.refreshToken();
} catch (IOException e) {
e.printStackTrace();
}
youtube = new YouTube.Builder(transport, jsonFactory, credential).build();
I imagine you can do something similar in Python with the API Client Libraries, although I haven't tried Python.

How to see a Google+ user's circles with google-api-python-client

I'm trying to access a user's circles in this way:
from apiclient.discovery import build
service = build('plus','v1',developerKey=my_developer_key) # <-- NOT the user's token
people_request = service.people().list(userId=my_gplus_id, collection='connected')
all_people = people_request.execute()
The user approved the following scope:
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile'
But I'm getting this error:
<HttpError 403 when requesting https://www.googleapis.com/plus/v1/people/107512995392892664693/people/connected?alt=json&key=... returned "Forbidden">
Any ideas? Thanks~!
EDIT: I tried the same with google's JS API. It doesn't use the "key" url param but instead uses a "bearer" header with the user's access token, perhaps I'm using the wrong token?
The only supported userId is me for the currently authenticated user.

Categories

Resources