Any way to use Google Api without every-time authentication? - python

I tried to use the API on python in a autorun on a PC. But I can't because every time the program starts, it asks me about the authorization code.
This is my code:
client_secret_file = "client_secret.json"
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
client_secrets_file, scopes)
credentials = flow.run_console()
youtube = googleapiclient.discovery.build(
api_service_name, api_version, credentials=credentials)
Any help? Thanks

Becouse you are using the YouTube API you can not use a service account you will need to use Oauth2.
Oauth2 can return something called a refresh token, if you store this token your code can then access the refresh token the next time it runs and use the refresh token to request a new access token this way it will not need to ask you every time it runs to access your data.
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
The only offical sample that includes refresh token that i know if is here Python quickstart you will need to alter it for YouTube but the auth code is really all you need just plug that int your code and you should be GTG

You can achieve this using Service Account.
https://googleapis.dev/python/google-api-core/latest/auth.html#service-accounts
Service account are technically pre authorized by the developer.
IF the API does not support Service account( in some cases) then you can try oauth2 where you have a consent for asking the owner of the account if you can access

Related

Bigquery google auth without browser prompt

i am accessing user data by connecting to bigquery via python with OAuth 2.0 method. But every time I make a query, it repeatedly asks for browser confirmation. How can I cancel this verification? When I set the launch_browser value to False, it requests confirmation from the terminal. Is there a different method I can use? I am using the same sample code found in the document https://cloud.google.com/bigquery/docs/authentication/end-user-installed
from google_auth_oauthlib import flow
from google.cloud import bigquery
launch_browser = True
appflow = flow.InstalledAppFlow.from_client_secrets_file(
"client_secrets.json", scopes=["https://www.googleapis.com/auth/bigquery"]
)
if launch_browser:
appflow.run_local_server()
else:
appflow.run_console()
credentials = appflow.credentials
project = 'user-project-id'
client = bigquery.Client(project=project, credentials=credentials)
query_string = """SELECT name, SUM(number) as total
FROM `bigquery-public-data.usa_names.usa_1910_current`
WHERE name = 'William'
GROUP BY name;
"""
query_job = client.query(query_string)
for row in query_job.result():
print("{}: {}".format(row["name"], row["total"]))
Storing the credentials in a file stops google from constantly requesting it, it only lasts for a little while though.
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_console()
#creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
This is what I use to load credentials (I do mine through console as it is on Linux with no browser)
You may have to change some parts to fit your code but this is the general idea.

python - how to authenticate against GmailAPI without user input

I have a small python script that collects some data and sends it in an email using the gmail api. My goal is to put this script on my raspberry, create a daily cronjob that calls it and forget about it. However, the way I have done my google authentication prevents me from automating it. Currently I have to authenticate using my browser(user needs to press the allow button), then I can use the credentials for a few days and then they expire and user input is required again. How can I make it authenticate once and then start refreshing its credentials automatically?
Current code:
def get_creds():
creds = None
if os.path.exists(os.path.join(dir,'token.json')):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
print("refreshing")
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
os.path.join(dir,'credentials.json'), SCOPES)
creds = flow.run_local_server(port=0)
with open(os.path.join(dir,'token.json'), 'w') as token:
token.write(creds.to_json())
return creds
You can use a service account instead of token. It doesn't expire.
from google.oauth2 import service_account
from googleapiclient.discovery import build
credentials = service_account.Credentials.from_service_account_file(
CREDENTIALS_JSON_PATH,
SCOPES
)
service = build('gmail', 'v1', credentials=credentials)
print(service.users().getProfile(userId='me').execute())
If you create Google Workspace service account you need to specify user email address
credentials = credentials.with_subject(USER_EMAIL)
As Daniel mentioned the problem was that my GoogleCLoud app was in test mode. I had to publish it first and then it started refreshing the token successfully without my help.
avoid auth token to expire

Missing Scopes Error: google.auth.exceptions.RefreshError

I'm trying to build a Google Classroom extension that gives the user control over when to receive "Work Due Soon" notifications. However, when the token refreshes, I get this error: "raise exceptions.RefreshError(google.auth.exceptions.RefreshError: Not all requested scopes were granted by the authorization server, missing scopes https://www.googleapis.com/auth/classroom.coursework.me.readonly. "
The code being used is straight from the google authorization page for google classroom
SCOPES = ['https://www.googleapis.com/auth/classroom.courses.readonly', 'https://www.googleapis.com/auth/classroom.coursework.me.readonly']
def main():
"""Shows basic usage of the Classroom API.
Prints the names of the first 10 courses the user has access to.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
As you can see, the scope in the error, is already in my list of scopes for the project. The only way I've found to get around this is to delete the token file, and sign-in every time the token expires. I've checked the classroom api documentation and stack overflow but I couldn't find a solution. Any help will be appreciated.

PYTHON Login in with multiple account using Gmail api/imaplib

I'm currently working on an application requiring a gmail inbox. Currently i'm using the Gmail API with a credentials.json and a token.pickle and this is working fine although I want to login with other credentials each time the script is used. I'm quite new to this API and was wondering if it's possible to login with other credentials than the credentials used for the token.pickle.
Gmail API
To currently get a gmail inbox I use the following code:
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
global service
service = build('gmail', 'v1', credentials=creds)
Imaplib
Another way I've tried to get a certain user's inbox is with the imaplib and email library since it lets you login with a certain email address and password. But to allow this to work a user needs to allow less secure apps to their google account which is a hassle for each user to enable that. The code I used for imaplib is the following code:
import imaplib, email
username = 'USERNAME'
password = 'PASSWORD'
imap_url = 'imap.gmail.com'
con = imaplib.IMAP4_SSL(imap_url)
con.login(username, password)
con.select('Inbox')
Question
My question is: Is it possible with the gmail api from google to login with multiple/other credentials to get the corresponding gmail inbox? If this is not possible and I have to use the Imaplib way, what are the steps I need to take so it doesn't require users to enable less secure apps?
Just change the .pickle file name. This code possibilite do this just changing the user variable. There will be different tokens to each account
def api_connection(user):
scopes = ['https://www.googleapis.com/auth/gmail.readonly']
creds = None
if os.path.exists(f'{user}.pickle'):
with open(f'{user}.pickle', 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', scopes)
creds = flow.run_local_server(port=0)
with open(f'{user}.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
return service

Using Gmail API without opening browser in Python

I have headless software in Jetson Xavier. I am using Gmail API for sending mail. My code is working correctly in Laptop however GUI service is disabled in Jetson, browser cannot be opened. So, Authentication is failed when I try to use Gmail API in Jetson.
I have copied authenticated "token.pickle" to Jetson from laptop. It works fine that for a short time. Then, it wants an authentication again.
How can I solve this issue? How to block the browser to be opened for authentication in Jetson?
Thanks.
This part of code is for authentication:
class EmailSender:
def __init__(self):
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.compose']
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
creds_dir = os.path.dirname(os.path.abspath(__file__)) + '/credentials.json'
flow = InstalledAppFlow.from_client_secrets_file(
creds_dir, SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
self.service = build('gmail', 'v1', credentials=creds)
Unfortunately, gmail(and most modern auth service) will not allow you to login automatically directly for safety reason. In order to ensure that a third party service not to steal your account, google will ask you as a human to type in your account and password and google will return a cookie, or token, to the service you try to login.
However, since you are working on your own project and I assume you know the program will not put your account at risk, you can use selenium to simulate a browser and type your account automatically. You may refer to this post to learn how to do it.

Categories