Пример #1
0
    async def authenticate(
            self, conn: HTTPConnection) -> Tuple[bool, Optional[User]]:
        """
        Main function that AuthenticationMiddleware uses from this backend.
        Should return whether request is authenticated based on credentials and
        if it was, return also user instance.

        :param conn: HTTPConnection of the current request-response cycle
        :return: 2-tuple: is authenticated & user instance if exists
        """
        authorization: str = conn.headers.get("Authorization")
        if not authorization:
            return False, None
        scheme, credentials = get_authorization_scheme_param(authorization)
        if not (authorization and scheme and credentials):
            raise AuthenticationError("Not authenticated")
        if scheme.lower() != "token":
            raise AuthenticationError("Invalid authentication credentials")

        token = await Token.get(
            key=credentials,
            is_active=True,
            expires={"$not": {
                "$lt": get_now()
            }},
        )
        if token is None:
            return False, None
        conn.scope["token"] = token

        user = await User.get(id=token.user_id)
        if user is None:
            return False, None

        return True, user
Пример #2
0
    async def authenticate(self, request):
        if "Authorization" not in request.headers:
            return

        self.users_repository.with_session(request.state.session)

        auth = request.headers["Authorization"]
        try:
            scheme, token = auth.split()
            if scheme.lower() != "bearer":
                return

            jwt_token = decode_token(token)
        except (
                ValueError,
                UnicodeDecodeError,
                jwt.ExpiredSignatureError,
                jwt.DecodeError,
                jwt.InvalidAudienceError,
        ):
            raise AuthenticationError("Invalid auth credentials")

        user = await self.users_repository.get_by_id(jwt_token.id)

        if not user or not user.is_active:
            raise AuthenticationError("Invalid auth credentials")

        user._authenticated_user = True
        return user.credentials, user
Пример #3
0
    async def authenticate(
            self, request: HTTPConnection
    ) -> Optional[Tuple[AuthCredentials, BaseUser]]:
        """Authenticate the user."""
        if "Authorization" not in request.headers:
            return

        authorization_header = request.headers["Authorization"]
        if not authorization_header.startswith("Bearer "):
            logger.info(msg=f"Invalid Authorization header sent by user")
            raise AuthenticationError(
                "Invalid Authorization header value. The header "
                "value must have the format Bearer <token>.")

        user_token = request.headers["Authorization"][
            7:]  # length of "Bearer " is 7
        try:
            payload = parse_token(user_token)
        except Exception:
            logger.exception(msg=f"Invalid or expired authentication token.")
            raise AuthenticationError(
                "Invalid or expired authentication token.")

        user = await user_repository.find_user_by_id(int(payload.user_id))

        if not user:
            logger.error(msg=f"No user found for id {payload.user_id}.")
            raise AuthenticationError("No user found for user id.")

        return AuthCredentials(["authenticated"]), AuthenticatedUser(user)
Пример #4
0
    async def authenticate(self, request):
        """
        Hàm dùng cho việc xác thực Http Request từ client

        :param request: HTTP request từ client
        :return: authenticated và JWTUser
        """

        if 'Authorization' not in request.headers:
            return None

        auth = request.headers['Authorization']
        token = self.get_token_from_header(authorization=auth,
                                           prefix=self.prefix)

        try:
            payload = self.decode_token(token)
        except jwt.InvalidTokenError:
            raise AuthenticationError('error: Token không hợp lệ!')
        else:
            # Kiểm tra xem Token có nằm trong danh sách blacklist Token hay không
            # ** blacklist Token là file chứa danh sách các token đã logout hoặc đã bị vô hiệu hóa
            with open('security.txt', 'r') as reader:
                modify_token_for_check = token + '\n'
                if modify_token_for_check in reader.readlines():
                    raise AuthenticationError(
                        'error: Token đã bị vô hiệu hoá!')
                else:
                    return AuthCredentials(
                        ['authenticated']), JWTUser(user_id=payload['userId'])
Пример #5
0
 async def authenticate(
         self, request: HTTPConnection
 ) -> tuple[AuthCredentials, SimpleUser] | None:
     """Authenticate a Starlette request with HTTP Basic auth."""
     if "Authorization" not in request.headers:
         return None
     try:
         auth = request.headers["Authorization"]
         basic_auth_username = os.getenv("BASIC_AUTH_USERNAME")
         basic_auth_password = os.getenv("BASIC_AUTH_PASSWORD")
         if not (basic_auth_username and basic_auth_password):
             raise AuthenticationError(
                 "Server HTTP Basic auth credentials not set")
         scheme, credentials = auth.split()
         decoded = base64.b64decode(credentials).decode("ascii")
         username, _, password = decoded.partition(":")
         correct_username = secrets.compare_digest(username,
                                                   basic_auth_username)
         correct_password = secrets.compare_digest(password,
                                                   basic_auth_password)
         if not (correct_username and correct_password):
             raise AuthenticationError(
                 "HTTP Basic auth credentials not correct")
         return AuthCredentials(["authenticated"]), SimpleUser(username)
     except Exception:
         raise
Пример #6
0
    async def authenticate(self, request):
        if 'Authorization' not in request.headers:
            return

        auth = request.headers['Authorization']
        try:
            scheme, credentials = auth.split()
            if scheme.lower() != 'basic':
                return
            decoded = base64.b64decode(credentials).decode("ascii")
        except (ValueError, UnicodeDecodeError, binascii.Error):
            raise AuthenticationError('Invalid basic auth credentials')

        pseudo, _, password = decoded.partition(':')
        db = get_session(DATABASE_URL)
        user = db.query(User).filter(User.pseudo == pseudo).one_or_none()
        if user is None or not user.check_password(password):
            db.close()
            raise AuthenticationError(f'pseudo or password incorrect')

        user.is_authenticated = True
        scopes = ['authenticated']
        for group in user.groups:
            scopes.extend([permission.name for permission in group.permissions])
        db.close()
        return AuthCredentials(scopes), user
Пример #7
0
    async def authenticate(self, request):

        if "Authorization" not in request.headers:
            return None

        authorization = request.headers["Authorization"]
        token = self.get_token_from_header(authorization=authorization,
                                           prefix=self.prefix)

        try:
            jwt_payload = jwt.decode(token,
                                     key=str(self.secret_key),
                                     algorithms=self.algorithm)
        except jwt.InvalidTokenError:
            if DEBUG:
                sprint_f(f"Invalid JWT token", "red")
            raise AuthenticationError("Invalid JWT token")
        except jwt.ExpiredSignatureError:
            if DEBUG:
                sprint_f(f"Expired JWT token", "red")
            raise AuthenticationError("Expired JWT token")

        if DEBUG:
            sprint_f(f"Decoded JWT payload: {jwt_payload}",
                     "green")  # debug part, do not forget to remove it

        return (
            AuthCredentials(["authenticated"]),
            JWTUser(username=jwt_payload["username"],
                    user_id=jwt_payload["user_id"],
                    email=jwt_payload["email"],
                    token=token),
        )
Пример #8
0
    async def authenticate(self, request):
        if request.url.path != "/pretix-webhook":
            raise ValueError("PretixAuthBackend used outside pretix-webhook")

        if "Authorization" not in request.headers:
            return

        auth = request.headers["Authorization"]
        try:
            scheme, credentials = auth.split()
            if scheme.lower() != "basic":
                return
            decoded = base64.b64decode(credentials).decode("ascii")
        except (ValueError, UnicodeDecodeError, binascii.Error) as exc:
            raise AuthenticationError(
                "Invalid basic auth credentials") from exc

        username, _, password = decoded.partition(":")
        if username != "pretix":
            raise AuthenticationError("Invalid auth")

        if password != str(PRETIX_WEBHOOK_SECRET):
            raise AuthenticationError("Invalid auth")

        return AuthCredentials(["authenticated",
                                "pretix"]), SimpleUser("pretix")
Пример #9
0
    async def authenticate(self, conn: HTTPConnection):
        if "Authorization" not in conn.headers:
            return AuthCredentials(), None

        auth_header = conn.headers["Authorization"]
        try:
            scheme, token = auth_header.split()
            if scheme.lower() != "bearer":
                return AuthCredentials(), None
        except Exception as error:
            raise AuthenticationError(
                "Invalid authentication credentials") from error

        try:
            payload: JWTPayloadSchema = TokensHandler.read_code(
                code=token, convert_to=JWTPayloadSchema)
            user_model: UserModel = await UsersHandler(
                request=conn).retrieve_user(request=conn,
                                            query={
                                                "_id": payload.object_id,
                                                "is_active": True
                                            })
        except HandlerException as error:
            raise AuthenticationError(str(error)) from error

        # request.auth, request.user
        return AuthCredentials(), user_model
Пример #10
0
    async def authenticate(
        self, request: Request
    ) -> Optional[Tuple["AuthCredentials", "BaseUser"]]:
        token = self._get_token(request.headers)
        if not token:
            return  # Consider that user is not authenticated

        try:
            json_header, json_body = validate(
                token, self.identity_provider_url, **self.validation_options
            )
        except (
            jwt.exceptions.InvalidTokenError or jwt.exceptions.InvalidKeyError
        ) as e:
            raise AuthenticationError(str(e)) from e

        try:
            username = get(json_body, self.username_field)
        except jwt.exceptions.InvalidTokenError as e:
            raise AuthenticationError(str(e)) from e

        return (
            AuthCredentials(scopes=self.scopes_retrieval(json_body)),
            SimpleUser(username=username),
        )
Пример #11
0
 def get_token_from_header(cls, authorization: str, prefix: str):
     """Get token from header."""
     try:
         scheme, token = authorization.split()
     except ValueError:
         raise AuthenticationError(
             'Could not separate Authorization scheme and token')
     if scheme.lower() != prefix.lower():
         raise AuthenticationError(
             f'Authorization scheme {scheme} is not supported')
     return token
Пример #12
0
    async def authenticate(self, request):
        path = request.url.path
        if not path.startswith('/api'):
            return
        if path == '/api/login':
            return
        if request.scope.get('method') == 'OPTIONS':
            return

        data = None
        if request.url.scheme != 'ws':
            auth = request.headers.get('X-Auth-Pacs')
            if not auth:
                auth = request.query_params.get('token')
                if not auth:
                    raise AuthenticationError('Invalid auth')

            credentials = auth
            try:
                data = jwt.decode(credentials,
                                  config['secret'],
                                  algorithms=['HS256'])
                async with get_conn() as conn:
                    active = await Users(conn).is_active(data['id'])
                if not active:
                    raise AuthenticationError('Deactivated user')

            except Exception as e:
                # try share file key
                async with get_conn() as conn:
                    file_id = await SharedFiles(conn).check(credentials)

                if file_id and (path.startswith(f'/api/files/{file_id}')
                                or path.startswith(f'/api/ws_token')):
                    data = {'id': credentials, 'admin': False}
                else:
                    raise AuthenticationError('Invalid auth')
        else:
            token = request.query_params.get('token')
            try:
                data = jwt.decode(token,
                                  config['secret'],
                                  algorithms=['HS256'])
            except Exception as e:
                raise AuthenticationError('Invalid auth')

            data = {'id': data['id'], 'admin': data['admin']}

        if not data:
            raise AuthenticationError('Invalid auth')

        return AuthCredentials(["authenticated"]), User(data)
Пример #13
0
    async def get_user(self, token: str) -> User:
        user_id = await self.token_table.get_user_id(token)

        if not user_id:
            raise AuthenticationError()

        user = (await self.auth_table.select(
            self.auth_table.username
        ).where(self.auth_table._meta.primary_key == user_id).first().run())

        if not user:
            raise AuthenticationError()

        user = User(user=user)
        return user
Пример #14
0
    def __init__(self):
        """Virtually private constructor."""
        if JWTWrapper.__instance is not None:
            raise AuthenticationError(
                'Attempt made to create multiple JWTWrappers')

        JWTWrapper.__instance = JWTAuthenticationBackend()
Пример #15
0
    async def __call__(self, request: Request) -> Optional[str]:
        for url, op in settings.NO_VERIFY_URL.items():
            if op == 'eq' and url == request.url.path.lower():
                return None
            elif op == 'in' and url in request.url.path.lower():
                return None

        authorization: str = request.headers.get("Authorization")
        scheme, param = get_authorization_scheme_param(authorization)
        if not authorization or scheme.lower() != "bearer":
            if self.auto_error:
                raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
                                    detail="Not authenticated")
            else:
                return None

        try:
            playload = jwt.decode(param,
                                  settings.SECRET_KEY,
                                  algorithms=[settings.ALGORITHM])
        except jwt.ExpiredSignatureError:
            raise custom_exc.TokenExpired()
        except (jwt.JWTError, ValidationError, AttributeError):
            raise custom_exc.TokenAuthError()

        username = playload.get('username')
        user = await get_user_by_name(username=username)
        if not user:
            raise AuthenticationError("认证失败")
        """在 Request 对象中设置用户对象,这样在其他地方就能通过 request.state.user 获取到当前用户了"""
        request.state.user = user
Пример #16
0
    async def authenticate(self, request):
        if "Authorization" not in request.headers:
            raise AuthenticationError('You have to authenticate.')

        auth = request.headers["Authorization"]
        try:
            scheme, credentials = auth.split()
            if scheme.lower() != 'basic':
                return
            decoded = base64.b64decode(credentials).decode("ascii")
        except (ValueError, UnicodeDecodeError, binascii.Error):
            raise AuthenticationError('Invalid basic auth credentials')

        username, _, password = decoded.partition(":")
        if username == config('username') and password == config('password'):
            return AuthCredentials(["authenticated"]), SimpleUser(username)
Пример #17
0
    def extract_token(self, header: str) -> str:
        try:
            token = header.split("Bearer ")[1]
        except IndexError:
            raise AuthenticationError("The header is in the wrong format.")

        return token
Пример #18
0
def get_user_from_header(
        auth_header: str
) -> Optional[Tuple[AuthCredentials, AuthenticatedUser]]:
    try:
        scheme, token = auth_header.split()
        if scheme.lower() == 'bearer':
            payload = decode_token(token)
            return AuthCredentials(
                payload['scopes']), AuthenticatedUser(**payload)
        return
    except ExpiredSignatureError:
        raise AuthenticationError('Token expired')
    except JWTError:
        raise AuthenticationError("Auth failed")
    except (ValueError, UnicodeDecodeError, KeyError, ValidationError,
            AttributeError):
        return
Пример #19
0
    def get_token_from_header(cls, authorization: str, prefix: str):
        """
        Parses the Authorization header and returns only the token
        :param authorization:
        :return:
        """
        if len(authorization.split()) != 2:
            return None
        try:
            scheme, token = authorization.split()
        except ValueError:
            raise AuthenticationError(
                'Could not separate Authorization scheme and token')
        if scheme.lower() != prefix.lower():
            raise AuthenticationError(
                f'Authorization scheme {scheme} is not supported')

        return token
Пример #20
0
    def verify_token(self, token):
        try:
            payload = jwt.decode(token,
                                 settings.SECRET_KEY,
                                 algorithms=[security.ALGORITHM])
            token_data = self.token_payload(**payload).dict(exclude_unset=True)
        except jose.ExpiredSignatureError:
            raise AuthenticationError({'detail': 'Signature has expired.'},
                                      401)
        except (jose.JWTError, ValidationError):
            raise AuthenticationError(
                {'detail': 'Invalid bearer auth credentials.'}, 400)

        scopes = token_data.get(self.user_group_flag)
        if self.user_group_flag not in token_data:
            msg = f"AuthenticationMiddleware lacks a required property '{self.user_group_flag}' in jwt"
            warnings.warn(msg)
        return AuthCredentials(scopes), AuthUser(
            str(token_data.get(self.user_id_flag)))
Пример #21
0
async def authenticate(email: str, password: str) -> User:
    error = AuthenticationError("Invalid email or password.")
    user = await _get_user_by_email(email)
    if not user:
        raise error

    if not _verify_password(user.hashed_password, password):
        raise error

    return user
Пример #22
0
    def get_token_from_header(authorization: str, prefix: str):
        """
        Hàm dùng cho việc lấy ra Token từ một
        chuỗi Authorization có trong request headers

        :param authorization: chuỗi Authorization có trong request headers
        :param prefix: tiếp đầu ngữ của chuỗi Authorization, mặc định là "lioToken"
        :return: chuỗi Token
        """

        try:
            scheme, token = authorization.split()
        except ValueError:
            raise AuthenticationError(
                'Could not separate Authorization scheme and token')
        if scheme != prefix:
            raise AuthenticationError(
                f'Authorization scheme {scheme} is not supported')
        return token
Пример #23
0
    def get_token_from_header(cls, authorization: str, prefix: str) -> str:
        """
        Parses the Authorization header and returns only the token

        :param authorization str: Value of the authorization header
        :param prefix str: Token prefix in the header
        :return: The token value
        :rtype str:
        :raises AuthenticationError: If prefix in header doesn't match `prefix` or
        if header value doesn't follow the `<prefix> <token>` pattern
        """
        try:
            scheme, token = authorization.split()
        except ValueError:
            raise AuthenticationError("incorrect authorization header format")
        if scheme.lower() != prefix.lower():
            raise AuthenticationError(
                f"authorization scheme {scheme} is not supported")
        return token
Пример #24
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')
Пример #25
0
    def get_token_from_header(cls, authorization: str, prefix: str):

        if DEBUG:
            sprint_f(f"JWT token from headers: {authorization}",
                     "cyan")  # debug part, do not forget to remove it
        try:
            scheme, token = authorization.split()
        except ValueError:
            if DEBUG:
                sprint_f(f"Could not separate Authorization scheme and token",
                         "red")
            raise AuthenticationError(
                "Could not separate Authorization scheme and token")
        if scheme.lower() != prefix.lower():
            if DEBUG:
                sprint_f(f"Authorization scheme {scheme} is not supported",
                         "red")
            raise AuthenticationError(
                f"Authorization scheme {scheme} is not supported")
        return token
Пример #26
0
    def get_identity(self, request: Request, type="access"):
        name = f"{type}_token_cookie"
        try:
            cookie = request.cookies.get(name)
            if cookie is None:
                if "Authorization" not in request.headers:
                    raise AuthenticationError(f"Could not find {name} on request")
                else:
                    value = self._decode(request.headers["Authorization"])
            else:
                value = self._decode(cookie)

            identity = value.get("identity")
            if identity is None:
                raise AuthenticationError(f"{name} has no key identity")
            if type != value.get("type"):
                raise AuthenticationError(f"{name} did not have a matching type")
            return identity
        except jwt.PyJWTError as e:
            raise AuthenticationError(*e.args) from None
Пример #27
0
    async def authenticate(self, conn: HTTPConnection):
        session_token = conn.cookies.get(settings.SESSION_COOKIE_NAME)
        if not session_token:
            return

        token = await Token.get_or_none(value=session_token)
        if token:
            await token.user.fetch()
            return AuthCredentials(), token.user
        elif conn.url.path == '/auth/login':
            return
        raise AuthenticationError('invalid token')
Пример #28
0
    async def authenticate(
        self, request: Request
    ) -> typing.Optional[typing.Tuple["AuthCredentials", "BaseUser"]]:
        header_token = AppAuthenticationBackend.get_token_from_headers(request)
        cookie_token = AppAuthenticationBackend.get_token_from_cookies(request)

        if header_token is None and cookie_token is None:
            return

        token = header_token if header_token is not None else cookie_token

        try:
            user_id = self.auth_service.get_user_id_from_token(token)

            user = await self.users_service.get_by_id(user_id)

            return AuthCredentials(["user"]), user
        except (jwt.ExpiredSignatureError, jwt.DecodeError):
            raise AuthenticationError("Invalid authorization token")
        except (KeyError, EntityDoesNotExistError):
            raise AuthenticationError("Bad credentials")
Пример #29
0
        async def authenticate(self, request: HTTPConnection):
            if "Authorization" not in request.headers:
                return

            auth = request.headers["Authorization"]
            bearer_token = auth.replace("Bearer", "").strip()
            try:
                verified_user = await verified_user_callback(bearer_token)
            except (jwt.exceptions.DecodeError, ValueError, KeyError) as e:
                raise AuthenticationError("Invalid token")
            else:
                return AuthCredentials(verified_user.auth_roles), verified_user
Пример #30
0
 async def authenticate(self, request):
     if "Authorization" not in request.headers:
         return
     auth = request.headers["Authorization"]
     try:
         scheme, username = auth.split()
         if scheme.lower() != 'custom':
             return
     except Exception as exc:
         logger.debug(f'get exception: {exc}')
         raise AuthenticationError("Bad auth header")
     return AuthCredentials(["authenticated"]), SimpleUser(username)