async def handle_oauth_callback(self, request, session) -> dict: params = request.GET gc = GoogleClient(client_id=self._id, client_secret=self._secret) code = params.get('code') if not code: raise BadAttemptError("No google code found. It's possible the " "session timed out while authenticating.") otoken, _ = await gc.get_access_token(code, redirect_uri=self.redirect_uri) client = GoogleClient( # Need a new client, so it includes the new access token client_id=self._id, client_secret=self._secret, access_token=otoken) user, info = await client.user_info() r = await client.request( 'GET', f'https://www.googleapis.com/admin/directory/v1/users/' f'{info["id"]}?projection=full') json = await r.json() info = {'user': info, 'org_user': json} print('customerId:', json['customerId']) if self.approved_customers and json['customerId'] \ not in self.approved_customers: raise BadAttemptError("This app does not allow users " "outside of their organization.") return info
async def oauth_login(request): google_client = GoogleClient( client_id=request.app.config.GOOGLE_ID, client_secret=request.app.config.GOOGLE_SECRET, ) redirect_url = request.url.origin().join( request.app.router["oauth:login"].url_for()) logger.debug("Start OAUTH2") if not request.url.query.get("code"): logger.debug("Code isn't exist") return web.HTTPFound( google_client.get_authorize_url( redirect_uri=redirect_url, scope="email profile", )) logger.debug("Code {} was received successfully".format( request.url.query["code"])) token, data = await google_client.get_access_token( request.url.query["code"], redirect_uri=redirect_url, ) logger.debug("Token {} was received successfully".format(token)) session = await get_session(request) session['token'] = token logger.debug("Redirect URL: {}".format(redirect_url)) return web.HTTPFound(request.app.router["oauth:complete"].url_for())
def __init__( self, bot, client_id, client_secret, aiohttp_address, callback_address, port, loop=None, users=None, watching=None, ): self.loop = loop if loop else asyncio.get_event_loop() self.bot = bot self.google = GoogleClient( client_id=client_id, client_secret=client_secret, redirect_uri=f'http://{callback_address}:{port}/callback' ) self.users = ( self.load_users(users, self.google, loop=self.loop) if users else {} ) self.watching = self.load_watching(watching) if watching else {} self.upload_queue = asyncio.Queue() app = web.Application() app.add_routes([web.get("/callback", self.callback)]) self.upload.start() self.runner = web.AppRunner(app) self.loop.run_until_complete(self.runner.setup()) site = web.TCPSite(self.runner, aiohttp_address, 8080) self.web_task = asyncio.Task(site.start(), loop=loop) self.loggingOn = False
async def get_oauth_url(self, request, session, state): gc = GoogleClient(client_id=self._id, client_secret=self._secret) authorize_url = gc.get_authorize_url( scope= 'email profile https://www.googleapis.com/auth/admin.directory.user.readonly', redirect_uri=self.redirect_uri, state=state) return authorize_url
async def get_oauth_url(self, request, session, state): gc = GoogleClient( client_id=self._id, client_secret=self._secret ) authorize_url = gc.get_authorize_url( scope='openid email profile', redirect_uri=self.redirect_uri, state=state, hd=self.org) return authorize_url
async def oauth(request): client = GoogleClient(client_id=cfg.client_id, client_secret=cfg.client_secret) if 'code' not in request.url.query: return ResponseRedirect( client.get_authorize_url(scope='email profile', redirect_uri=cfg.redirect_uri)) token, data = await client.get_access_token(request.url.query['code'], redirect_uri=cfg.redirect_uri) request.session['token'] = token return ResponseRedirect('/')
async def oauth(request): client = GoogleClient(client_id=cfg.client_id, client_secret=cfg.client_secret) if 'code' not in request.GET: return web.HTTPFound( client.get_authorize_url(scope='email profile', redirect_uri=cfg.redirect_uri)) token, data = await client.get_access_token(request.GET['code'], redirect_uri=cfg.redirect_uri) session = await get_session(request) session['token'] = token return web.HTTPFound('/')
async def oauth_login(request): client = GoogleClient(client_id=request.app.config.OAUTH_ID, client_secret=request.app.config.OAUTH_SECRET) if 'code' not in request.GET: return web.HTTPFound( client.get_authorize_url( redirect_uri=request.app.config.REDIRECT_URI, scope='email profile')) token, data = await client.get_access_token( request.GET['code'], redirect_uri=request.app.config.REDIRECT_URI) session = await get_session(request) session['token'] = token return web.HTTPFound(request.app.router['oauth:complete'].url_for())
async def oauth_complete(request): session = await get_session(request=request) if session['token'] is None: return web.HTTPFound(request.app.router['oauth:login'].url_for()) client = GoogleClient(client_id=request.app.config.OAUTH_ID, client_secret=request.app.config.OAUTH_SECRET, access_token=session['token']) user, info = await client.user_info() google_id = info['id'] display_name = info['displayName'] email = info['emails'][0]['value'] async with request.app.db.acquire() as conn: try: await conn.execute(models.UserGoogle.__table__.insert().values( google_id=google_id, google_user=display_name, google_email=email)) except IntegrityError: await conn.execute(models.UserGoogle.__table__.update().where( models.UserGoogle.__table__.c.google_email == email).values( google_id=google_id, google_user=display_name, google_email=email)) session['display_name'] = display_name session['google_id'] = google_id session['email'] = email return web.HTTPFound(request.app.router['index'].url_for())
async def google_auth_sucess(request): code = request.rel_url.query.get('code') if not code: return web.HTTPBadRequest() access_token, _ = await google_client.get_access_token(code) google = GoogleClient( client_id=GOOGLE_CLIENT_ID, client_secret=GOOGLE_CLIENT_SECRET, access_token=access_token, ) resp = await google.request('GET', google.user_info_url) user = await User.query.where(User.google_id == resp['id']).gino.first() if not user: user = await User.create(nickname=resp['email'].split('@')[0], email=resp['email'], google_id=resp['id']) payload = {'exp': experied_at(), 'user_id': user.id} access_token = jwt.encode(payload, APP_SECRET).decode('utf-8') payload['exp'] = experied_at(access_token=False) refresh_token = jwt.encode(payload, APP_SECRET).decode('utf-8') await RefreshToken.create(token=refresh_token) return web.json_response({ 'access_token': access_token, 'refresh_token': refresh_token, })
async def oauth(request): client = GoogleClient( client_id=cfg.client_id, client_secret=cfg.client_secret ) if 'code' not in request.GET: return web.HTTPFound(client.get_authorize_url( scope='email profile', redirect_uri=cfg.redirect_uri )) token, data = await client.get_access_token( request.GET['code'], redirect_uri=cfg.redirect_uri ) session = await get_session(request) session['token'] = token return web.HTTPFound('/')
def google(request): google = GoogleClient( client_id='150775235058-9fmas709maee5nn053knv1heov12sh4n.apps.googleusercontent.com', client_secret='df3JwpfRf8RIBz-9avNW8Gx7', redirect_uri='http://%s%s' % (request.host, request.path), scope='email profile', ) if 'code' not in request.GET: return web.HTTPFound(google.get_authorize_url()) # Get access token code = request.GET['code'] token = yield from google.get_access_token(code) # Get a resource response = yield from google.request('GET', 'people/me') body = yield from response.read() return web.Response(body=body, content_type='application/json')
async def authenticate(self, request: Request): if request['method'] == 'GET' and \ any((x.match(request.url.path) for x in self.allowed_patterns)): return AuthCredentials(['unauthenticated']), UnauthenticatedUser() host = request.headers.get('host') if 'local' in host or 'internal' in host or \ '.' not in host: return AuthCredentials(['unauthenticated']), UnauthenticatedUser() elif self.id is None: # local dev username = '******' return AuthCredentials(['authenticated' ]), SimpleUser(username=username) elif request.url.path == '/oauth_callback/google': # handle redirect # print('sess', request.session) query = request.query_params state = query.get('state') code = query.get('code') gc = GoogleClient(client_id=self.id, client_secret=self.secret) host = get_hostname(request) if request.url.port: host += f':{request.url.port}' otoken, other = await gc.get_access_token( code, redirect_uri=f'{host}/oauth_callback/google') idt = other['id_token'] id_token = jwt.decode(idt, verify=False) email = id_token.get('email') if not (id_token.get('hd') == self.org == email.split('@')[1]): return AuthenticationError('Bad user') timestamp = time.time() request.session['ts'] = timestamp request.session['user'] = email request.state.redirect_url = state raise RedirectAuthError('need to redirect') elif request.session and request.session.get('user'): # make sure cookie is still valid timestamp = request.session.get('ts') now = time.time() if now - timestamp > 86520: raise StartAuthError user = request.session.get('user') return AuthCredentials(['authenticated' ]), SimpleUser(username=user) else: raise StartAuthError('Not logged in')
async def handle_oauth_callback(self, request, session) -> dict: params = request.query gc = GoogleClient(client_id=self._id, client_secret=self._secret) code = params.get('code') if not code: raise BadAttemptError( "No google 'code' parameter found. It's possible the " "session timed out while authenticating.") otoken, _ = await gc.get_access_token(code, redirect_uri=self.redirect_uri) client = GoogleClient( # Need a new client, so it includes the new access token client_id=self._id, client_secret=self._secret, access_token=otoken) user, info = await client.user_info() if self.approved_domains and info.get('domain') \ not in self.approved_domains: raise BadAttemptError("This app does not allow users " "outside of their organization.") return info
async def wrapped(request, **kwargs): if 'token' not in request.session: return ResponseRedirect('/oauth/google') client = GoogleClient(client_id=cfg.client_id, client_secret=cfg.client_secret, access_token=request.session['token']) try: user, info = await client.user_info() except Exception: return ResponseRedirect(cfg.oauth_redirect_path) return await fn(request, user, **kwargs)
async def wrapped(request, **kwargs): session = await get_session(request) if 'token' not in session: return web.HTTPFound(cfg.oauth_redirect_path) client = GoogleClient(client_id=cfg.client_id, client_secret=cfg.client_secret, access_token=session['token']) try: user, info = await client.user_info() except Exception: return web.HTTPFound(cfg.oauth_redirect_path) return await fn(request, user, **kwargs)
async def test_client(http): from aioauth_client import GoogleClient google = GoogleClient(client_id='123', client_secret='456', access_token='789') data = await google.request('GET', '/') assert data == {'response': 'ok'} http.assert_called_with( 'GET', 'https://www.googleapis.com/', params=None, headers={ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'Authorization': 'Bearer 789' })
async def oauth_complete(request): session = await get_session(request=request) if session["token"] is None: logger.debug("No token, redirect to login page") return web.HTTPFound(request.app.router['oauth:login'].url_for()) client = GoogleClient(client_id=request.app.config.GOOGLE_ID, client_secret=request.app.config.GOOGLE_SECRET, access_token=session["token"]) user, info = await client.user_info() google_id = info.get("id") display_name = info.get("name") email = info.get("email") logger.debug("Vars:{}, {}, {}.".format(google_id, display_name, email)) async with request.app["pool"].acquire() as conn: row = await conn.fetchrow( 'SELECT * FROM user_google WHERE google_id= $1', google_id) if not row: logger.info( "Add a new google account with ID: {}.".format(google_id)) _sql = f""" INSERT INTO user_google (google_id, google_user, google_email) VALUES ('{google_id}', '{display_name}', '{email}'); """ res = await request.app["pool"].execute(_sql) else: logger.info( "Update existing account with ID: {}.".format(google_id)) _sql = f""" UPDATE user_google SET google_user='******', google_email='{email}' WHERE google_id='{google_id}'; """ res = await request.app["pool"].execute(_sql) # import ipdb; ipdb.set_trace() session['display_name'] = display_name session['google_id'] = google_id session['email'] = email logger.debug( "Add to current session information ({}).".format(display_name)) return web.HTTPFound(request.app.router['account'].url_for())
def __init__(self, cID, cSecret, token_path): self.logger = logging.getLogger(self.__class__.__name__) self.chat_subscribers = [] #self.thread = threading.Thread(target=self.run) self.livechatIds = {} self.message_queue = Queue() #storage = Storage(credential_filename) #credentials = storage.get() if not token_path: otoken = do_interactive_auth(cID, cSecret) else: with open(token_path): otoken = file.read() self.google = GoogleClient(client_id=client_id, client_secret=client_secret, access_token=otoken) self.livechat_api = LiveChatApi(self.http) #!!!move this out of init!!! ''' for chat_id in livechatIds: self.livechatIds[chat_id] = {'nextPoll': datetime.now(), 'msg_ids': set(), 'pageToken': None} result = self.livechat_api.live_chat_messages_list(chat_id) while result['items']: pollingIntervalMillis = result['pollingIntervalMillis'] self.livechatIds[chat_id]['msg_ids'].update(msg['id'] for msg in result['items']) self.livechatIds[chat_id]['nextPoll'] = datetime.now() + timedelta(seconds=pollingIntervalMillis / 1000) if result['pageInfo']['totalResults'] > result['pageInfo']['resultsPerPage']: self.livechatIds[chat_id]['pageToken'] = result['nextPageToken'] time.sleep(result['pollingIntervalMillis'] / 1000) result = self.livechat_api.live_chat_messages_list(chat_id, pageToken=self.livechatIds[chat_id]['pageToken']) else: break ''' #!!!end move this out of init!!! self.logger.debug("Initalized")
async def handle_oauth_callback(self, request, session) -> dict: params = request.query gc = GoogleClient( client_id=self._id, client_secret=self._secret ) code = params.get('code') if not code: raise BadAttemptError("No google code found. It's possible the " "session timed out while authenticating.") otoken, json = await gc.get_access_token(code, redirect_uri=self.redirect_uri) idt = json['id_token'] id_token = jwt.decode(idt, verify=False) email = id_token.get('email') if not (id_token.get('hd') == self.org == email.split('@')[1]): raise BadAttemptError("This app does not allow users " "outside of their organization.") info = {'username': email, 'email': email, 'name': email.split('@')[0].replace('.', ' ').title()} return info
class ImageSaverCog(commands.Cog, name="Image saver cog"): def __init__( self, bot, client_id, client_secret, aiohttp_address, callback_address, port, loop=None, users=None, watching=None, ): self.loop = loop if loop else asyncio.get_event_loop() self.bot = bot self.google = GoogleClient( client_id=client_id, client_secret=client_secret, redirect_uri=f'http://{callback_address}:{port}/callback' ) self.users = ( self.load_users(users, self.google, loop=self.loop) if users else {} ) self.watching = self.load_watching(watching) if watching else {} self.upload_queue = asyncio.Queue() app = web.Application() app.add_routes([web.get("/callback", self.callback)]) self.upload.start() self.runner = web.AppRunner(app) self.loop.run_until_complete(self.runner.setup()) site = web.TCPSite(self.runner, aiohttp_address, 8080) self.web_task = asyncio.Task(site.start(), loop=loop) self.loggingOn = False @staticmethod def load_users(json, auth_client, loop=None): loop = loop if loop else asyncio.get_event_loop() return { int(user): Token.load(token, auth_client, loop) for user, token in json.items() } @staticmethod def load_watching(json): return { int(channel): { int(author_id): user_id for author_id, user_id in users.items() } for channel, users in json.items() } def cog_unload(self): self.upload.cancel() self.loop.run_until_complete(self._stop()) async def _stop(self): await self.runner.cleanup() await self.web_task self.save() def save(self): users = {u: t.save() for u, t in self.users.items()} with open("users.json", "w") as f: json.dump(users, f) with open("watching.json", "w") as f: json.dump(self.watching, f) @tasks.loop() async def upload(self): u = await self.upload_queue.get() upload_tokens = [] async with aiohttp.ClientSession( headers={"Authorization": f"Bearer {str(u.bearer)}"} ) as session: for pic in u.pictures: async with session.post( "https://photoslibrary.googleapis.com/v1/uploads", data=await pic.attachment.read(), headers={ "Content-Type": "application/octect-stream", "X-Goog-Upload-File-Name": pic.attachment.filename, "X-Goog-Upload-Protocol": "raw", }, ) as resp: await u.update1(resp) if resp.status == 200: upload_tokens.append( {"description": pic.description, "token": await resp.text()} ) if len(upload_tokens) > 0: async with session.post( "https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate", json={ "newMediaItems": [ { "description": t["description"], "simpleMediaItem": {"uploadToken": t["token"]}, } for t in upload_tokens ] }, ) as resp: await u.update2(resp) @commands.Command async def login(self, ctx): id = ctx.author.id authorize_url = self.google.get_authorize_url( scope="https://www.googleapis.com/auth/photoslibrary.appendonly", state=str(id), access_type="offline", ) await ctx.author.send(f"Login with google here: {authorize_url}") @commands.Command async def watch(self, ctx, user: commands.UserConverter): channel_id = int(ctx.channel.id) user_id = int(user.id) author_id = int(ctx.author.id) if not self.watching.get(channel_id): self.watching[channel_id] = {} if not self.watching.get(channel_id).get(user_id): self.watching[channel_id][user_id] = [] if not author_id in self.watching.get(channel_id).get(user_id): self.watching[channel_id][user_id].append(author_id) await ctx.send( f"I'm watching {user} for images in this channel to upload to {ctx.author}'s google photos library'" ) @commands.Cog.listener() async def on_message(self, message): # are we watching this channel? if message.author != self.bot.user: channel = self.watching.get(message.channel.id) if channel: # are we watching any users in this channel? users = channel.get(message.author.id, []) # upload for all users we're watching for. for user_id in users: if user_id in self.users.keys(): # Message has title + 1 picture if message.content and len(message.attachments) == 1: upload = Upload( self.bot, [Picture(message.content, message.attachments[0])], message, self.users[user_id], self.bot.get_user(user_id), self.loggingOn, ) await self.upload_queue.put(upload) await upload.log() elif len(message.attachments) > 0: upload = Upload( self.bot, [Picture(a.filename, a) for a in message.attachments], message, self.users[user_id], self.bot.get_user(user_id), self.loggingOn, ) await self.upload_queue.put(upload) await upload.log() @commands.command() @commands.is_owner() async def stop(self, ctx): await self.bot.logout() @commands.command() @commands.is_owner() async def check(self, ctx): await ctx.author.send(f"users: {self.users}") await ctx.author.send(f"watching: {self.watching}") @commands.group() @commands.is_owner() async def logging(self, ctx): if ctx.invoked_subcommand is None: await ctx.author.send("Invalid logging command") @logging.command() async def on(self, ctx): self.loggingOn = True await ctx.author.send("Logging turned on") @logging.command() async def off(self, ctx): self.loggingOn = False await ctx.author.send("Logging turned off") async def callback(self, request): user_id = request.query.get("state") code = request.query.get("code") otoken, meta = await self.google.get_access_token(code) self.users[int(user_id)] = Token( otoken, meta.get("refresh_token"), meta.get("expires_in"), self.google, loop=self.loop, ) return web.Response( text="Thank you, you can now close this tab and go back to discord" )
from http import HTTPStatus from json import JSONDecodeError from aiohttp import web import jwt from aioauth_client import GoogleClient from conf import APP_SECRET, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET from authorization.utils import experied_at from authorization.models import RefreshToken from models import User google_client = GoogleClient( client_id=GOOGLE_CLIENT_ID, client_secret=GOOGLE_CLIENT_SECRET, redirect_uri='http://localhost:5000/auth/google/sucess') scope = 'https://www.googleapis.com/auth/userinfo.email' google_authorize_url = google_client.get_authorize_url(scope=scope) async def google_auth(request): raise web.HTTPFound(google_authorize_url) async def google_auth_sucess(request): code = request.rel_url.query.get('code') if not code: return web.HTTPBadRequest() access_token, _ = await google_client.get_access_token(code)