Beispiel #1
0
 def decorated_view(*args, **kw):
     auth = request.headers.get('Authorization')
     if not auth:
         return json_error_response(401, 'Authorization required')
     try:
         auth_type, auth_token = auth.split()
     except ValueError:
         return json_error_response(401, 'Invalid authentication header')
     if auth_type.lower() != 'basic':
         return json_error_response(401, 'Invalid authentication type')
     signer_kw = {'digest_method': hashlib.sha512}
     serializer = URLSafeTimedSerializer(
         current_app.secret_key, salt=current_app.config['TOKEN_SALT'],
         signer_kwargs=signer_kw,
     )
     try:
         name = serializer.loads(auth_token, current_app.config['TOKEN_MAX_AGE'])
         user = get_user(name)
         if not user:
             return json_error_response(401, 'Invalid token')
         g.user = user
         return func(*args, **kw)
     except SignatureExpired:
         return json_error_response(400, 'Token expired')
     except BadSignature:
         return json_error_response(401, 'Invalid token')
Beispiel #2
0
def check_token(token: str, secret: str, max_age: int) -> TokenCheckResult:
    """Check token validity, returns validation result with payload if token
    is valid.

    :param token: token to check
    :type token: str
    :param secret: secret that was used to generate token
    :type secret: str
    :param max_age: max age of token
    :type max_age: int
    :return: validation result
    :rtype: TokenCheckResult
    """
    serializer = URLSafeTimedSerializer(secret)
    payload = None
    is_error = True
    msg = None
    try:
        payload = serializer.loads(token, max_age=max_age)
        is_error = False
    except SignatureExpired as e:
        msg = _(
            "token expired, it's valid for 48 hrs and it was generated on %(date)s",
            date=e.date_signed,
        )
    except BadSignature:
        msg = _('invalid token')
    return TokenCheckResult(is_error, message=msg, payload=payload)
Beispiel #3
0
    def update_password(self, http_context):
        """
        Update user's password in the auth provider.

        :param http_context: HttpContext
        :type http_context: HttpContext
        """

        serial = json.loads(http_context.body.decode())['serial']
        password = json.loads(http_context.body.decode())['password']

        if serial and password:
            with open(SECRET_FILE, 'r') as f:
                secret = f.read().strip('\n')
                serializer = URLSafeTimedSerializer(secret)
            user = serializer.loads(serial, max_age=900)['user']
            auth_provider = AuthenticationService.get(
                self.context).get_provider()
            answer = auth_provider.update_password(user, password)
            if not answer:
                http_context.respond_forbidden()
                return [b'403 Forbidden']
            else:
                http_context.respond_ok()
                return [b'200 OK']
Beispiel #4
0
    def load_token(token):
        duration = app.config['REMEMBER_COOKIE_DURATION'].total_seconds()
        serializer = URLSafeTimedSerializer(app.secret_key)

        data = serializer.loads(token, max_age=duration)
        user_uid = data[0]

        return user_model.query.get(user_uid)
Beispiel #5
0
 def confirm_token(self, token, expired=86400):
     """
     验证token
     :param token: generate_validate_token产生的字符串
     :param expired: 过期时间,以秒为单位
     :return: 成功返回负载数据,失败返回错误码
     """
     serializer = URLSafeTimedSerializer(self.secret_key, self.salt)
     try:
         data = serializer.loads(token, max_age=expired)
     except BadData as e:
         return TokenException(e)
     # 签名验证通过,返回原始数据
     return data
Beispiel #6
0
    def check_serial(self, http_context):
        """
        Check if the serial in a given reset link is valid

        :param http_context: HttpContext
        :type http_context: HttpContext
        """

        serial = json.loads(http_context.body.decode())['serial']

        if serial:
            try:
                with open(SECRET_FILE, 'r') as f:
                    secret = f.read().strip('\n')
                    serializer = URLSafeTimedSerializer(secret)
                    # Serial can not be used after 15 min
                serializer.loads(serial, max_age=900)
                http_context.respond_ok()
                return [b'200 OK']
            except (SignatureExpired, BadTimeSignature, BadSignature) as err:
                logging.warning('Password reset link not valid or expired')
                http_context.respond_not_found()
                return [b'Link not valid']
        return False
Beispiel #7
0
def unserialize(data, secret=None, max_age=432000):
    if secret is None:
        secret = current_app.config["SECRET_KEY"]
    s = URLSafeTimedSerializer(secret)
    return s.loads(data, max_age=max_age)
Beispiel #8
0
def unserialize(data, max_age=432000):
    secret = current_app.config['SECRET_KEY']
    s = URLSafeTimedSerializer(secret)
    return s.loads(data, max_age=max_age)
Beispiel #9
0
class SessionCookie(SecurityBase):
    def __init__(
        self,
        *,
        name: str,
        secret_key: str,
        backend: Type[SessionBackend],
        data_model: Type[BaseModel],
        scheme_name: Optional[str] = None,
        auto_error: bool = True,
        max_age: int = 14 * 24 * 60 * 60,  # 14 days in seconds
        expires: datetime = None,
        path: str = "/",
        domain: str = None,
        secure: bool = False,
        httponly: bool = True,
        samesite: str = "lax",
    ):
        self.model: APIKey = APIKey(**{"in": APIKeyIn.cookie}, name=name)
        self.scheme_name = scheme_name or self.__class__.__name__
        self.auto_error = auto_error

        self.signer = URLSafeTimedSerializer(secret_key, salt=name)
        self.backend = backend
        self.data_model = data_model

        self.max_age = max_age
        self.expires = expires
        self.path = path
        self.domain = domain
        self.secure = secure
        self.httponly = httponly
        self.samesite = samesite

    async def __call__(self, request: Request) -> Optional[SessionInfo]:
        # Get the signed session id from the session cookie
        signed_session_id = request.cookies.get(self.model.name)
        if not signed_session_id:
            return self.authentication_error()

        # Verify and timestamp the signed session id
        try:
            session_id = self.signer.loads(
                signed_session_id,
                max_age=self.max_age,
                return_timestamp=False,
            )
        except (SignatureExpired, BadTimeSignature):
            return self.authentication_error()

        # Attempt to read the corresponding session data from the backend
        session_data = await self.backend.read(session_id)
        if not session_data:
            return self.authentication_error()
        session_data = SessionDataWrapper[self.data_model](
            session_id=session_id,
            **session_data,
        )

        # Retrieve the csrf token, if it doesn't exist then its a potential
        # csrf attack and remove the session
        frontend_signed_csrf_token = request.cookies.get(self.model.name +
                                                         "csrf")
        if not frontend_signed_csrf_token:
            await self.backend.remove(session_id)
            return self.authentication_error()

        # Validate the csrf token, if not valid then its a potential csrf
        # attack and delete the session
        try:
            frontend_csrf_token = self.signer.loads(
                frontend_signed_csrf_token,
                max_age=self.max_age,
                return_timestamp=False,
            )
            assert frontend_csrf_token == session_data.csrf_token
        except (SignatureExpired, BadTimeSignature, AssertionError):
            await self.backend.remove(session_id)
            return self.authentication_error()

        return session_data.session_id, session_data.data

    def authentication_error(self):
        if self.auto_error:
            raise HTTPException(status_code=403, detail="Not authenticated")
        else:
            return None

    async def create_session(self,
                             data: Type[BaseModel],
                             response: Response,
                             prev_session_info: Optional[str] = None):
        session_data = SessionDataWrapper[self.data_model](data=data)
        if prev_session_info:
            await self.backend.remove(prev_session_info)

        await self.backend.write(session_data)

        response.set_cookie(
            key=self.model.name,
            value=self.signer.dumps(session_data.session_id),
            max_age=self.max_age,
            expires=self.expires,
            path=self.path,
            domain=self.domain,
            secure=self.secure,
            httponly=self.httponly,
            samesite=self.samesite,
        )

        # Temporary csrf cookie setting
        response.set_cookie(key=self.model.name + "csrf",
                            value=self.signer.dumps(session_data.csrf_token))

    async def end_session(self, session_id: str, response: Response):
        response.delete_cookie(self.model.name)
        await self.backend.remove(session_id)
Beispiel #10
0
def decode_token():
    request = getRequest()
    secret = request.form.get("secret", "")
    if not secret:
        return {
            "error":
            _(
                "unsubscribe_confirm_secret_null",
                default=
                u"Unable to manage subscriptions. Token not present.",  # noqa
            )
        }
    try:
        token_secret = api.portal.get_registry_record(
            "token_secret", interface=IRerUfficiostampaSettings)
        token_salt = api.portal.get_registry_record(
            "token_salt", interface=IRerUfficiostampaSettings)
    except (KeyError, InvalidParameterError):
        return {
            "error":
            _(
                "unsubscribe_confirm_secret_token_settings_error",
                default=
                u"Unable to manage subscriptions. Token keys not set in control panel.",  # noqa
            )
        }
    if not token_secret or not token_salt:
        return {
            "error":
            _(
                "unsubscribe_confirm_secret_token_settings_error",
                default=
                u"Unable to manage subscriptions. Token keys not set in control panel.",  # noqa
            )
        }
    serializer = URLSafeTimedSerializer(token_secret, token_salt)
    try:
        data = serializer.loads(secret, max_age=86400)
    except SignatureExpired:
        return {
            "error":
            _(
                "unsubscribe_confirm_secret_expired",
                default=u"Unable to manage subscriptions. Token expired.",
            )
        }
    except BadSignature:
        return {
            "error":
            _(
                "unsubscribe_confirm_secret_invalid",
                default=u"Unable to manage subscriptions. Invalid token.",
            )
        }
    record_id = data.get("id", "")
    email = data.get("email", "")
    if not record_id or not email:
        return {
            "error":
            _(
                "unsubscribe_confirm_invalid_parameters",
                default=u"Unable to manage subscriptions. Invalid parameters.",
            )
        }
    tool = getUtility(ISubscriptionsStore)
    record = tool.get_record(record_id)
    if not record:
        return {
            "error":
            _(
                "unsubscribe_confirm_invalid_id",
                default=u"Unable to manage subscriptions. Invalid id.",
            )
        }
    if record.attrs.get("email", "") != email:
        return {
            "error":
            _(
                "unsubscribe_confirm_invalid_email",
                default=u"Unable to manage subscriptions. Invalid email.",
            )
        }
    return {"data": record}