Exemple #1
0
    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
Exemple #2
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')
Exemple #3
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)
Exemple #4
0
def email_confirmation_begin():
    if request.method == 'POST':
        if not current_user.email:
            abort(400)
        payload = {'id': current_user.id}
        serializer = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
        token = serializer.dumps(payload)
        html_body = render_template('email/email_confirmation.html',
                                    token=token)
        subject = _('Email confirmation at Brewlog')
        current_app.queue.enqueue(
            'brewlog.tasks.send_email',
            current_app.config['EMAIL_SENDER'],
            [current_user.email],
            subject,
            html_body,
        )
        flash(
            _(
                'confirmation email has been sent to %(email)s, please check your '
                'mailbox',
                email=current_user.email,
            ),
            category='success',
        )
        return redirect(url_for('.details', user_id=current_user.id))
    return render_template('account/email_confirm_begin.html')
Exemple #5
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']
Exemple #6
0
 def generate_token(self, playload):
     """
     :param playload: 负载,也就是你要序列化的数据,不要用关键数据(如密码等)做playload
     :return: token字符串
     """
     serializer = URLSafeTimedSerializer(self.secret_key, self.salt)
     return serializer.dumps(playload)
Exemple #7
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)
 def verify_auth_token(token, max_age=EXPIRATION_SECONDS):
     s = URLSafeTimedSerializer(SK).signer(SK)
     try:
         token = token.encode('utf-8')
         user_id = s.unsign(token, max_age=max_age)
         user_id = user_id.decode('utf-8')
     except SignatureExpired:
         return None  # valid token, but expired
     except BadSignature:
         return None  # invalid token
     return User(user_id)
Exemple #9
0
 def save(self):
     user = BrewerProfile.get_by_email(self.email1.data)
     if user is not None and user.email_confirmed:
         payload = {'id': user.id}
         serializer = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
         token = serializer.dumps(payload)
         html_body = render_template('email/password_reset.html', token=token)
         sender = current_app.config['EMAIL_SENDER']
         subject = str(_('Request to reset password at Brewlog'))
         current_app.queue.enqueue(
             'brewlog.tasks.send_email', sender, [user.email], subject, html_body,
         )
         return True
     return False
Exemple #10
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
Exemple #11
0
def generate_token(payload: str) -> str:
    """Generate token for authenticating and autorising client.

    The token is URL-safe and includes timestamp.

    :param payload: data to be serialised
    :type payload: str
    :return: token string
    :rtype: str
    """
    signer_kw = {'digest_method': hashlib.sha512}
    serializer = URLSafeTimedSerializer(
        current_app.secret_key, salt=current_app.config['TOKEN_SALT'],
        signer_kwargs=signer_kw,
    )
    return serializer.dumps(payload)
Exemple #12
0
    def __init__(self,
                 sent_from=gmail_user,
                 gmail_password=gmail_password,
                 to=[email_reviewer]):

        self.sent_from = sent_from
        self.gmail_password = gmail_password.encode('utf-8')
        self.gmail_password = base64.b64encode(self.gmail_password)

        self.timed_safe_serial = URLSafeTimedSerializer(
            'new_plan_confirmation')

        self.to = to
        self.subject = 'sca_project_test_email at: ' + str(
            datetime.datetime.now())
        self.email_text = ''
Exemple #13
0
def serializerCompressed(key):
    return URLSafeTimedSerializer(secret_key=key,
                                  salt='cookie-session',
                                  serializer=TaggedJSONSerializer(),
                                  signer_kwargs={
                                      'key_derivation': 'hmac',
                                      'digest_method': hashlib.sha1
                                  })
Exemple #14
0
 def get_serializer(self):
     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 None
     if not token_secret or not token_salt:
         None
     return URLSafeTimedSerializer(token_secret, token_salt)
Exemple #15
0
    def send_password_reset(self, http_context):
        """
        Sends upstream a request to check if a given email exists, in order to
        send a password reset link per email.

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

        mail = json.loads(http_context.body.decode())['mail']
        username = self.auth_provider.check_mail(mail)

        if username:
            with open(SECRET_FILE, 'r') as f:
                secret = f.read().strip('\n')
                serializer = URLSafeTimedSerializer(secret)
            serial = serializer.dumps({'user': username, 'email': mail})
            origin = http_context.env['HTTP_ORIGIN']
            link = f'{origin}/view/reset_password/{serial}'
            self.notifications.send_password_reset(mail, link)
Exemple #16
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
Exemple #17
0
    SIGNING_SECRET,
    OAUTH_BLIZZARD_CLIENT_ID,
    OAUTH_BLIZZARD_CLIENT_SECRET,
    OAUTH_DISCORD_CLIENT_ID,
    OAUTH_DISCORD_CLIENT_SECRET,
    OAUTH_REDIRECT_PATH,
    OAUTH_REDIRECT_HOST,
)
from .config_classes import GuildConfig
from .i18n import _, ngettext, CurrentLocale
from .models import User, GuildConfigJson, HighscoreCron
from .utils import run_sync

logger = logging.getLogger(__name__)

serializer = URLSafeTimedSerializer(SIGNING_SECRET)

TOKEN_MAX_AGE = 1800 if not DEVELOPMENT else 3600000

app = QuartTrio(__name__)

# HACK: these three are set by Orisa in orisa.py.
send_ch = None
client = None
orisa = None

app.debug = DEVELOPMENT


async def render_message(message, is_error=False):
    return await render_template(
Exemple #18
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)
Exemple #19
0
def serialize(data, secret=None):
    if secret is None:
        secret = current_app.config["SECRET_KEY"]
    s = URLSafeTimedSerializer(secret)
    return s.dumps(data)
Exemple #20
0
def serializerNormal(key):
    return URLSafeTimedSerializer(key)
Exemple #21
0
def serialize(data):
    secret = current_app.config['SECRET_KEY']
    s = URLSafeTimedSerializer(secret)
    return s.dumps(data)
Exemple #22
0
def unserialize(data, max_age=432000):
    secret = current_app.config['SECRET_KEY']
    s = URLSafeTimedSerializer(secret)
    return s.loads(data, max_age=max_age)
Exemple #23
0
from flask_security.decorators import login_required, roles_required
from flask_security.utils import login_user, logout_user, hash_password
from flask_security.core import current_user
from flask_login import login_user, logout_user

from flask_mail import Message

from itsdangerous.url_safe import URLSafeTimedSerializer
from itsdangerous.exc import BadSignature, SignatureExpired
from jinja2 import Markup
from datetime import datetime

confirm_time = 3  # hours
invalid_token_markup = Markup(f"""<h3>Время для подтверждения истекло</h3><br>
                                  Проведите повторную регистрацию для подтверждения""")
signer = URLSafeTimedSerializer(secret_key=app.config.get("SECRET_KEY"))

bp_auth = Blueprint('auth', __name__, url_prefix='/auth', template_folder="templates")


# !!!! Переделать - убрать тут и добавить в html
def collect_warnings(form_errors) -> list:
    """Collect all warning in form and return
        :returns list of strings"""
    warnings = []
    for errors in form_errors.values():
        warnings += errors
    return warnings


@bp_auth.route("/register", methods=["POST", "GET"])
Exemple #24
0
class Emails():
    def __init__(self,
                 sent_from=gmail_user,
                 gmail_password=gmail_password,
                 to=[email_reviewer]):

        self.sent_from = sent_from
        self.gmail_password = gmail_password.encode('utf-8')
        self.gmail_password = base64.b64encode(self.gmail_password)

        self.timed_safe_serial = URLSafeTimedSerializer(
            'new_plan_confirmation')

        self.to = to
        self.subject = 'sca_project_test_email at: ' + str(
            datetime.datetime.now())
        self.email_text = ''

    def email_body(
        self,
        new_plan,
        email_text=DEFAULT_EMAIL_BODY,
    ):
        form = NewPlanForm()

        body = 'sca_project_test_email at: ' + str(datetime.datetime.now())
        body += '\n This is a test email from Python Dev App.'
        body += '\n user request: ' + new_plan.username
        body += '\n plan name: ' + new_plan.plan_name
        body += '\n plan time frame: ' + str(new_plan.plan_timeframe)
        body += '\n plan link: ' + new_plan.plan_url

        # DEV Include a link.
        body += '\n\n Click this link to confirm new plan and add to the database: '
        body += '\n\n url safe timed serializer:' + self.timed_safe_serial.dumps(
            [1])

        email_text = """
        From: %s
        To: %s
        Subject: %s
        %s
        """ % (self.sent_from, ", ".join(self.to), self.subject, body)
        self.email_text = email_text

        # request.method == 'POST':

        # Protecting Proprietary or Sensitive Information.
        ## Some plan review has already happened.
        ## Endangered species locations.
        ## How to review proprietary and sensitive information....
        ## Maybe include a disclaimer in the message.

    # @app.route('/login', methods=['POST'])
    def email_send(self, new_plan):
        try:
            self.email_body(new_plan)

            smtp_server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
            smtp_server.ehlo()
            smtp_server.login(self.sent_from,
                              base64.b64decode(self.gmail_password).decode())
            smtp_server.sendmail(self.sent_from, self.to, self.email_text)

            smtp_server.close()
            print("Email sent successfully!")
            return True

        except Exception as ex:
            print("Something went wrong….", ex)
            return False
Exemple #25
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}
Exemple #26
0
 def generate_auth_token(self):
     s = URLSafeTimedSerializer(SK).signer(SK)
     token = s.sign(self.id)
     token = token.decode('utf-8')
     return token
Exemple #27
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)