def doauth(): print('in /doauth') client_config_str = os.getenv('GOOGLE_CLIENT_SECRETS', None) if client_config_str: client_config = json.loads(client_config_str) flow = Flow.from_client_config(client_config=client_config, scopes=SCOPES) else: # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps. flow = Flow.from_client_secrets_file(CLIENT_SECRET_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 = url_for('auth', _scheme='https', _external=True) if 'localhost' in flow.redirect_uri: flow.redirect_uri = url_for('auth', _scheme='http', _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. session['state'] = state return redirect(authorization_url)
def load_calendar(request): # here call method load calendar # print(request.user) # current user # obtain calendar token creds = CalendarCredentials.objects.filter(student=request.user) creds = pickle.loads(creds[0].credentials) if creds else None if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: try: creds.refresh(Request()) except: try: flow = Flow.from_client_config( json.loads(os.environ["CLIENT_CONFIG"]), SCOPES) flow.redirect_uri = ( "https://schedme.osc-fr1.scalingo.io/students/callback" ) authorization_url, state = flow.authorization_url( access_type="offline") return redirect(authorization_url) except: # When running on localhost creds = get_creds() else: try: flow = Flow.from_client_config( json.loads(os.environ["CLIENT_CONFIG"]), SCOPES) flow.redirect_uri = ( "https://schedme.osc-fr1.scalingo.io/students/callback") authorization_url, state = flow.authorization_url( access_type="offline") return redirect(authorization_url) except: # When running on localhost creds = get_creds() CalendarCredentials.objects.update_or_create( student=request.user, defaults={"credentials": pickle.dumps(creds)}) # obtain google calendar data and store it in our database events = get_events(creds) for event in events: default_value = { "start": event["start"]["dateTime"], "end": event["end"]["dateTime"], "isLocal": False, } if "title" in event.keys(): default_value["title"] = event["title"] Activity.objects.update_or_create(student=request.user, google_id=event["id"], defaults=default_value) messages.info( request, "The events in your calendar was successfully lodaded.", ) return redirect("students:index")
def request_oauth2_credentials(): ''' Steps: 1. Set authorization parameters 2. Redirect to Google's OAuth 2.0 server 3. Google prompts the user for consent 4. Handle the OAuth 2.0 server response 5. Exchange authorization code for refresh and access tokens ''' # Use the client_secret.json file to identify the application requesting # authorization. The client ID (from that file) and access scopes are required. flow = Flow.from_client_secrets_file(CLIENT_SECRETS_FILE, scopes=[YOUTUBE_UPLOAD_SCOPE]) # Indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value 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 in your # Google API's account you will get a 'redirect_uri_mismatch' error. flow.redirect_uri = REDIRECT_URI # Generate URL for request to Google's OAuth 2.0 server. # Use kwargs to set optional request parameters. 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', ) # Your application redirects the user to Google along with the list of requested permissions. # The user decides whether to grant the permissions to your application. print(authorization_url) # To-DO: This step should be handled by a web server automatically and should not require user input when in production authorization_response = input( "Go to the above url, allow permissions and then when you get redirected to a new page, paste the url here" ) # After the web server receives the authorization code, it can begin the exchange the authorization code for an access token. # First verify the authoriation server response by providing the same state token to protect against XSRF flow = Flow.from_client_secrets_file(CLIENT_SECRETS_FILE, scopes=[YOUTUBE_UPLOAD_SCOPE], state=state) flow.redirect_uri = REDIRECT_URI # Then exchange the authorization respnse (which contains the auth code) to get the credentials flow.fetch_token(authorization_response=authorization_response) credentials = flow.credentials return credentials
def fetch_token(self, code: str = None, authorization_response: str = None, state: str = None): """Complete the authentiction process. Parameters: code (``str``, *optional*): The code that the user got from google when they authorized your app. Defaults to None. authorization_response (``str``, *optional*): The reponse that the client sent to your server after the user authorized your app. Defaults to None. state (``str``, *optional*): The state used when you started the flow. Defaults to None. Returns: :obj:`~google_workspace.service.GoogleService`: Authenticated GoogleService. """ self.flow = Flow.from_client_config( self.client_config, scopes=self.scopes, redirect_uri=self.redirect_uri, state=state, ) self.flow.fetch_token(code=code, authorization_response=authorization_response) self.credentials = self.flow.credentials self._retrieve_session_data() self._save_session() self._init_service() return self
def callback(request): flow = Flow.from_client_config(json.loads(os.environ["CLIENT_CONFIG"]), SCOPES) flow.redirect_uri = "https://schedme.osc-fr1.scalingo.io/students/callback" authorization_response = request.build_absolute_uri() print("autho : ") print(authorization_response) flow.fetch_token(authorization_response=authorization_response) creds = flow.credentials CalendarCredentials.objects.update_or_create( student=request.user, defaults={"credentials": pickle.dumps(creds)}) # obtain google calendar data and store it in our database events = get_events(creds) for event in events: default_value = { "start": event["start"]["dateTime"], "end": event["end"]["dateTime"], "isLocal": False, } if "title" in event.keys(): default_value["title"] = event["title"] Activity.objects.update_or_create(student=request.user, google_id=event["id"], defaults=default_value) messages.info( request, "The events in your calendar was successfully lodaded.", ) return redirect("students:index")
def get_authorize_url(self, scopes: list): flow = Flow.from_client_config(self.client_config, scopes=scopes, redirect_uri=self.redirect_uri) authorization_url, _ = flow.authorization_url(access_type="offline", include_granted_scopes="true") return authorization_url
def __init__( self, service_provider, redirect_uri, scopes=None, ): scopes = scopes or ['https://www.googleapis.com/auth/calendar.events'] self.service_provider = service_provider self.credentials = service_provider.googlecredentials self.flow = Flow.from_client_config( { "web": { "client_id": self.credentials.client_id, "project_id": self.credentials.project_id, "client_secret": self.credentials.client_secret, "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", } }, scopes, ) self.flow.redirect_uri = redirect_uri
def oauth_authorize(): if "return_to" in request.args: session["redirect"] = request.args["return_to"] state = session.setdefault("analytics", {}) credentials = None if "token" in state: credentials = pickle.loads(state["token"]) if credentials and credentials.expired and credentials.refresh_token: credentials.refresh(Request()) if credentials and credentials.valid: return redirect(session.get("redirect", "/")) authorization = {"web": session["google_cloud"]} print(json.dumps(authorization, indent=4)) flow = Flow.from_client_config(authorization, scopes) host = os.getenv("API_URL", request.host_url[:-1]) # flow.redirect_uri = "https://localhost:5000/oauth/callback/" flow.redirect_uri = "{}{}".format(host, url_for("oauth_callback")) auth_url, app.config["state"] = flow.authorization_url( prompt='consent', access_type='offline', include_granted_scopes='true') # For some reason redirect_uri is not attached by the lib return redirect(auth_url)
def oauth_callback(): state = request.args.get("state", None) if not state: return render_template("error.html", errors=["No state provided to callback"]) host = os.getenv("API_URL", request.host_url[:-1]) try: authorization = {"web": session["google_cloud"]} flow = Flow.from_client_config(authorization, scopes, state=state) flow.redirect_uri = "{}{}".format(host, url_for("oauth_callback")) auth_url = request.url if auth_url.startswith("http://"): auth_url = "https" + auth_url[4:] flow.fetch_token(authorization_response=auth_url) sess_state = session["analytics"] sess_state.update({"token": pickle.dumps(flow.credentials)}) session["analytics"] = sess_state with open(app.config["pickle"], "wb") as fin: pickle.dump(app.config["creds"], fin) except: tb.print_exc() return render_template( "error.html", error=[ "An exception occured while attempting to complete the oauth flow" ]) return redirect(session["redirect"])
def get(): # Specify the state when creating the flow in the callback so that it can # verified in the authorization server response. result = MongoDB.instance().authorization.find_one({ 'service': 'calendar-service', 'type': 'state' }) state = result['state'] flow = Flow.from_client_secrets_file('.secrets/credentials.json', SCOPES, state=state) flow.redirect_uri = request.args.get('redirect_uri') # Use the authorization server's response to fetch the OAuth 2.0 tokens. authorization_response = request.url flow.fetch_token(authorization_response=authorization_response) # Store credentials in mongo. credentials = flow.credentials MongoDB.instance().authorization.replace_one( { 'service': 'calendar-service', 'type': 'credentials' }, credentials_to_dict(credentials), upsert=True, ) return make_response({'message': 'Successfully authorized.'}, 200)
def get(): flow = Flow.from_client_secrets_file('.secrets/credentials.json', 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 = request.args.get('redirect_uri') 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. MongoDB.instance().authorization.replace_one( { 'service': 'calendar-service', 'type': 'state' }, { 'service': 'calendar-service', 'type': 'state', 'state': state }, upsert=True, ) return {'authorization_url': authorization_url}
def oauth2callback(): # Specify the state when creating the flow in the callback so that it can # verified in the authorization server response. state = session['state'] flow = Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=None, state=state, redirect_uri=url_for('oauth2callback', _external=True) ) # Use the authorization server's response to fetch the OAuth 2.0 tokens. authorization_response = 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 session['credentials'] = credentials_to_dict(credentials) return redirect('/')
def oauth2_request(req): # meat is here: https://developers.google.com/identity/protocols/oauth2/web-server#python if req.method == "POST": address = req.POST['address'] flow = Flow.from_client_config( client_config={ "web": { "client_id": env("OAUTH_CLIENT_ID"), "client_secret": env("OAUTH_CLIENT_SECRET"), # "callbackUrl": "http://localhost:8000", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://accounts.google.com/o/oauth2/token" } }, scopes=["https://www.googleapis.com/auth/fitness.activity.read"]) flow.redirect_uri = "http://localhost:8000/oauth2callback/" auth_url, _ = flow.authorization_url(prompt='consent', access_type='offline', include_granted_scopes='true') resp = Response(status=302, location=auth_url) resp.set_cookie('ADDRESS', address) return resp return get_template('request.html').render()
def complete_google_auth(request): """Admin view that handles the redirect from Google after completing Google auth""" if not settings.FEATURES.get("COUPON_SHEETS"): raise Http404 state = request.session.get("state") if not state: raise GoogleAuthError( "Could not complete Google auth - 'state' was not found in the session" ) flow = Flow.from_client_config(generate_google_client_config(), scopes=REQUIRED_GOOGLE_API_SCOPES, state=state) flow.redirect_uri = urljoin(settings.SITE_BASE_URL, reverse("complete-google-auth")) flow.code_verifier = request.session["code_verifier"] flow.fetch_token(code=request.GET.get("code")) # Store credentials credentials = flow.credentials with transaction.atomic(): google_api_auth, _ = GoogleApiAuth.objects.select_for_update( ).get_or_create() google_api_auth.requesting_user = request.user google_api_auth.access_token = credentials.token google_api_auth.refresh_token = credentials.refresh_token google_api_auth.save() return redirect("{}?success=auth".format(reverse("sheets-admin-view")))
def authorize(): ''' Create a flow instance to manage the OAuth2 Authorization Grant Flow steps .. :quickref: User; Create a flow instance to manage the OAuth2 ''' # Check if user is logged_in, then redirect to main page. if session.get('logged_in', None): flash('You are already logged in.', 'warning') return redirect(url_for('main.list_categories')) # Create the flow instance using the client secret file flow = Flow.from_client_secrets_file(app.config['CLIENT_SECRET_FILE'], scopes=app.config['SCOPES']) # Add the redirect_uri to the oauth2session flow.redirect_uri = url_for('.oauth2callback', _external=True) # Generate the Authorization URL. Step 1 in the Oauth2.0 Authorization Flow authorization_url, state = flow.authorization_url( # Enable offline access to prevent re-prompting the user for permission access_type='offline', # Enable incremental authorization. include_granted_scopes='true') # Store the state in the session to verify the callback. session['state'] = state # Redirect the user to Google OAuth page to obtain consent return redirect(authorization_url)
def get_flow( redirect_uri: str, path_to_secrets: str, verification_string: str, state=None, ) -> 'Flow': ''' Utility method to handle OAuth conversation with Google Params: ------- redirect_uri: str Path to callback endpoint path_to_secrets: str Path to json file containing oauth secrets verification_string: str Random string to serve as an auth check on the callback ''' flow = Flow.from_client_secrets_file( path_to_secrets, scopes=os.environ.get('SCOPES').split(','), state=state, ) flow.redirect_uri = redirect_uri flow.code_verifier = verification_string return flow
def CredentialsFlowWrapper(client, credentials_only=False, **kwargs): # relax scope comparison, order and default scopes are not critical os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1' # parse credentials from file or json if RE_CREDENTIALS_JSON.match(client): client_json = json.loads(client) else: with open(client, 'r') as json_file: client_json = json.load(json_file) if credentials_only: return client_json else: if 'installed' in client_json: flow = InstalledAppFlow.from_client_config(client_json, APPLICATION_SCOPES, **kwargs) else: flow = Flow.from_client_config(client_json, APPLICATION_SCOPES, **kwargs) flow.user_agent = APPLICATION_NAME return flow
def google_auth_callback(): flow = Flow.from_client_config( json.loads(os.getenv('GOOGLE_CREDENTIALS')), scopes=['https://www.googleapis.com/auth/photoslibrary.readonly'], ) flow.redirect_uri = url_for('api.google_auth_callback', _external=True) authorization_response = request.url flow.fetch_token(authorization_response=authorization_response) if 'error' in authorization_response: return make_response( jsonify({ 'status': 401, 'success': False, 'message': f"authentication error: {authorization_response['error']}" })) app.google_credentials = flow.credentials return redirect(url_for('photo_gallery'))
def ViewCourseWork(chat_id, course_id): course_id = '' creds = None pickleToken_path = "AddCourse/" + str(chat_id) + "_token.pickle" credentials_path = "AddCourse/credentials.json" if os.path.exists(pickleToken_path): with open(pickleToken_path, '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 = Flow.from_client_secrets_file(credentials_path, SCOPES) creds = flow.run_local_server(port=users) with open(pickleToken_path, 'wb') as token: pickle.dump(creds, token) service = build('classroom', 'v1', credentials=creds) students_list = service.courses().courseWork().list( courseId=course_id).execute() return students_list
def build_flow(self, state=None): flow = Flow.from_client_config( self.config, scopes=self.scopes, redirect_uri=self.redirect_uri, state=state) return flow
def auth(): token = oauth.google.authorize_access_token() user = oauth.google.parse_id_token(token) session["user"] = user session["token"] = token sub = str(user["sub"]) row = db.execute("SELECT * FROM users WHERE id = ?", sub) # Authorize the user flow = Flow.from_client_config(client_config=app.config["CLIENT_CONFIG"], scopes=SCOPES) flow.redirect_uri = url_for("oauth2callback", _external=True) authorization_url, state = flow.authorization_url( access_type="offline", login_hint=sub, include_granted_scopes="true") # Store state in session session["state"] = state # Ensure user is logging in for the first time if len(row) == 0: # Add user to database db.execute("INSERT INTO users (id) VALUES (?)", sub) return redirect(authorization_url)
def oauth2callback(): state = session["state"] flow = Flow.from_client_config(client_config=app.config["CLIENT_CONFIG"], scopes=SCOPES, state=state) flow.redirect_uri = url_for("oauth2callback") # Use the authorization server's response to fetch the OAuth 2.0 tokens. authorization_response = request.url flow.fetch_token(authorization_response=authorization_response) # Store credentials in the session. credentials = flow.credentials session["credentials"] = { "token": credentials.token, "refresh_token": credentials.refresh_token, "token_uri": credentials.token_uri, "client_id": credentials.client_id, "client_secret": credentials.client_secret, "scopes": credentials.scopes } # Flash message flash("Hello, " + session["user"]["given_name"] + "!") return redirect("/")
def credentialsCheck(self): print('credentialsCheck::starting') if not self.creds or not self.creds.valid: if self.creds and self.creds.expired \ and self.creds.refresh_token: self.creds.refresh(Request()) else: ''' pathChecks is done here, this will only run at first launch after checking, we set the defaults values programmatically. ''' self.pathChecks([self.config, self.download_path]) self.createConfigBody() flow = Flow.from_client_secrets_file( self.client_id, header.SCOPES, redirect_uri='urn:ietf:wg:oauth:2.0:oob') self.flow = flow (auth_url, _) = flow.authorization_url(prompt='consent') pyotherside.send('authUrl', str(auth_url))
def get_credentials(): """Generates new credentials for google api. TODO: google_auth has yet to implement storage, so that may have wait for another day. TODO: This also doesn't automatically open in your browser. """ # We only need read permissions. scopes = [ 'https://www.googleapis.com/auth/drive.readonly', 'https://www.googleapis.com/auth/spreadsheets.readonly' ] flow = Flow.from_client_secrets_file( 'client_secret.json', scopes, redirect_uri='urn:ietf:wg:oauth:2.0:oob') auth_url, _ = flow.authorization_url(prompt='consent') print('Go to') print(auth_url) print('and copy Auth Code') code = input('Enter auth code: ') print("Fetching Token.") flow.fetch_token(code=code) return flow.credentials
def get_refresh_token(): # as we don't use session from flask, then we save into user registry, at least for now if not app.auth.authorized([], 'global_preferences', 'POST'): return app.auth.authenticate() secrets = request.files.get('secretsFile', None) if secrets is None: return api_error('Please provide your youtube credentials', 400) secrets.seek(0) file_content = secrets.read() yt_data = json.loads(bytes2string(file_content)) if 'web' not in yt_data: return api_error( 'OAuth project has to be configured as web in google console', 400) # let's save secrets file content in db for future usage global_serv = get_resource_service('global_preferences') global_serv.save_preference(YT_KEY, yt_data) redirect_uri = flask.url_for('video_upload.oauth2callback', _external=True, _scheme=SCHEME) flow = Flow.from_client_config(yt_data, scopes=SCOPES, redirect_uri=redirect_uri) auth_url, _ = flow.authorization_url(prompt='consent', access_type='offline', include_granted_scopes='true') return make_response(auth_url, 200)
def GetCourses(chat_id): creds = None pickleToken_path = "GetCourses/" + str(chat_id) + "_token.pickle" credentials_path = "GetCourses/credentials.json" if os.path.exists(pickleToken_path): with open(pickleToken_path, '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 = Flow.from_client_secrets_file(credentials_path, SCOPES) creds = flow.run_local_server(port=users) with open(pickleToken_path, 'wb') as token: pickle.dump(creds, token) service = build('classroom', 'v1', credentials=creds) results = service.courses().list().execute() courses = results.get('courses', []) answer = [] if not courses: answer.append('No courses found.') else: answer.append('Courses:') for course in courses: answer.append(course['name']) return answer
def get_authorization_credentials(google_credentials, email=''): # Use the client_secret.json file to identify the application requesting # authorization. The client ID (from that file) # and access scopes are required. flow = Flow.from_client_config( google_credentials, scopes=['https://www.googleapis.com/auth/calendar']) # Indicate where the API server will redirect the user # after the user completes # the authorization flow. The redirect URI is required. flow.redirect_uri = 'http://proton-dev.com:5000/authorize' # Generate URL for request to Google's OAuth 2.0 server. # Use kwargs to set optional request parameters. return flow.authorization_url( # Enable offline access so that you can refresh an access token without # res-prompting the user for permission. Recommended # for web server apps. access_type='offline', login_hint=email, prompt='consent', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true' )
def finalize_google_auth(): code = request.values.get('code') state = flask.session.get('state') code_verifier = flask.session.get('code_verifier') flask.session['state'], flask.session['code'], flask.session['code_verifier'] = None, None, None if (code is not None) & (code_verifier is not None): flow = Flow.from_client_config(CLIENT_JSON, scopes=SCOPES, state=state) flow.redirect_uri = flask.url_for('finalize_google_auth', _external=True, _scheme=HTTP_SCHEME) flow.fetch_token(code=code, code_verifier=code_verifier) credentials = flow.credentials current_google_calendar_user = current_user.google_calendar_user primary_calendar = get_primary_calendar_details(credentials) if primary_calendar: if current_google_calendar_user: update_existing_user_creds(current_google_calendar_user, credentials, \ primary_calendar, current_user) else: add_new_user_creds(credentials, primary_calendar, current_user) else: raise KeyError('Could not access a primary calendar for user %s' % current_user.id) else: return flask.jsonify({ 'errors': auth_form.errors }) return flask.redirect('/#/settings')
def _get_user_authentication_credentials(client_secret_file, scopes, credential_directory=None, local=False): """Returns user credentials.""" if credential_directory is None: credential_directory = os.getcwd() elif credential_directory == 'global': home_dir = os.path.expanduser('~') credential_directory = os.path.join(home_dir, '.credentials') if not os.path.exists(credential_directory): os.makedirs(credential_directory) else: pass credentials_path = os.path.join( credential_directory, 'sheets.googleapis.com-python.json') # TODO Change hardcoded name? credentials = None if os.path.exists(credentials_path): # expect these to be valid. may expire at some point, but should be refreshed by google api client... credentials = Credentials.from_authorized_user_file(credentials_path, scopes=scopes) if credentials: if credentials.expired and credentials.refresh_token: credentials.refresh(Request()) else: if local: flow = InstalledAppFlow.from_client_secrets_file( client_secret_file, scopes) credentials = flow.run_local_server() else: flow = Flow.from_client_secrets_file( client_secret_file, scopes=scopes, redirect_uri='urn:ietf:wg:oauth:2.0:oob') auth_url, _ = flow.authorization_url(prompt='consent') print( 'Please go to this URL and finish the authentication flow: {}'. format(auth_url)) code = input('Enter the authorization code: ') flow.fetch_token(code=code) credentials = flow.credentials # Save the credentials for the next run credentials_as_dict = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'id_token': credentials.id_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret } with open(credentials_path, 'w') as file: file.write(json.dumps(credentials_as_dict)) return credentials
def authGoogle(client_secret_file, scopes, redirect_uri): """ Function that signs into google Parameters client_secret_file : String name of the json file containing api access information scopes : List of strings indicating the scope of the API service redirect_uri : String url where to redirect after authentication flow Returns the url for google sign in prompt and the current state to be stored in Flask session for authGoogleComplete. """ # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps. flow = Flow.from_client_secrets_file(client_secret_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 = redirect_uri 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') return (authorization_url, state)
def _get_user_authentication_credentials(client_secret_file, scopes, credential_directory=None): """Returns user credentials.""" if credential_directory is None: credential_directory = os.getcwd() elif credential_directory == 'global': home_dir = os.path.expanduser('~') credential_directory = os.path.join(home_dir, '.credentials') if not os.path.exists(credential_directory): os.makedirs(credential_directory) else: pass credentials_path = os.path.join(credential_directory, 'sheets.googleapis.com-python.json') # TODO Change hardcoded name? if os.path.exists(credentials_path): # expect these to be valid. may expire at some point, but should be refreshed by google api client... return Credentials.from_authorized_user_file(credentials_path, scopes=scopes) flow = Flow.from_client_secrets_file(client_secret_file, scopes=scopes, redirect_uri='urn:ietf:wg:oauth:2.0:oob') auth_url, _ = flow.authorization_url(prompt='consent') print('Please go to this URL and finish the authentication flow: {}'.format(auth_url)) code = input('Enter the authorization code: ') flow.fetch_token(code=code) credentials = flow.credentials credentials_as_dict = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'id_token': credentials.id_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret } with open(credentials_path, 'w') as file: file.write(json.dumps(credentials_as_dict)) return credentials