When developing on a local machine I used standart code to authorize and work with Google disk
creds = None
cred = os.path.join(settings.BASE_DIR, 'credentials.json')
# 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(
cred, SCOPES)
creds = flow.run_local_server(port=8080)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
I use 8080 as the port parameter value. This works. When deploying a project on a production server, I get a message port is already in use.
Server: Ubuntu 18.04, Nginx, uwsgi, Django
I've changed the port to 5000, everything works on the local machine. I tried to run it on a production server and got a 504 error. I checked the uwsgi log and saw that the end of the file contains a link to authorization.

On the local machine, this link automatically opens in a new window to log on to the account. If try to run the production server again, I will get the [Errno 98] Address already in use error and this error is saved until reboot uwsgi. After the reboot, everything repeats itself again.
I've tried many different port meanings, the same problem with everyone. I think the problem here is not in the specific meaning. After restart uwsgi there is an attempt of authorization (i.e. the value of the port is accepted) but the redirection by reference to OAuth2 does not occur. And it's quite strange that when try again, the error[Errno 98] Address already in use
What values should I use?
Hi @Lepiloff,
It looks like you're using InstalledAppFlow, which is for applications installed on devices. It sounds like you are developing a web server application?
run_local_server uses a default host of localhost for the redirect_uri, which is fine when you run the project locally but won't work once your project is deployed.
Please take a look at the Python documentation for the OAuth2 Web Server flow. There are code snippets and a complete example using flask that should be helpful.
Please do let us know if you have additional questions.
@busunkim96 thank you for answering.
Yes, I use web server application. Google API documentation in some places not very clear. Now I know that run_local_server uses only for locall projects. It is very strange that there are no good examples on the Internet for using Django and Google API for my purposes. I will try to deal with this problem
I'm trying to change the code according to the link you gave me.
My code
import google_auth_oauthlib.flow
from googleapiclient.discovery import build
from django.urls import reverse
from django.http import HttpResponse, HttpResponseRedirect
import os
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
SCOPES = 'https://www.googleapis.com/auth/drive'
cred = os.path.join(settings.BASE_DIR, 'credentials.json')
Function for upload file:
def file_to_drive(request, import_file=None):
state = request.session['state']
if state is None:
authorize(request)
else:
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
cred, scopes=SCOPES, state=state)
flow.redirect_uri = "http://localhost:8000/oauth2callback"
authorization_response = request.build_absolute_uri()
flow.fetch_token(authorization_response=authorization_response)
credentials = flow.credentials
service = build('drive', 'v3', credentials=credentials)
file_metadata = {
'name': 'My Report',
'mimeType': 'application/vnd.google-apps.spreadsheet'
}
media = MediaFileUpload(import_file,
mimetype='text/html',
resumable=True)
file = service.files().create(body=file_metadata,
media_body=media,
fields='id').execute()
print('File ID: %s' % file.get('id'))
return (f"https://docs.google.com/document/d/{file.get('id')}/edit")
And function for user authorization
def authorize(request):
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
cred, scopes=SCOPES)
flow.redirect_uri = "http://localhost:8000/oauth2callback"
authorization_url, state = flow.authorization_url(
access_type='offline',
include_granted_scopes='true')
request.session['state'] = state
return HttpResponseRedirect(authorization_url)
urls.py
path('oauth2callback', authorize, name='authorize'),
path('to_drive', file_to_drive, name='file_to_drive'),
In function file_to_drive searching for the value of the state parameter from the session, if it is not found, the authorize function is called. In the end, I get a message
oauthlib.oauth2.rfc6749.errors.MismatchingStateError: (mismatching_state) CSRF Warning! State not equal in request and response.
Error traseback
File "/home/y700/projects/CV/cv-base/ems/base/utils.py", line 119, in file_to_drive
flow.fetch_token(authorization_response=authorization_response)
File "/home/y700/Env/cv-base-XRtgVf2K/lib/python3.7/site-packages/google_auth_oauthlib/flow.py", line 263, in fetch_token
self.client_config['token_uri'], **kwargs)
File "/home/y700/Env/cv-base-XRtgVf2K/lib/python3.7/site-packages/requests_oauthlib/oauth2_session.py", line 208, in fetch_token
state=self._state)
File "/home/y700/Env/cv-base-XRtgVf2K/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/clients/web_application.py", line 203, in parse_request_uri_response
response = parse_authorization_code_response(uri, state=state)
File "/home/y700/Env/cv-base-XRtgVf2K/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 268, in parse_authorization_code_response
raise MismatchingStateError()
oauthlib.oauth2.rfc6749.errors.MismatchingStateError: (mismatching_state) CSRF Warning! State not equal in request and response.
[13/Sep/2019 13:19:52] "GET /to_drive HTTP/1.1" 500 98701
the error is caused by a string
flow.fetch_token(authorization_response=authorization_response)
Hi @Lepiloff. It looks like you're getting an error about mismatching states. There is a bit more info about state here in the description of the parameters. State needs to match in the request and response.
I think you'll want to write one more function.
In the flask example down towards the bottom of the page, you'll see there are _two_ routes for the OAuth flow.
/authorize is called to initiate the authorization flow. It concludes by redirecting the user to the Google OAuth2 server. The state is stored in the session This state is used later in the callback.@app.route('/authorize')
def authorize():
# Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
CLIENT_SECRETS_FILE, scopes=SCOPES)
# The URI created here must exactly match one of the authorized redirect URIs
# for the OAuth 2.0 client, which you configured in the API Console. If this
# value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch'
# error.
flow.redirect_uri = flask.url_for('oauth2callback', _external=True)
authorization_url, state = flow.authorization_url(
# Enable offline access so that you can refresh an access token without
# re-prompting the user for permission. Recommended for web server apps.
access_type='offline',
# Enable incremental authorization. Recommended as a best practice.
include_granted_scopes='true')
# Store the state so the callback can verify the auth server response.
flask.session['state'] = state
return flask.redirect(authorization_url)
/oauth2callback processes the response from the OAuth2 server. This is where the user is sent after they've authorized your app. The state is verified in the authorization server response.@app.route('/oauth2callback')
def oauth2callback():
# Specify the state when creating the flow in the callback so that it can
# verified in the authorization server response.
state = flask.session['state']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
flow.redirect_uri = flask.url_for('oauth2callback', _external=True)
# Use the authorization server's response to fetch the OAuth 2.0 tokens.
authorization_response = flask.request.url
flow.fetch_token(authorization_response=authorization_response)
# Store credentials in the session.
# ACTION ITEM: In a production app, you likely want to save these
# credentials in a persistent database instead.
credentials = flow.credentials
flask.session['credentials'] = credentials_to_dict(credentials)
return flask.redirect(flask.url_for('test_api_request'))
Closing due to lack of activity. Please file a new issue if you are experiencing this problem.
Gracias ^^
Most helpful comment
@busunkim96 thank you for answering.
Yes, I use web server application. Google API documentation in some places not very clear. Now I know that
run_local_serveruses only for locall projects. It is very strange that there are no good examples on the Internet for using Django and Google API for my purposes. I will try to deal with this problem