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 __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 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 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 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 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 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 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 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 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 authorize_user_step1(calendar_id): """ Start the authorization steps for a user """ global TEMP_CREDS_CACHE, CLIENT_SECRETS_CACHE if CLIENT_SECRETS_CACHE is None: load_client_secret() auth_email = None if '@' in calendar_id: auth_email = calendar_id flow = Flow.from_client_config(CLIENT_SECRETS_CACHE, scopes=CALENDAR_SCOPES) flow.redirect_uri = GOOGLE_AUTH_REDIRECT auth_url, state = flow.authorization_url(access_type='offline', prompt='consent', login_hint=auth_email, include_granted_scopes='true') TEMP_CREDS_CACHE[state] = { 'calendar_id': calendar_id, 'state': state, 'code': None, 'scope': CALENDAR_SCOPES } save_credentials() return auth_url
def get(self, request): access_code = AccessToken.objects.filter(integration=3) org = Organization.objects.get() if access_code.exists(): access_code = access_code.first() # TODO: proper error handling necessary. try: flow = Flow.from_client_config(client_config={ "web": {"client_id": access_code.client_id, "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", "client_secret": access_code.client_secret, "redirect_uris": [settings.BASE_URL + "/api/auth/google_login"], "javascript_origins": [settings.BASE_URL]}}, scopes=['https://www.googleapis.com/auth/userinfo.email', 'openid'], redirect_uri=settings.BASE_URL + "/api/auth/google_login") flow.fetch_token(code=request.GET.get('code', '')) session = flow.authorized_session() results = session.get('https://openidconnect.googleapis.com/v1/userinfo').json() except: return redirect('/#/?error=not_found') if 'email' in results: users = get_user_model().objects.filter(email=results['email'].lower()) if users.exists() and org.google_login: user = users.first() user.backend = 'django.contrib.auth.backends.ModelBackend' login(request, user) if user.role == 1 or user.role == 2: return redirect('/#/admin/') else: return redirect('/#/portal/') return redirect('/#/?error=not_found')
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 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 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 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 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 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 build_google_calendar_auth_request(): flow = Flow.from_client_config(CLIENT_JSON, scopes=SCOPES) flow.redirect_uri = flask.url_for("finalize_google_auth", _external=True, _scheme=HTTP_SCHEME) flow.autogenerate_code_verifier = True authorization_url, state = flow.authorization_url(access_type='offline', include_granted_scopes='true', prompt='consent') flask.session['state'] = state flask.session['code_verifier'] = flow.code_verifier return flask.redirect(authorization_url)
def request_authentication(self, server: str, sheet_id: str) -> str: flow = Flow.from_client_config(self.gca_credentials, SCOPES) flow.redirect_uri = "urn:ietf:wg:oauth:2.0:oob" url, _ = flow.authorization_url() sheet = Sheet(sheet_id=sheet_id, waiting_token=True) self.sheet_store.set(server, sheet) self.flows[server] = flow return url
def create_google_flow(google_client_config): global _google_flow if _google_flow is None: _google_flow = Flow.from_client_config( google_client_config, scopes=SCOPES, redirect_uri="{}{}".format(QuerybookSettings.PUBLIC_URL, GSPREAD_OAUTH_CALLBACK), )
def authorize_google(request: HttpRequest) -> HttpResponseRedirect: """Build and present an auth URL to get permission to use Google Drive.""" flow = Flow.from_client_config( settings.GOOGLE_CLIENT_CONFIG, scopes=GoogleDriveAuth.SCOPES, redirect_uri=settings.GOOGLE_CLIENT_CONFIG["web"]["redirect_uris"][0], ) authorization_url, state = flow.authorization_url(access_type="offline", prompt="consent") request.session["state"] = state return HttpResponseRedirect(authorization_url)
def build_flow(state=None): """Build Flow Object""" with current_app.open_instance_resource( current_app.config["YOUTUBE_API_CLIENT_SECRET_FILE"], "r" ) as json_file: client_config = json.load(json_file) flow = Flow.from_client_config( client_config, scopes=current_app.config["YOUTUBE_READ_WRITE_SSL_SCOPE"], state=state, ) flow.redirect_uri = url_for("user.setting_youtube_oauth_callback", _external=True) return flow
def request_google_auth(request): """Admin view to begin Google OAuth auth""" if not settings.FEATURES.get("COUPON_SHEETS"): raise Http404 flow = Flow.from_client_config(generate_google_client_config(), scopes=REQUIRED_GOOGLE_API_SCOPES) flow.redirect_uri = urljoin(settings.SITE_BASE_URL, reverse("complete-google-auth")) authorization_url, state = flow.authorization_url( access_type="offline", include_granted_scopes="true", prompt="consent") request.session["state"] = state request.session["code_verifier"] = flow.code_verifier return redirect(authorization_url)
def test_callback_works(self, credentials_from_session_mock, flow_from_session_mock): request = self.factory.get('oauth2/oauth2callback', data={ 'state': json.dumps(self.fake_state), 'code': 123 }) self.session['google_oauth2_csrf_token'] = self.CSRF_TOKEN flow_config = { "client_config": { "web": { "client_id": 'client_idz', "client_secret": 'client_secretz', "auth_uri": googleoauth2django.GOOGLE_AUTH_URI, "token_uri": googleoauth2django.GOOGLE_TOKEN_URI } }, "scopes": ['email'], "state": json.dumps(self.fake_state), "redirect_uri": request.build_absolute_uri('oauth2/oauth2callback'), } flow = Flow.from_client_config(**flow_config) fake_credentials = Credentials( token='access_tokenz', id_token='base64encodedjwtidtoken', refresh_token='refresh_tokenz', token_uri=googleoauth2django.GOOGLE_TOKEN_URI, client_id='client_idz', client_secret='client_secretz', scopes=['email']) name = 'google_oauth2_flow_{0}'.format(self.CSRF_TOKEN) pickled_flow = object() self.session[name] = pickled_flow flow.fetch_token = mock.Mock() flow_from_session_mock.return_value = flow credentials_from_session_mock.return_value = fake_credentials request.session = self.session request.user = self.user response = views.oauth2_callback(request) self.assertIsInstance(response, http.HttpResponseRedirect) self.assertEqual(response.status_code, django.http.HttpResponseRedirect.status_code) self.assertEqual(response['Location'], self.RETURN_URL)
def oauth2_callback(req): address = req.cookies.get('ADDRESS') if not address: raise exc.HTTPBadRequest("cookie ADDRESS is not set") 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"], state=req.GET['state']) flow.redirect_uri = "http://localhost:8000/oauth2callback/" flow.fetch_token(code=req.GET['code']) # import pdb; pdb.set_trace() credentials_dict = credentials_to_dict(flow.credentials) # save in redis the credentials for this user/address. # this can be decoded with json.loads(base64.b64decode(b64str.decode('ascii'))) rdb.set(address.lower(), base64.b64encode(json.dumps(credentials_dict).encode('ascii'))) # The ID is formatted like: "startTime-endTime" where startTime and endTime are # 64 bit integers (epoch time with nanoseconds). TODAY = datetime.datetime.today().date() NOW = datetime.datetime.today() START = int(time.mktime(TODAY.timetuple()) * 1000000000) END = int(time.mktime(NOW.timetuple()) * 1000000000) DATA_SET = "%s-%s" % (START, END) DATA_SOURCE = "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps" credentials = google.oauth2.credentials.Credentials(**credentials_dict) fitness_service = googleapiclient.discovery.build('fitness', 'v1', credentials=credentials) resp = (fitness_service.users().dataSources().datasets().get( userId='me', dataSourceId=DATA_SOURCE, datasetId=DATA_SET).execute()) total_steps = sum([p['value'][0]['intVal'] for p in resp['point']]) # print("total_steps", total_steps) return get_template('approved.html').render(total_steps=total_steps, **req.GET)
def google_auth(): ''' Handles authentication of the Google Photos API. ''' 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_url, state = flow.authorization_url( access_type='offline', include_granted_scopes='true') return authorization_url
def __init__(self): client_config = { "web": { "client_id": config.googlefit_client_id, "project_id": "scripts-140708", "auth_uri": config.googlefit_auth_uri, "token_uri": config.googlefit_token_uri, "auth_provider_x509_cert_url": config.googlefit_auth_provider_x509_cert_url, "client_secret": config.googlefit_client_secret, "redirect_uris": [config.googlefit_redirect_uri], "javascript_origins": [config.googlefit_javascript_origins], } } flow = Flow.from_client_config(client_config, scopes=scopes) flow.redirect_uri = config.googlefit_redirect_uri self.client = flow