Exemplo n.º 1
0
async def checkaccesskey(request, api_key):
    if request.method == "OPTIONS":
        return HTTPResponse(None, 200, None)
    if api_key is None:
        raise Unauthorized("Please include API Key in query")
    valid, message = await check_apikey_valid(api_key)
    if not valid:
        if request.method == "HEAD":
            return HTTPResponse(None, 401, None)
        else:
            if message:
                raise Unauthorized(
                    "API Key validation error: {}".format(message))
            raise Unauthorized("API Key is not valid")
    works, message = await test_apikey(api_key)
    if not works:
        if request.method == "HEAD":
            return HTTPResponse(None, 401, None)
        else:
            if message:
                raise Unauthorized("API Key Test error: {}".format(message))
            raise Unauthorized(
                "API Key is not valid but does not work. Perhaps the OAuth access key has been revoked."
            )
    return HTTPResponse(message, 200)
Exemplo n.º 2
0
async def verify_auth(route: str, headers: dict) -> None:
    kind, token = headers.get('Authorization', 'no auth').split()
    if kind != 'Bearer':
        raise Unauthorized('invalid token type', scheme='Bearer')

    # Use the shared secret to decrypt. Homefully we can generate this from a
    # single source of truth, ie. the name of the method, or the URL, or
    # something like that. Maybe the `Location` header?
    async with aiohttp.ClientSession() as sess:
        kms = KMS(API_PROJECT, API_SERVICE, route, session=sess)
        try:
            # If we can't decrypt the token, we know it was not encrypted with
            # the referenced KMS key, eg. the request was made by someone who
            # does not have access to the secret associated with this
            # project/service/route/method.
            payload = decode(await kms.decrypt(token))
        except Exception:
            raise Unauthorized('access denied', scheme='Bearer')

    # Checking this value let's us avoid replay attacks, eg. by making sure
    # someone who intercepted a token can not use it for their own requests
    # later.
    if json.loads(payload).get('epoch', 0) < time.time() - TOKEN_TTL:
        raise Unauthorized('token expired', scheme='Bearer')

    # At the point, we've proven that the request has been generated recently
    # by a valid user who is whitelisted for accessing this endpoint.
    return
Exemplo n.º 3
0
async def authorize(request: Request, roles: Optional[List[str]]):
    """
    Authorize user role against roles
    @param request:
    @param roles:
    @return:
    """
    if not roles:
        roles = ACTIVE_ROLES
    redis_client: Redis = request.app.redis_client
    db_client: DatabaseClient = request.app.db_client
    user_id: int = request.ctx.user_id
    cached_role: str = await redis_client.get(CacheKey.user_role(user_id),
                                              encoding="utf-8")
    if cached_role:
        if cached_role not in roles:
            raise Unauthorized("Unauthorized")
        return
    role_repo: RoleRepository = RoleRepository(db_client)
    role = role_repo.find_by_user_id(user_id)
    if not role or role["name"] not in roles:
        raise Unauthorized("Unauthorized")
    await redis_client.set(CacheKey.user_role(user_id),
                           role["name"],
                           expire=3600)
Exemplo n.º 4
0
async def auth_server(session: aiohttp.ClientSession, username: str,
                      password: str):
    """ 登录到 SDUT AuthServer(七天有效期) """
    # 获取页面参数
    async with session.get(
        'http://authserver.sdut.edu.cn/authserver/login') as resp:
        text = await resp.text()
        cookies = resp.cookies
    soup = BeautifulSoup(text, 'html.parser')
    ipts = soup.form.find_all('input')
    data = {
        'username': username,
        'password': password,
        'rememberMe': 'on',  # 七天内记住我
    }

    for ipt in ipts:
        if ipt.get('value'):
            data[ipt.get('name')] = ipt.get('value')

    JSESSIONID_auth = cookies.get('JSESSIONID_auth').value

    # 提交登录
    # 山东理工大学统一登录平台有一处 Set-Cookie 错误,Python 没有对错误的格式进行兼容
    # 手动处理第一次跳转,处理格式兼容
    async with session.post(
        f'http://authserver.sdut.edu.cn/authserver/login;{JSESSIONID_auth}',
        data=data,
        allow_redirects=False) as resp:
        headers = resp.headers

        next_url = headers.get('Location')

        for key in headers:
            if key.lower() == 'set-cookie' and headers[key].startswith(
                    'CASTGC'):
                castgc = headers[key].split(';')[0][7:]
                session.cookie_jar.update_cookies(
                    {'CASTGC': castgc},
                    URL('http://authserver.sdut.edu.cn/authserver'))
                break
        else:
            raise Unauthorized('获取 Cookie 失败,请检查用户名与密码。如果问题持续出现,请联系作者。')

    # 手动进行后续的跳转
    async with session.get(next_url) as resp:
        text = await resp.text()
        url = str(resp.url)

    # 若页面跳转至首页,则说明登录成功
    if url == 'http://authserver.sdut.edu.cn/authserver/index.do':
        return True
    # 若页面跳转回登录界面,则说明登录失败(用户名或密码错误)
    elif url == 'http://authserver.sdut.edu.cn/authserver/login':
        raise Unauthorized('用户名或密码错误')
    elif url == 'http://authserver.sdut.edu.cn/authserver/pcImproveInfo.do':
        raise Forbidden('需要修改初始密码后使用')
    else:
        print(url)
        raise ServerError('发生意料之外的错误,如果问题持续出现,请联系作者。')
Exemplo n.º 5
0
async def update_user(request, id, user) -> HTTPResponse:
    """ Updates an already existing user """

    if user:
        if user.id != int(id):
            raise Unauthorized('Unauthorized access.', status_code=400)
        with scoped_session() as session:
            ret_user = session.query(User).filter(User.id == int(id)).first()
            data = request.json or {}
            if 'username' in data and data[
                    'username'] != ret_user.username and session.query(
                        User).filter(
                            User.username == data['username']).first():
                return sanic_json(
                    Response('Please use a different username.').__dict__,
                    status=400)
            if 'email' in data and data[
                    'email'] != ret_user.email and session.query(User).filter(
                        User.email == data['email']).first():
                return sanic_json(
                    Response('Please use a different email address.').__dict__,
                    status=400)
            if 'password' in data:
                user.set_password(data['password'])
                session.query(User).filter(User.id == int(id)).update({
                    User.username:
                    data['username'],
                    User.email:
                    data['email'],
                    User.password:
                    user.password,
                    User.modified_at:
                    datetime.utcnow()
                })
                session.commit()
                return sanic_json(
                    Response('User successfully updated.').__dict__,
                    status=200)
            else:
                session.query(User).filter(User.id == int(id)).update({
                    User.username:
                    data['username'],
                    User.email:
                    data['email'],
                    User.modified_at:
                    datetime.utcnow()
                })
                session.commit()
                return sanic_json(
                    Response('User successfully updated.').__dict__,
                    status=200)
    else:
        raise Unauthorized('Please provide credentials.', status_code=400)
Exemplo n.º 6
0
async def get_user(request, id, user) -> HTTPResponse:
    """ Retrieves from the DB a particular user using his `id` """

    if user:
        if user.id == int(id):
            with scoped_session() as session:
                user = session.query(User).filter(User.id == int(id)).first()
                return sanic_json(user.to_dict())
        else:
            raise Unauthorized('Unauthorized access.', status_code=400)
    else:
        raise Unauthorized('Please provide credentials.', status_code=400)
Exemplo n.º 7
0
async def delete_user(request, id, user) -> HTTPResponse:
    """ Deletes an existing user from the DB"""

    if user:
        if user.id == int(id):
            with scoped_session() as session:
                session.query(User).filter(User.id == int(id)).delete()
                return sanic_json(
                    Response('User successfully removed.').__dict__,
                    status=200)
        raise Unauthorized('Unauthorized access.', status_code=400)
    else:
        raise Unauthorized('Please provide credentials.', status_code=400)
Exemplo n.º 8
0
    def check_auth(self, request: Request) -> None:
        try:
            if request.ctx.request_user is None:
                logger.error("unauthorized")
                raise Unauthorized("Unauthorized")

            if self.required_scopes:
                if not (set(self.required_scopes)
                        & set(request.ctx.request_user.scopes)):
                    logger.error("forbidden")
                    raise Forbidden("Forbidden")
        except AttributeError:
            logger.error("unauthorized")
            raise Unauthorized("Unauthorized")
Exemplo n.º 9
0
async def customer(request):
    data = request.json
    if not request.headers.get('Authentication'):
        raise Unauthorized("It seems like you're not authenticated", 401)
    db = get_mongo_conn()

    name = data['namec']
    data.pop('namec')

    data['name'] = name
    customer = {
        "defaultBank": data['defaultBank'],
        "name": data['name'],
        "email": data['email']
    }
    headers = {
        'Authorization': request.headers.get('Authorization'),
        'X-CUSTOMER-ID': CUSTOMER_ID,
        "Accept": "application/json",
        "Content-Type": "application/json"
    }
    r = requests.post("https://api.paystand.co/v3/customers/accounts",
                      json.dumps(data),
                      headers=headers)
    j = r.json()
    if 'account' in j:
        customer['bank_id'] = j['id']
        await db.customer.insert_one(customer)
        return response.json({"customerData": j}, 200)
    else:
        return response.json(j['error']['description'],
                             int(j['error']['status']))
Exemplo n.º 10
0
    async def post(self, request):
        args = validate_required_params(request.args, 'idtoken')

        token = args['idtoken'][0].replace("'", "").replace('"', '')
        # example from https://developers.google.com/identity/sign-in/web/backend-auth
        try:
            session = requests.session()
            cached_session = cachecontrol.CacheControl(session)
            request = google.auth.transport.requests.Request(
                session=cached_session)
            id_info = id_token.verify_oauth2_token(token, request, CLIENT_ID)

            if id_info['iss'] not in [
                    'accounts.google.com', 'https://accounts.google.com'
            ]:
                raise ValueError('Wrong issuer.')

            user_id = id_info['sub']
            user_nickname = id_info['name']
            user_photo = str(id_info['picture']).replace('=s96-c', '')
            session_token = self.db.sign_in_or_create_oauth_user(
                user_id, user_nickname, user_photo)
            response = json({'session_id': session_token})
            response.cookies['session_token'] = session_token
            return response

        except ValueError:
            raise Unauthorized('Token not accepted')
            pass
Exemplo n.º 11
0
async def _check_token_redis(token):
    connection = await db.RedisEngine.create()
    item = await connection.get(str(token))
    if item:
        return item
    else:
        raise Unauthorized('Need sign in')
Exemplo n.º 12
0
async def checkapikey(request):
    if request.method == "OPTIONS":
        return HTTPResponse(None, 200, None)
    existing_apikey = request.headers.get("X-API-Key")
    if existing_apikey:
        return await checkaccesskey(request, existing_apikey)
    raise Unauthorized("Please include X-API-Key")
Exemplo n.º 13
0
async def bank_payment(request):
    data = request.json
    db = get_mongo_conn()
    if not (request.headers.get('Authorization')):
        raise Unauthorized("It seems like you're not authenticated", None)
    headers = {
        'Authorization': request.headers.get('Authorization'),
        'X-CUSTOMER-ID': CUSTOMER_ID,
        "Accept": "application/json",
        "Content-Type": "application/json"
    }
    r = requests.post("api.paystand.com/v3/payments/secure",
                      data=data,
                      headers=headers)
    j = r.json()
    if 'id' in j:
        payer = await db.payer.find_one({'id': j['payer_id']}, {'_id': 0})
        if not payer:
            await db.payer.insert_one(j['payer'])
            del j['_id']
        return response.json({'paymentData': r.json()}, 200)
    else:
        j = r.json()
        return response.json(j['error']['description'],
                             int(j['error']['status']))
Exemplo n.º 14
0
    async def transfer_role(self, request: Request, actor: "User",
                            consume: TransferRoleRequest) -> OkListResult:
        """Transfer a role from the actor to the provided user"""
        url = self.get_url()
        role = f"{consume.role}@{url}"
        owner = await request.app._models.User.get(self._table,
                                                   email=consume.owner)
        if role not in owner.roles:
            raise Unauthorized(f"{owner.name} has not {consume.role} @ {url}")

        newOwner = await request.app._models.User.get(self._table,
                                                      email=consume.newOwner)
        if role in newOwner.roles:
            raise ValidationError(
                f"{newOwner.name} has already {consume.role} @ {url}")

        newOwner_roles = newOwner.roles
        newOwner_roles.append(role)
        owner_roles = owner.roles
        owner_roles.pop(owner_roles.index(role))

        async with await self._table.database.client.start_session() as s:
            async with s.start_transaction():
                await newOwner.update(request.app._models,
                                      roles=newOwner_roles)
                await owner.update(request.app._models, roles=owner_roles)

        return {"newOwner": newOwner_roles, "exOwner": owner_roles}
Exemplo n.º 15
0
    async def decorated(*args, **kwargs):
      request = None
      for arg in args:
        if hasattr(arg, "app") and hasattr(arg.app, "models"):
          request = arg
          break

      if request is None:
        raise InvalidRoute(func.__qualname__)

      if func.__decorators__["permission"]["name"] is None:
        permission = "call" if func.__name__ == '__call__' else func.__name__
      else:
        permission = func.__decorators__["permission"]["name"]

      permRepo = await args[0].ancestors(request.app.models, check = lambda x: hasattr(x, "permissions") and x.permissions)
      if isinstance(permRepo, list) and len(permRepo):
        permRepo = permRepo[0]

      perm = await permRepo.get_permission(args[0].__class__.__name__, permission)
      actor = await (yAuth()._actor(request))

      if await perm.can(actor, args[0], request):
        return await func(*args, **kwargs)

      raise Unauthorized("Not enought privileges")
Exemplo n.º 16
0
    async def inner(request, *args, req_args=None, **kwargs):
        # Validate the token before checking permission
        requester = await get_token_requester_from_request(request)

        # Invalidate the staff if he is disabled
        if "role_id" in requester and requester["disabled"]:
            raise Unauthorized(
                "Your account have been disabled. Please contact your supervisor."
            )

        if not model:
            return await func(request,
                              req_args=req_args,
                              requester=requester,
                              *args,
                              **kwargs)

        # Role authorization
        permissions = model.permissions[request.method]
        if ROLES[requester["role_id"]] not in permissions:
            raise_permission_exception()

        return await func(request,
                          req_args=req_args,
                          requester=requester,
                          *args,
                          **kwargs)
Exemplo n.º 17
0
async def verify_token_in_redis(token):
    connection = await RedisEngine.get_redis_engine()
    try:
        await connection.get(token)
        return token
    except TypeError:
        raise Unauthorized('Unauthorized user')
Exemplo n.º 18
0
    async def _sign_in_with_token(self, request):
        args = validate_required_params(request.args, 'idtoken')

        token = args['idtoken'][0].replace("'", "").replace('"', '')

        try:
            session = requests.session()
            cached_session = cachecontrol.CacheControl(session)
            request = google.auth.transport.requests.Request(
                session=cached_session)
            id_info = id_token.verify_oauth2_token(token, request,
                                                   self.client_id)

            if id_info['iss'] not in ['accounts.google.com',
                                      'https://accounts.google.com']:
                raise ValueError('Wrong issuer.')

            user_id = id_info['sub']
            user_nickname = id_info['name']
            user_photo = str(id_info['picture']).replace('=s96-c', '')

            session_token = self._db_manager.sign_in_or_create_oauth_user(
                user_id, user_nickname, user_photo)

            response = json({'session_token', session_token})
            response.cookies['session_token'] = session_token
            return response

        except ValueError:
            raise Unauthorized('Token not accepted')
            pass
Exemplo n.º 19
0
            async def decorated(request, *args, **kwargs):
                nonlocal self, plug, reg, context
                for func in context._before_request_funcs:
                    r = func()
                    if isawaitable(r):
                        r = await r
                request_context = context['request'][id(request)]
                _oauth = request_context.get('oauth', None)
                if _oauth:
                    return f(request, *args, context=context, **kwargs)
                valid, req = plug.verify_request(request, scopes, self)

                for func in context._after_request_funcs:
                    r = func(valid, req)
                    if isawaitable(r):
                        r = await r
                    valid, req = r

                if not valid:
                    if context._invalid_response:
                        return context._invalid_response(req)
                    raise Unauthorized("Unauthorized")
                request_context['oauth'] = req
                ret = f(request, *args, context=context, **kwargs)
                if isawaitable(ret):
                    ret = await ret
                return ret
Exemplo n.º 20
0
    async def post(self, request, *args, **kwargs):
        if request.json is not None:
            user, errors = UserLoginSchema().load(request.json)
            if errors is not None and len(errors) > 0:
                raise InvalidUsage(errors)
            else:
                if user.exists():
                    clear_password = user.cleartext_passowrd
                    user = user.get_by_email(user.email)
                    if not user.password_matched(clear_password):
                        raise Unauthorized(
                            "You are not allowed into the secret garden!")

                    jwt, output = await self.responses.get_access_token_output(
                        request, user, self.config, self.instance)

                    refresh_token = await self.instance.auth.generate_refresh_token(
                        request, user)
                    output.update(
                        {self.config.refresh_token_name: refresh_token})

                else:
                    raise InvalidUsage("User do not exists")
        else:
            raise InvalidUsage("Missing JSON body")

        return response.json({
            "jwt": jwt,
            "refresh_token": refresh_token
        },
                             status=201)
Exemplo n.º 21
0
async def token(request: Request):
    """ 登录,获取 cookies,创建 token,存入数据库并返回 """
    userid = request.args.get('userid')
    if userid is None:
        raise Unauthorized(
            '接到学校网络中心通知,本小程序涉及非法使用,因此主动停止提供服务,使用权限的申请请求已被拒绝,因此本程序将无限期停止服务。请不要继续尝试登录!也请务必不要再向外传播!谢谢同学们!'
        )
    username = request.form.get('userid') or request.json.get('userid')
    password = request.form.get('password') or request.json.get('password')
    x_referer = request.headers.get('X-Referer', 'Unknown')

    async with aiohttp.ClientSession(headers=headers,
                                     loop=asyncio.get_event_loop()) as session:
        # 登录至 AuthServer,如果登录失败则会触发登录失败 401
        await auth_server(session, username, password)
        cookies = auth_server_dump_cookies(session)

    # 生成 token
    now = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
    token = f'SDUTAPI-{x_referer}-{username}-{now}-' + str(uuid.uuid4())
    cookies_str = python_json.dumps(cookies)

    # 将 token 与 cookies 存入 redis,七天有效
    await app.config.redis.setex(token, 7 * 24 * 60 * 60, cookies_str)

    # 返回 token
    return success(data={'token': token})
Exemplo n.º 22
0
 def handler_401_digest(request):
     raise Unauthorized("Unauthorized",
                        scheme="Digest",
                        realm="Sanic",
                        qop="auth, auth-int",
                        algorithm="MD5",
                        nonce="abcdef",
                        opaque="zyxwvu")
Exemplo n.º 23
0
  async def _actor(self, request, model):
    payload = model.verify(request.app.config["JWT_SECRET"])
    if payload:
      model = request.app.models.User(request.app.table, exclude = ("password",))
      await model.get(_id = ObjectId(payload["user_id"]))
      return model

    raise Unauthorized("No actor")
Exemplo n.º 24
0
 async def auth(self, request, model):
   user = await request.app.models.User.exists(self.table, model.email, True)
   if user and check_password_hash(user.password, model.password):
     token = AuthToken()
     token.generate({"user_id": str(user._id)}, request.app.config["JWT_SECRET"])
     return token.to_plain_dict()
   else:
     raise Unauthorized("Authentication has failed")
Exemplo n.º 25
0
async def delete_user(request, id, user):
    """ Deletes an existing user from the DB"""

    if user.id == int(id):
        with scoped_session() as session:
            session.query(User).filter(User.id == int(id)).delete()
            return sanic_json(Response('User successfully removed.').__dict__)
    raise Unauthorized('Unauthorized access.')
Exemplo n.º 26
0
 def handler_401_digest(request):
     challenge = {
         "qop": "auth, auth-int",
         "algorithm": "MD5",
         "nonce": "abcdef",
         "opaque": "zyxwvu",
     }
     raise Unauthorized("Unauthorized", "Digest", "Sanic", challenge)
Exemplo n.º 27
0
def decode_token(token: str, token_type: str = "access"):
    try:
        payload = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
        if payload['token_type'] != token_type:
            raise JWTError
        return payload
    except JWTError:
        raise Unauthorized("Unauthorized", status_code=401)
Exemplo n.º 28
0
async def get_user(request, id, user):
    """ Retrieves from the DB a particular user using his `id` """

    if user.id == int(id):
        with scoped_session() as session:
            user = session.query(User).filter(User.id == int(id)).first()
            return sanic_json(user.to_dict())
    else:
        raise Unauthorized('Unauthorized access.')
Exemplo n.º 29
0
async def verify_token(request):
    token = request.headers.get('Authorization')
    if request.path in available_endpoints:
        return True
    stored_token = await verify_token_in_redis(token)
    if stored_token and stored_token == token:
        return True
    else:
        raise Unauthorized('Unauthorized user')
Exemplo n.º 30
0
 async def post(self, request):
     user_id = await authorization._check_token_redis(
         request.headers['Authorization'])
     result = await access.checker(request.form.get('project_id'))
     if result[user_id][0] == 'DELETE':
         response = await access.sharing(request.form, result)
         return response
     else:
         raise Unauthorized('Permision denied')