def extract_jwt_token(self, token): """ Extracts a data dictionary from a jwt token """ # Note: we disable exp verification because we will do it ourselves with PraetorianError.handle_errors('failed to decode JWT token'): data = jwt.decode( token, self.encode_key, algorithms=self.allowed_algorithms, options={'verify_exp': False}, ) self.validate_jwt_data(data, access_type=AccessType.access) return data
def send_token_email(self, email, user=None, template=None, action_sender=None, action_uri=None, subject=None, override_access_lifespan=None, custom_token=None, sender='no-reply@praetorian'): """ Sends an email to a user, containing a time expiring token usable for several actions. This requires your application is initialized with a `mail` extension, which supports Flask-Mail's `Message()` object and a `send()` method. Returns a dict containing the information sent, along with the `result` from mail send. :param: email: The email address to use (username, id, email, etc) :param: user: The user object to tie claim to (username, id, email, etc) :param: template: HTML Template for confirmation email. If not provided, a stock entry is used :param: action_sender: The sender that should be attached to the confirmation email. :param: action_uri: The uri that should be visited to complete the token action. :param: subject: The email subject. :param: override_access_lifespan: Overrides the JWT_ACCESS_LIFESPAN to set an access lifespan for the registration token. """ notification = { 'result': None, 'message': None, 'user': str(user), 'email': email, 'token': custom_token, 'subject': subject, 'confirmation_uri': action_uri, # backwards compatibility 'action_uri': action_uri, } PraetorianError.require_condition( action_sender, "A sender is required to send confirmation email", ) PraetorianError.require_condition( custom_token, "A custom_token is required to send notification email", ) if template is None: with open(self.confirmation_template) as fh: template = fh.read() with PraetorianError.handle_errors('fail sending email'): flask.current_app.logger.debug( "NOTIFICATION: {}".format(notification)) jinja_tmpl = jinja2.Template(template) notification['message'] = jinja_tmpl.render(notification).strip() msg = Message(html=notification['message'], sender=action_sender, subject=notification['subject'], recipients=[notification['email']]) flask.current_app.logger.debug("Sending email to {}".format(email)) notification['result'] = flask.current_app.extensions['mail'].send( msg) return notification
def send_token_email( self, email, user=None, template=None, action_sender=None, action_uri=None, subject=None, override_access_lifespan=None, custom_token=None, ): """ Sends an email to a user, containing a time expiring token usable for several actions. This requires your application is initialized with a `mail` extension, which supports Flask-Mail's `Message()` object and a `send()` method. Returns a dict containing the information sent, along with the `result` from mail send. :param: email: The email address to use (username, id, email, etc) :param: user: The user object to tie claim to (username, id, email, etc) :param: template: HTML Template for confirmation email. If not provided, a stock entry is used :param: action_sender: The sender that should be attached to the confirmation email. :param: action_uri: The uri that should be visited to complete the token action. :param: subject: The email subject. :param: override_access_lifespan: Overrides the JWT_ACCESS_LIFESPAN to set an access lifespan for the registration token. :param: custom_token: The token to be carried as the email's payload """ notification = { "result": None, "message": None, "user": str(user), "email": email, "token": custom_token, "subject": subject, "confirmation_uri": action_uri, # backwards compatibility "action_uri": action_uri, } PraetorianError.require_condition( "mail" in flask.current_app.extensions, "Your app must have a mail extension enabled to register by email", ) PraetorianError.require_condition( action_sender, "A sender is required to send confirmation email", ) PraetorianError.require_condition( custom_token, "A custom_token is required to send notification email", ) if template is None: with open(self.confirmation_template) as fh: template = fh.read() with PraetorianError.handle_errors("fail sending email"): jinja_tmpl = jinja2.Template(template) notification["message"] = jinja_tmpl.render(notification).strip() msg = Message( html=notification["message"], sender=action_sender, subject=notification["subject"], recipients=[notification["email"]], ) flask.current_app.logger.debug("Sending email to {}".format(email)) notification["result"] = flask.current_app.extensions["mail"].send( msg ) return notification
def send_registration_email(self, email, user=None, template=None, confirmation_sender=None, confirmation_uri=None, subject=None, override_access_lifespan=None): """ Sends a registration email to a new user, containing a time expiring token usable for validation. This requires your application is initiliazed with a `mail` extension, which supports Flask-Mail's `Message()` object and a `send()` method. Returns a dict containing the information sent, along with the `result` from mail send. :param: user: The user object to tie claim to (username, id, email, etc) :param: template: HTML Template for confirmation email. If not provided, a stock entry is used :param: confirmation_sender: The sender that shoudl be attached to the confirmation email. Overrides the PRAETORIAN_CONFIRMRATION_SENDER config setting :param: confirmation_uri: The uri that should be visited to complete email registration. Should usually be a uri to a frontend or external service that calls a 'finalize' method in the api to complete registration. Will override the PRAETORIAN_CONFIRMATION_URI config setting :param: subject: The registration email subject. Will override the PRAETORIAN_CONFIRMATION_SUBJECT config setting. :param: override_access_lifespan: Overrides the JWT_ACCESS_LIFESPAN to set an access lifespan for the registration token. """ if subject is None: subject = self.confirmation_subject if confirmation_uri is None: confirmation_uri = self.confirmation_uri notification = { 'result': None, 'message': None, 'user': str(user), 'email': email, 'token': None, 'subject': subject, 'confirmation_uri': confirmation_uri, } sender = confirmation_sender or self.confirmation_sender PraetorianError.require_condition( sender, "A confirmation sender is required to send confirmation email", ) if template is None: with open(self.confirmation_template) as fh: template = fh.read() with PraetorianError.handle_errors('fail sending confirmation email'): app = flask.current_app app.logger.debug("NOTIFICATION: {}".format(notification)) app.logger.debug( "Generating registration token with lifespan: {}".format( override_access_lifespan)) notification['token'] = self.encode_jwt_token( user, override_access_lifespan=override_access_lifespan, bypass_user_check=True, is_registration_token=True, ) jinja_tmpl = jinja2.Template(template) notification['message'] = jinja_tmpl.render(notification).strip() msg = Message(html=notification['message'], sender=sender, subject=notification['subject'], recipients=[notification['email']]) app.logger.debug("Sending verification email to {}".format(email)) notification['result'] = app.extensions['mail'].send(msg) return notification