예제 #1
0
    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
예제 #2
0
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())
예제 #3
0
 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
예제 #4
0
 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
예제 #5
0
파일: gsuite.py 프로젝트: ask/aiohttp-oauth
 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
예제 #6
0
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('/')
예제 #7
0
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('/')
예제 #8
0
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())
예제 #9
0
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())
예제 #10
0
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('/')
예제 #12
0
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')
예제 #13
0
    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')
예제 #14
0
파일: google.py 프로젝트: ask/aiohttp-oauth
    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
예제 #15
0
    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)
예제 #16
0
    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)
예제 #17
0
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'
        })
예제 #18
0
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())
예제 #19
0
    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")
예제 #20
0
파일: gsuite.py 프로젝트: ask/aiohttp-oauth
    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
예제 #21
0
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"
        )
예제 #22
0
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)