def reset_password(userid, user_email): s = TimestampSigner(app.secret_key) userid = s.sign(userid) token = s.sign(user_email) body = ( "Hey, a password reset for this account was requested. If you wish to continue, then please follow the link below:\n" + app.hvb_conf["domain"] + "/reset/" + userid + "/token/" + token ) subject = "[HumanVoiceBankInitiative] Password Reset for " + user_email send_mail(subject, body, app.hvb_conf["admin_email"], user_email)
def channelstream_request(secret, endpoint, payload, throw_exceptions=False, servers=None): responses = [] if not servers: servers = [] signer = TimestampSigner(secret) sig_for_server = signer.sign(endpoint) for secret, server in [(s["secret"], s["server"]) for s in servers]: response = {} secret_headers = { "x-channelstream-secret": sig_for_server, "x-channelstream-endpoint": endpoint, "Content-Type": "application/json", } url = "%s%s" % (server, endpoint) try: response = requests.post( url, data=json.dumps(payload, cls=DateTimeEncoder), headers=secret_headers, verify=False, timeout=2, ).json() except requests.exceptions.RequestException as e: if throw_exceptions: raise responses.append(response) return responses
def make_server_request(request, payload, endpoint, auth=None, method="post"): """ makes a json request to channelstream server endpoint signing the request and sending the payload :param request: :param payload: :param endpoint: :param auth: :return: """ server_port = request.registry.settings["port"] signer = TimestampSigner(request.registry.settings["secret"]) sig_for_server = signer.sign("channelstream") if not six.PY2: sig_for_server = sig_for_server.decode("utf8") secret_headers = { "x-channelstream-secret": sig_for_server, "Content-Type": "application/json", } url = "http://127.0.0.1:%s%s" % (server_port, endpoint) response = getattr(requests, method)( url, data=json.dumps(payload), headers=secret_headers, auth=auth ) if response.status_code >= 400: log.error(response.text) response.raise_for_status() return response
def generate_session_token(self): timer = TimestampSigner(app.config["SECRET_KEY"]) token = Serializer(app.config["SECRET_KEY"]) return timer.sign( token.dumps({ 'userId': int(self.id) }).decode('utf-8')).decode('utf-8')
def Register(request): restdata = {'data': '', 'regerror': ''} registerobj = forms.Register() #实例化forms restdata['data'] = registerobj #将对象传到模板中 if request.method == 'POST': form = forms.Register(request.POST) if form.is_valid(): username = request.POST['username'] email = request.POST['email'] password1 = request.POST['password1'] password2 = request.POST['password2'] if not Suser.objects.all().filter(email=email): #先判断是否存在该用户 if form.pwd_validate(password1, password2): #判断密码是否一致 user = Suser.objects.create_user(email, username, password1) user.save() #生成验证连接并发送邮件 s = TimestampSigner(django_settings.SECRET_KEY) registerstring = s.sign(email) sendmail.delay(dict(to=email, string=registerstring)) #发送邮件 return HttpResponseRedirect('/web/login/') else: error = u'密码输入不一致!!' restdata['regerror'] = error else: error = u'用户已存在,请重新输入!!!!!' restdata['regerror'] = error else: restdata['data'] = form return render(request, 'webapp/register.html', restdata)
def confirm_account(token): email = _check_token(token).decode('utf8') form = forms.SetPasswordForm() user = models.InviteApplicant.objects.filter(email=email).first() if not email: current_app.logger.info('token has expired.') flash('Link has expired', 'error') else: if user.password_set: flash('Account already confirmed and password set') return render_template('done.html', message='Account already confirmed and password set') if form.validate_on_submit(): password = form.password.data www_id = app.config['WWW_CLIENT_ID'] www_key = app.config['WWW_CLIENT_KEY'] to_sign = '%s:%s:%s' % (www_id, email, password) signer = TimestampSigner(www_key, digest_method=hashlib.sha256) signed = signer.sign(to_sign) headers = { 'Authorisation': signed } url = '%s/update-user-password' % app.config['REGISTRY_BASE_URL'] resp = requests.post(url, data={'email': email}, headers=headers) if resp.status_code == 200: user = models.InviteApplicant.objects.filter(email=email).first() user.password_set = True user.save() flash('Your password has been updated') return render_template('done.html', message='Your password has been updated') else: flash('Failed to set new password in registry', 'error') return render_template('set_account_password.html', form=form, token=token, user=user)
class CookieBackend(SessionBackend): """Stores session data in the browser's cookie as a signed string.""" def __init__(self, secret_key: t.Union[str, Secret], max_age: int): self._signer = TimestampSigner(str(secret_key)) self._max_age = max_age async def read(self, session_id: str) -> t.Dict: """A session_id is a signed session value.""" try: data = self._signer.unsign(session_id, max_age=self._max_age) return json.loads(b64decode(data).decode()) except (BadSignature, SignatureExpired): return {} async def write(self, data: t.Dict, session_id: t.Optional[str] = None) -> str: """The data is a session id in this backend.""" encoded_data = b64encode(json.dumps(data).encode("utf-8")) return self._signer.sign(encoded_data).decode("utf-8") async def remove(self, session_id: str) -> None: """Session data stored on client side - no way to remove it.""" async def exists(self, session_id: str) -> bool: return False
def make_server_request(request, payload, endpoint, auth=None, method="post"): """ makes a json request to channelstream server endpoint signing the request and sending the payload :param request: :param payload: :param endpoint: :param auth: :return: """ server_port = request.registry.settings["port"] signer = TimestampSigner(request.registry.settings["secret"]) sig_for_server = signer.sign("channelstream") if not six.PY2: sig_for_server = sig_for_server.decode("utf8") secret_headers = { "x-channelstream-secret": sig_for_server, "Content-Type": "application/json", } url = "http://127.0.0.1:%s%s" % (server_port, endpoint) response = getattr(requests, method)(url, data=json.dumps(payload), headers=secret_headers, auth=auth) if response.status_code >= 400: log.error(response.text) response.raise_for_status() return response
def send(): pass_secret = current_app.config.get('PASS_SECRET_KEY') pass_token_age = current_app.config.get('PASS_TOKEN_AGE') test_mode = current_app.config.get('TESTING') email = request.json.get('email') user = User.get_by_email(email) if user: singer = TimestampSigner(pass_secret) token_bytes = singer.sign(user.email) token = token_bytes.decode('utf-8') # Send token only for testing purposes if test_mode == True: return make_response( jsonify({ 'message': 'Email has been sent', 'token': token }), HTTPStatus.ACCEPTED) # TODO: add sending email current_app.logger.info( 'Reset password link: /password/reset?token=%s', token) return make_response(jsonify({'message': 'Email has been sent'}), HTTPStatus.ACCEPTED) return make_response(jsonify({'message': { 'email': 'Not found' }}), HTTPStatus.NOT_FOUND)
class Tokenizer(object): """ A class for creating cryptographically signed tokens used by CivID. >>> tokenizer = Tokenizer('123') >>> lt = tokenizer.create_login_token('gatzy') >>> tokenizer.validate_login_token(lt) 'gatzy' >>> ic = tokenizer.create_identity_code('ttk2') >>> tokenizer.validate_identity_code(ic) 'ttk2' """ def __init__(self, signing_key): self.key = signing_key self.signer = TimestampSigner(signing_key) def short_sig(self, string): """ Returns a token computed from truncating the hash of the given string with the signing key. """ return base64.urlsafe_b64encode( hashlib.sha256(self.key + string).digest() )[:SHORT_SIG_LENGTH] def create_login_token(self, username): """ Creates a login token of the form "signatureUsername". This token is bound to a UNIX timestamp divided by LOGIN_WINDOW_S, but it is not stored within the token in order to limit its length. """ return self.short_sig(username + now_str()) + username def validate_login_token(self, token): if len(token) < SHORT_SIG_LENGTH + MIN_USERNAME_LENGTH: raise InvalidTokenError("Malformed token") signature = token[0:SHORT_SIG_LENGTH] user = token[SHORT_SIG_LENGTH:] if ( signature != self.short_sig(user + now_str()) and signature != self.short_sig(user + last_period_str()) ): raise InvalidTokenError("Login link invalid or expired") return user def create_identity_code(self, username): # Identity codes contain this silly "scrambled" version of the username # to discourage naive implementations from parsing it out of the code # without making a request to validate it against the CivID server. return self.signer.sign(scramble_username(username)) def validate_identity_code(self, code): try: return unscramble_username(self.signer.unsign(code, max_age=CODE_WINDOW_S)) except: raise InvalidCodeError()
def create_token(self): """ 生成 token (基于 uuid) """ from uuid import uuid1 from itsdangerous import TimestampSigner s = TimestampSigner(self._sign_key) return s.sign(str(uuid1()))
async def send_path(loop): signer = TimestampSigner(args.key) message = signer.sign(args.path.encode('utf-8')) logger.debug('message: %s', message) _, writer = await asyncio.open_connection(args.host, args.port, loop=loop) writer.write(message) writer.close()
def sign(self, session_id): """ 签名 session_id :param session_id: :return: """ s = TimestampSigner(self._sign_key) return s.sign(session_id)
def create_token(self): """ 生成 token (基于 uuid) """ from uuid import uuid1 from itsdangerous import TimestampSigner s = TimestampSigner(self._sign_key) return s.sign(str(uuid1()))
def encrypt(self, payload, timestamp=False): result = '' s1 = URLSafeSerializer(self.secret_key) result = s1.dumps(payload) if(timestamp == True): s2 = TimestampSigner(self.secret_key) result = s2.sign(result) return result
def generate_reset_token(): s = TimestampSigner( "Secret") # Creating a timestamp signer with an associated secret key string = s.sign("foo") # Attaches time information of the signing print(s.unsign( string, max_age=20)) # Decrypts the received string with the timestamp signer return string
def sign(self, session_id): """ 签名 session_id :param session_id: :return: """ s = TimestampSigner(self._sign_key) return s.sign(session_id)
class TokenManager(object): def setup(self, secret): """ Create a cypher to encrypt IDs and a signer to sign tokens.""" # Create cypher to encrypt IDs key = secret + '0123456789abcdef' # ensure >=16 characters sixteen_byte_key = key[0:16] # get first 16 characters self.cipher = AES.new(sixteen_byte_key) # Create signer to sign tokens self.signer = TimestampSigner(secret) def encrypt_id(self, id): """ Encrypts integer ID to url-safe base64 string.""" str1 = '%016d' % id # --> 16 byte integer string str2 = self.cipher.encrypt(str1) # --> encrypted data str3 = base64.urlsafe_b64encode(str2) # --> URL safe base64 string with '==' return str3[0:-2] # --> base64 string without '==' def decrypt_id(self, encrypted_id): """ Decrypts url-safe base64 string to integer ID""" # In Python3, encrypted_id is <type 'str'> and needs to be converted to bytes if type(encrypted_id)=='str': # pragma: no cover encrypted_id = encrypted_id.encode('ascii') try: str3 = encrypted_id + b'==' # --> base64 string with '==' str2 = base64.urlsafe_b64decode(str3) # --> encrypted data str1 = self.cipher.decrypt(str2) # --> 16 byte integer string return int(str1) # --> integer id except Exception as e: # pragma: no cover print('!!!Exception in decrypt_id!!!') return 0 def generate_token(self, id): """ Return token with id, timestamp and signature""" # In Python3 we must make sure that bytes are converted to strings. # Hence the addition of '.decode()' return self.signer.sign(self.encrypt_id(id)).decode() def verify_token(self, token, expiration_in_seconds): """ Verify token and return (is_valid, has_expired, id). Returns (True, False, id) on success. Returns (False, True, None) on expired tokens. Returns (False, False, None) on invalid tokens.""" try: data = self.signer.unsign(token, max_age=expiration_in_seconds) is_valid = True has_expired = False id = self.decrypt_id(data) except SignatureExpired: is_valid = False has_expired = True id = None except BadSignature: is_valid = False has_expired = False id = None return (is_valid, has_expired, id)
class Tokenizer(object): """ A class for creating cryptographically signed tokens used by CivID. >>> tokenizer = Tokenizer('123') >>> lt = tokenizer.create_login_token('gatzy') >>> tokenizer.validate_login_token(lt) 'gatzy' >>> ic = tokenizer.create_identity_code('ttk2') >>> tokenizer.validate_identity_code(ic) 'ttk2' """ def __init__(self, signing_key): self.key = signing_key self.signer = TimestampSigner(signing_key) def short_sig(self, string): """ Returns a token computed from truncating the hash of the given string with the signing key. """ return base64.urlsafe_b64encode( hashlib.sha256(self.key + string).digest())[:SHORT_SIG_LENGTH] def create_login_token(self, username): """ Creates a login token of the form "signatureUsername". This token is bound to a UNIX timestamp divided by LOGIN_WINDOW_S, but it is not stored within the token in order to limit its length. """ return self.short_sig(username + now_str()) + username def validate_login_token(self, token): if len(token) < SHORT_SIG_LENGTH + MIN_USERNAME_LENGTH: raise InvalidTokenError("Malformed token") signature = token[0:SHORT_SIG_LENGTH] user = token[SHORT_SIG_LENGTH:] if (signature != self.short_sig(user + now_str()) and signature != self.short_sig(user + last_period_str())): raise InvalidTokenError("Login link invalid or expired") return user def create_identity_code(self, username): # Identity codes contain this silly "scrambled" version of the username # to discourage naive implementations from parsing it out of the code # without making a request to validate it against the CivID server. return self.signer.sign(scramble_username(username)) def validate_identity_code(self, code): try: return unscramble_username( self.signer.unsign(code, max_age=CODE_WINDOW_S)) except: raise InvalidCodeError()
def setup_password_reset(email): if email and urlfinder.get_userinfo(email): s = TimestampSigner(settings["secret_key"]) signed_string_b64 = base64.b64encode(s.sign(email)) msg = Message(body="Hi,\nYou requested a password reset.\nHere is your reset link: " + settings["domain"] + "?token=" + signed_string_b64 + "#reset", subject="Password reset", recipients=[email]) mail.send(msg)
def admin_login(user_id): """ 后台登录前台用户 :return: """ s = TimestampSigner(app.config.get('ADMIN_TO_USER_LOGIN_SIGN_KEY')) user_id_sign = s.sign(str(user_id)) return redirect('%s/auth/admin_login/?uid_sign=%s' % (app.config.get('FRONTEND_URL', ''), user_id_sign))
def Index(): """Login portal for clients""" if current_user.is_authenticated: """If client is authenticated, return them back to their portal case view""" return render_template("Client_View.html", title='client_view', Client_id=current_user.Client_id, api_key=current_user.api_key) form = LoginForm() if (request.method == 'POST') and (form.validate_on_submit()): Client_id = form.Client_id.data Password = form.Password.data user = User.query.filter_by(Client_id=Client_id).first() if not user and app.config['NO_PASSWORD'] == True: """Allow anyone to create their own account""" pass_hash = bcrypt_sha256.encrypt(Password, rounds=12) user = User(Client_id=Client_id, Password=pass_hash, api_key='') Sample_date = Client_View(client_id=Client_id, case_name='sample case', priority='1', target_date='10/7/2016', product_area='Engineering', status='In Progress', description='something') db.session.add(user) db.session.commit() db.session.add(Sample_date) db.session.commit() """ If user is a vaild account, proceed with verifying \ their credentials and provide them the API key""" if user: if bcrypt_sha256.verify( Password, user.Password) and user.Client_id == Client_id: signer = TimestampSigner(SECRET_KEY) API_KEY = ''.join([ random.choice(string.ascii_letters + string.digits) for n in xrange(30) ]) user.api_key = signer.sign(API_KEY) user.current_login_ip = request.remote_addr db.session.commit() login_user(user) flash('You have successfully logged in') return render_template("Client_View.html", title='client_view', Client_id=Client_id, api_key=user.api_key) if form.errors: flash(form.errors, 'danger') flash( 'Incorrect Credentials, please enter the correct Client Id and Password' ) return render_template('Index.html', form=form) if form.errors: flash(form.errors, 'danger') return render_template('Index.html', form=form)
def _sign(app, session_id): """ 签名 session_id :param app: :param session_id: 通常是uuid :return: """ s = TimestampSigner(app.secret_key) return s.sign(session_id)
class SignedCookieManager: session = Session def __init__(self, secret, store, cookie='sid'): self.store = store self.delta = store.delta # lifespan delta in seconds. self.cookie_name = cookie self.signer = TimestampSigner(secret) def generate_id(self): return str(uuid4()) def refresh_id(self, sid): return str(self.signer.sign(sid), 'utf-8') def verify_id(self, ssid): return self.signer.unsign(ssid, max_age=self.delta) def get_session(self, cookie): new, sid = self.get_id(cookie) return self.session(sid, self.store, new=new) def get_id(self, cookie): if cookie is not None: morsels = parse(cookie) signed_sid = morsels.get(self.cookie_name) if signed_sid is not None: try: sid = self.verify_id(signed_sid) return False, str(sid, 'utf-8') except itsdangerous.exc.SignatureExpired: # Session expired. We generate a new one. pass return True, self.generate_id() def cookie(self, sid, path="/", domain="localhost"): """We enforce the expiration. """ # Refresh the signature on the sid. ssid = self.refresh_id(sid) # Generate the expiration date using the delta expires = datetime.now() + timedelta(seconds=self.delta) # Create the cookie containing the ssid. cookie = Cookie( name=self.cookie_name, value=ssid, path=path, domain=domain, expires=expires) value = str(cookie) # Check value if len(value) > 4093: # 4096 - 3 bytes of overhead raise ValueError('The Cookie is over 4093 bytes.') return value
def email_sign(): """ 邮箱签名(带过期时间) http://localhost:5000/email/[email protected] """ email = request.args.get('email', '') from itsdangerous import TimestampSigner s = TimestampSigner(app.config['SECRET_KEY']) return s.sign(email)
def email_sign(): """ 邮箱签名(带过期时间) http://localhost:5000/email/[email protected] """ email = request.args.get('email', '') from itsdangerous import TimestampSigner s = TimestampSigner(app.config['SECRET_KEY']) return s.sign(email)
def _login(client: TestClient, email: str) -> None: signer = TimestampSigner(config.SESSION_SECRET) session_cookie = signer.sign( b64encode(json.dumps({ 'email': email, }).encode())).decode() client.cookies[config.SESSION_COOKIE] = session_cookie
class TestFeatureRequestController(unittest.TestCase): def setUp(self): src.main.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' src.main.app.config['TESTING'] = True self.signer = TimestampSigner(secret) self.app = src.main.app.test_client() with src.main.app.app_context(): src.main.init_app() def tearDown(self): pass def test_get_all_empty_db(self): response = self.app.get('/v1/feature_request', headers={'token': self.signer.sign('tomasz')}) json_response = json.loads(response.data) self.assertIsNotNone(json_response['feature_requests']) self.assertEquals(len(json_response['feature_requests']), 0) def test_post_new(self): json_payload = { "title": "test_post_new", "description": "Added from unit test", "client_id": 1 } response = self.app.post('/v1/feature_request', data=json.dumps(json_payload), headers={ 'Content-Type': 'application/json', 'token': self.signer.sign('tomasz') }) self.assertEquals(response.status_code, 201) get_all_response = self.app.get( '/v1/feature_request', headers={'token': self.signer.sign('tomasz')}) json_response = json.loads(get_all_response.data) self.assertIsNotNone(json_response['feature_requests']) self.assertEquals(len(json_response['feature_requests']), 1) item = json_response['feature_requests'][0] del item['id'] self.assertEquals(item, json_payload)
def encrypt(string): """ This method will return encrypted version of a string. It will return False if encryption fails """ try: signer = TimestampSigner(encrypt_key) return signer.sign(string) except: return False
def get_reset_token(self) -> str: secret_key = current_app.config.get('SECRET_KEY') expire_in = current_app.config.get('RESET_TOKEN_EXPIRES') salt = expire_in.__str__() url_safe_serializer = URLSafeSerializer(secret_key, salt) timestamp_signer = TimestampSigner(secret_key) data = url_safe_serializer.dumps({'user_id': self.id}) return timestamp_signer.sign(data).decode('utf-8')
class TestClientController(unittest.TestCase): def setUp(self): src.main.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' src.main.app.config['TESTING'] = True self.signer = TimestampSigner(secret) self.app = src.main.app.test_client() with src.main.app.app_context(): src.main.init_app() def tearDown(self): pass def test_get_all_initial_clients(self): from itsdangerous import TimestampSigner response = self.app.get('/v1/client', headers={'token': self.signer.sign('tomasz')}) json_response = json.loads(response.data) self.assertIsNotNone(json_response['clients']) self.assertEquals(len(json_response['clients']), 0) def test_post_new(self): json_payload = { "name": "test_post_new_client", } response = self.app.post('/v1/client', data=json.dumps(json_payload), headers={ 'Content-Type': 'application/json', 'token': self.signer.sign('tomasz') }) self.assertEquals(response.status_code, 201) get_all_response = self.app.get( '/v1/client', headers={'token': self.signer.sign('tomasz')}) json_response = json.loads(get_all_response.data) self.assertIsNotNone(json_response['clients']) self.assertEquals(len(json_response['clients']), 1) item = json_response['clients'][0] self.assertIsNotNone(item['feature_requests']) self.assertEquals(len(item['feature_requests']), 0)
def send_account_recovery_mail(app, user): signer = TimestampSigner(app.config['SECRET_KEY'], salt='recovery') recovery_token = signer.sign(user.username) recovery_url = 'http://%s%s' %(app.config['SERVER_NAME'], url_for('recover_account', recovery_token=recovery_token)) response = send_mail(app, user, subject='Account recovery', html= "Hi %s \n <br>" % user.username+ "Someone has requested to reset the password for your account.<br>" "If you wish to reset your password click the following link: <br>" "<a href='%s'>%s</a> <br>" % (recovery_url, recovery_url) + "This link will expire in one hour.") return response.status_code == 200
async def agent_websocket_token(request: web.Request): error = verify_token(test_config, request) if error: return error ########## Sing and send signer = TimestampSigner(test_config.app_config['SECRET_KEY'], salt="websocket_agent") assert test_config.agent_id is not None token = signer.sign(str(test_config.agent_id)) response_dict = {"token": token.decode()} return web.Response(text=json.dumps(response_dict), headers={'content-type': 'application/json'})
def generate_api_key(environment, user): if environment not in ['Development', 'Staging', 'Production']: print('Invalid environment') sys.exit(1) from itsdangerous import TimestampSigner from pxa import config config_env = getattr(config, '{0}Config'.format(environment)) signer = TimestampSigner(config_env.SIGNER_KEY) print('APIKEY: {0}'.format(signer.sign(user)))
class Auth: @classmethod def __init__(self, app): self.signer = TimestampSigner(app.config['SECRET_KEY']) self.app = app @classmethod def requires_login(self, f): @wraps(f) def decorated(*args, **kwargs): authentication_token = request.headers.get('Authentication-Token') if not authentication_token or not self.__is_token_valid( authentication_token): return response( status=401, message='Not authorized' ) return f(*args, **kwargs) return decorated @staticmethod def hash_password(password): return hashlib.sha256(password).hexdigest() @classmethod def generate_auth_token(self): token_random_string = ''.join( choice(ascii_letters) for i in range( self.app.config['TOKEN_RANDOM_STRING_LENGTH'])) return self.signer.sign(token_random_string) @classmethod def __is_token_valid(self, authentication_token): try: self.signer.unsign( authentication_token, max_age=self.app.config['TOKEN_VALIDITY_DURATION'] ) except SignatureExpired as e: self.app.logger.info('INFO: SignatureExpired, %s', str(e)) return False # valid token, but expired except BadSignature as e: self.app.logger.info('INFO: BadSignature, %s', str(e)) return False # invalid token return True
def get(self, workspace_name): """ --- get: tags: ["Token"] responses: 200: description: Ok """ workspace = self._get_workspace(workspace_name) signer = TimestampSigner(app.config['SECRET_KEY'], salt="websocket") token = signer.sign(str(workspace.id)).decode('utf-8') return {"token": token}
def reset_user_password_step_one(form): """ first step of the password reset: hash generated, email with hash sent """ # create an itsdangerous object to sign the verification email and encrypt the password itsd = TimestampSigner(config.ACCOUNT_VERIFICATION_SECRET) # generate a temporary password temp_password = os.urandom(12).encode("hex") reset_code = itsd.sign(temp_password) time_limit = datetime.now() + timedelta(hours=3) # check local database loc_db_user = AdsUserRecord.query.filter(AdsUserRecord.username == form.login.data) # @UndefinedVariable # get the user object user_rec = loc_db_user.first() if not user_rec: app.logger.error("User password reset error: user not in db. Email used: %s" % form.login.data) else: # store the reset password locally loc_db_user.set(password=reset_code).execute() # sent the email message_html = """<h3>ADS Password reset</h3> <p>Your temporary reset code is <strong>%(reset_code)s</strong></p> <p>To complete the password reset, please click <a href="%(reset_url)s">here</a></p> <p>If the link doesn't work, please copy the following URL and paste it in your browser:<br/>%(reset_url)s</p> <p>This temporary reset code is valid only until %(password_time_limit)s<p> <p>Please do not replay to this email: to contact us please use our <a href="%(feedb_url)s">feedback form</a></p> <p>Regards,<br/>The ADS team</p> """ % { "reset_code": reset_code, "reset_url": "%s%s?login=%s&resetcode=%s" % ( config.MAIL_CONTENT_REDIRECT_BASE_URL, url_for("user.confirm_reset_password"), form.login.data, reset_code, ), "feedb_url": "%s%s" % (config.MAIL_CONTENT_REDIRECT_BASE_URL, url_for("feedback.feedback")), "password_time_limit": time_limit.strftime("%A, %d. %B %Y %I:%M%p"), } try: send_email_to_user(u"NASA ADS: confirmation required for login update", message_html, [form.login.data]) except: app.logger.error("Failed to send reset email for user password.") return False, "There are some technical problems: please try later.", "error" return ( True, "If the email you entered exists in our system, you will shortly receive a message at your e-mail address with further instructions on how to reset your password.", "warning", )
def generate_sign_token(string, secret_key=None, salt=None, sep=None): if not salt: salt = constants["SALT_KEY"] if not sep: sep = constants["SEP_KEY"] if not secret_key: secret_key = constants["SECRET_KEY"] signer = TimestampSigner(secret_key, salt=salt, sep=sep) signed_string = signer.sign(string).decode() ts = signer.get_timestamp() return signed_string, ts
def index(): if not login.current_user.is_authenticated: return redirect(url_for('user_login')) received = IncomingMessages.objects.all() resp = make_response(render_template( 'index.html', user=login.current_user, received=received)) # workaround for firefox issue with cookies if hasattr(g.user, 'id'): s = TimestampSigner(app.config["SECRET"]) signature = s.sign(str(g.user.id)) resp.set_cookie(app.config["OPERATOR_ID_COOKIE"], value=signature) return resp
def send_email(self, host): # send email using the self.cleaned_data dictionary data = self.cleaned_data email = data['email'] s = TimestampSigner(SECRET_KEY, salt="register-user") token_string = s.sign(email) registration_url = reverse('activate_user') registration_url += "?em_tk=" + token_string #registration_url = PRODUCTION_BASE_URL + registration_url registration_url = "http://" + host + registration_url ctx = { 'email' : email, 'registration_url' : registration_url } send_template_email(_("Email verification for signup"), "verified_registration/registration_mail.html", ctx, email)
def itsEncode(data: str, url_safe_key: str = DEFAULT_SAFE_KEY, time_safe_key: str = DEFAULT_SAFE_KEY) -> TimestampSigner.sign: ''' @description: its加密 @param {data} data 加密数据 @param {str} url_safe_key URL加密密钥 @param {str} time_safe_key Time加密密钥 @return: Data ''' uSafe = URLSafeSerializer(url_safe_key) dumpUsafe = uSafe.dumps(data) tSafe = TimestampSigner(time_safe_key) signTsafe = tSafe.sign(dumpUsafe) return signTsafe
def SendResetEmail(request): if request.method == 'POST': email = request.POST.get('email') try: user = Suser.objects.get(email=email) except Suser.DoesNotExist: msg = {'msgerror': u'对不起,您输入的用户不存在,请重新输入!!!'} return HttpResponse(json.dumps(msg)) s = TimestampSigner(django_settings.SECRET_KEY) resetstring = s.sign(email) resetpass.delay(dict(to=email, string=resetstring)) msg = {'msginfo': u'邮件发送成功,请及时确认!!!!'} return HttpResponse(json.dumps(msg)) else: return render(request, 'webapp/sendresetpw.html')
def login(): body = request.get_json() if body['login'] is None: return '', 403 user = User.query.filter_by(login=body['login']).first() if user is None: return '', 403 if user.password != body['password']: return '', 403 signer = TimestampSigner(secret) token = signer.sign(body['login']) return jsonify(user=user.jsonify(), token=token)
def send_email(self): # send email using the self.cleaned_data dictionary data = self.cleaned_data email = data['email'] s = TimestampSigner(SECRET_KEY, salt="change-password") token_string = s.sign(email) registration_url = reverse('change_password') registration_url += "?em_tk=" + token_string #registration_url =PRODUCTION_BASE_URL + registration_url registration_url = "http://" + host + registration_url ctx = { 'email' : email, 'registration_url' : registration_url } send_template_email(_("Reset password confirmation"), "verified_registration/password_recover_mail.html", ctx, email)
def demo_payload_relay(request): server_url = request.registry.settings["channelstream.url"] endpoint = request.json_body["endpoint"] payload = request.json_body["payload"] method = request.json_body["method"] signer = TimestampSigner(request.registry.settings["channelstream.secret"]) sig_for_server = signer.sign("channelstream") secret_headers = { "x-channelstream-secret": sig_for_server, "Content-Type": "application/json", } url = f"{server_url}{endpoint}" response = getattr(requests, method)( url, data=json.dumps(payload), headers=secret_headers ) return response.json()
def get_password_reset_link(email): email = unicode(email).lower() retrieved_user = User.query.filter_by(email=email).first() if retrieved_user is None: abort(404, "That user doesn't exist.") # make the signed reset token s = TimestampSigner(os.getenv("SECRET_KEY"), salt="reset-password") reset_token = s.sign(retrieved_user.email) base_reset_url = g.roots["webapp_pretty"] + "/change-password" full_reset_url = base_reset_url + "/" + reset_token # send the email here... mailer = mandrill.Mandrill(os.getenv("MANDRILL_APIKEY")) text = """Hi! You asked to reset your ImpactStory password. To do that, just copy and paste the URL below into your browser's address bar:\n\n{url}\n\n(If you didn't ask to reset your password, you can just ignore this message).\nBest,\nThe ImpactStory team""".format(url=full_reset_url) html = """<p>Hi! You asked to reset your ImpactStory password. To do that, just <a href="{url}">click this reset link</a>, or copy and paste the URL below into your browser's address bar:</p><pre>{url}</pre><p>(If you didn't ask to reset your password, you can just ignore this message.)<br>Best,<br>The ImpactStory team</p>""".format(url=full_reset_url) msg = { "text": text, "html": html, "subject": "Password reset link", "from_email": "*****@*****.**", "from_name": "ImpactStory support", "to": [{"email":email, "name":"ImpactStory user"}], # must be a list "tags": ["password-resets"], "track_opens": False, "track_clicks": False } mailer.messages.send(msg) logger.info(u"Sent a password reset email to " + email) return json_for_client({"message": "link emailed."})
def index(self): secret_key = current_app.config.get("SECRET_KEY") if current_app.config.get("TEMP_SECRET_KEY"): inifile = INIConfig() inifile.read(settings.CONFIG_FILE) if not inifile.has_section("flask"): inifile.add_section("flask") flask_config = inifile["flask"] if not flask_config.get("SECRET_KEY"): flash("Missing SECRET_KEY, creating a new config file...", "error") inifile.set("flask", "SECRET_KEY", str(os.urandom(24))) with open(settings.CONFIG_FILE, 'w') as configfile: inifile.write(configfile) else: flash("A new SECRET_KEY is in the configfile, but app still needs a restart...", "warning") s = TimestampSigner(secret_key) print(78 * "=" + "\nLogin Code: %s\n" % s.sign('maintain').decode("utf-8") + 78 * "=") form = MTLogin() return self.render('home/index.html', form=form)
def get_auth_user(self): """ Use self-signed TimestampSigner to retrieve auth_id """ auth_token = parse_cookie(self.ws.environ['HTTP_COOKIE']).get('auth_token') if auth_token is None: self.on_close('invalid authentication') self.ws.send('AUTH') # tell client to reauth self.ws.close() else: expiration_seconds = app.config['AUTH_TOKEN_SECONDS'] signer = TimestampSigner(app.config['SECRET_KEY']) try: auth_id = signer.unsign(auth_token, max_age=expiration_seconds) # Validate user is in db user = models.User.query.filter_by(auth_id=auth_id).first() if user is None: self.ws.send('AUTH') self.ws.close() return # Upgrade token if token is about to expire try: reissue_seconds = app.config['REISSUE_AUTH_TOKEN_SECONDS'] auth_id = signer.unsign(auth_token, max_age=reissue_seconds) except SignatureExpired: signer = TimestampSigner(app.config['SECRET_KEY']) auth_token = signer.sign(auth_id) self.ws.send('UPGRADE:{}'.format(auth_token)) return user except SignatureExpired: self.on_close('auth token expired') self.ws.send('AUTH') # tell client to reauth self.ws.close() except BadSignature: self.on_close('invalid authentication') self.ws.send('AUTH') # tell client to reauth self.ws.close()
def send_reset_token(email, url_base): # make the signed reset token s = TimestampSigner(os.getenv("SECRET_KEY"), salt="reset-password") reset_token = s.sign(email) full_reset_url = url_base + "reset-password/" + reset_token # send the email here... mailer = mandrill.Mandrill(os.getenv("MANDRILL_APIKEY")) text = """Hi! You asked to reset your ImpactStory password. To do that, just copy and paste the URL below into your browser's address bar:\n\n{url}\n\n(If you didn't ask to reset your password, you can just ignore this message).\nBest,\nThe ImpactStory team""".format( url=full_reset_url ) html = """<p>Hi! You asked to reset your ImpactStory password. To do that, just <a href="{url}">click this reset link</a>, or copy and paste the URL below into your browser's address bar:</p><pre>{url}</pre><p>(If you didn't ask to reset your password, you can just ignore this message.)<br>Best,<br>The ImpactStory team</p>""".format( url=full_reset_url ) msg = { "text": text, "html": html, "subject": "Password reset link", "from_email": "*****@*****.**", "from_name": "ImpactStory support", "to": [{"email": email, "name": "ImpactStory user"}], # must be a list "tags": ["password-resets"], "track_opens": False, "track_clicks": False, } mailer.messages.send(msg) logger.info(u"Sent a password reset email to " + email) return True
def login(): method = request.form['method'] if method == 'device': device_id = request.form['id'] device_login = DeviceLogin.query.get(device_id) if device_login is None: abort(401) signer = TimestampSigner(app.secret_key) user_id = device_login.user.id token = signer.sign(str(user_id)) return jsonify({'token': token}) elif method == 'username': username = request.form['username'] password = request.form['password'] username_login = UsernameLogin.query.get(username) if username_login is None or username_login.password != password: abort(401) login_user(username_login.user) return jsonify({'success': True})
def invite_user(): email = request.args.get('email') full_name = request.args.get('full_name') if not (email or full_name): current_app.logger.info('must provide email and full name') return 400, 'Bad Request' www_id = app.config['WWW_CLIENT_ID'] www_key = app.config['WWW_CLIENT_KEY'] to_sign = '%s:%s:%s' % (www_id, email, full_name) signer = TimestampSigner(www_key, digest_method=hashlib.sha256) signed = signer.sign(to_sign) headers = { 'Authorisation': signed } url = '%s/register-user' % app.config['REGISTRY_BASE_URL'] resp = requests.post(url, data={'email':email, 'full_name': full_name}, headers=headers) if resp.status_code == 201: user = models.InviteApplicant.objects.filter(email=email).first() user.invited = True user.save() token = _generate_token(email) confirmation_url = "%s/confirm-account/%s" % (app.config['BASE_URL'], token) html = render_template('confirm_account.html', full_name=full_name, confirmation_url=confirmation_url) msg = Message(html=html, subject="Your idealgov account", sender="*****@*****.**", recipients=[email]) try: mail.send(msg) flash("User account created. Invite sent to: %s." % email) except Exception as ex: log_traceback(current_app.logger, ex) flash("Failed to send invite to: %s" % email, 'error') else: flash('Error creating account', 'error') return redirect(url_for('the_hatch'))
class TokenManager(object): def __init__(self): """ Create a cypher to encrypt IDs and a signer to sign tokens.""" # Create cypher to encrypt IDs # and ensure >=16 characters # secret = app.config.get('SECRET_KEY') secret = 'SECRET_KEY' precursor = b'0123456789abcdef' if isinstance(secret, bytes): key = secret + precursor else: key = secret.encode("utf-8") + precursor self.cipher = AES.new(key[0:16], AES.MODE_ECB) # Create signer to sign tokens self.signer = TimestampSigner(secret) def encrypt_id(self, id): """ Encrypts integer ID to url-safe base64 string.""" # 16 byte integer str1 = '%016d' % id # encrypted data str2 = self.cipher.encrypt(str1.encode()) # URL safe base64 string with '==' str3 = base64.urlsafe_b64encode(str2) # return base64 string without '==' return str3[0:-2] def decrypt_id(self, encrypted_id): """ Decrypts url-safe base64 string to integer ID""" # Convert strings and unicode strings to bytes if needed if hasattr(encrypted_id, 'encode'): encrypted_id = encrypted_id.encode('ascii', 'ignore') try: str3 = encrypted_id + b'==' # --> base64 string with '==' # print('str3=', str3) str2 = base64.urlsafe_b64decode(str3) # --> encrypted data # print('str2=', str2) str1 = self.cipher.decrypt(str2) # --> 16 byte integer string # print('str1=', str1) return int(str1) # --> integer id except Exception as e: # pragma: no cover print('!!!Exception in decrypt_id!!!:', e) return 0 def generate_token(self, id): """ Return token with id, timestamp and signature""" # In Python3 we must make sure that bytes are converted to strings. # Hence the addition of '.decode()' return self.signer.sign(self.encrypt_id(id)).decode() def verify_token(self, token, expiration_in_seconds): """ Verify token and return (is_valid, has_expired, id). Returns (True, False, id) on success. Returns (False, True, None) on expired tokens. Returns (False, False, None) on invalid tokens.""" try: data = self.signer.unsign(token, max_age=expiration_in_seconds) is_valid = True has_expired = False id = self.decrypt_id(data) except SignatureExpired: is_valid = False has_expired = True id = None except BadSignature: is_valid = False has_expired = False id = None return (is_valid, has_expired, id)
def timestamp_sign(value, secret_key, *, salt=''): signer = TimestampSigner(secret_key, salt=salt) return signer.sign(value)
def gen_signature(data): """Generates a TimestampSignature using config SECRET_KEY.""" s = TimestampSigner(conf.get('cookie_secret')) return s.sign(str(data))
def _generate_token(email): from itsdangerous import TimestampSigner signer = TimestampSigner(app.config['SECRET_KEY']) return signer.sign(email).decode('utf8')
def add_reset(reset_user): #todo this key should actually be secret s = TimestampSigner(app.config.get('SECRET_KEY')) token = s.sign(str(reset_user.id)+'password-reset') app.redis_db.set("password-reset:#"+str(reset_user.id), token) return token
def gauth_signin(): """ Google Authentication https://developers.google.com/identity/sign-in/web/backend-auth """ try: id_token = request.form['id_token'] auth_id = request.form['auth_id'] email = request.form.get('email') name = request.form.get('name') image_url = request.form.get('image_url', 'https://ssl.webpack.de/lorempixel.com/96/96/cats/') domain = request.headers.get('Host') idinfo = client.verify_id_token(id_token, app.config['GAUTH_CLIENT_ID']) if idinfo['aud'] != app.config['GAUTH_CLIENT_ID']: raise crypt.AppIdentityError("Unrecognized client.") if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']: raise crypt.AppIdentityError("Wrong issuer.") if domain not in app.config['AUTH_DOMAINS']: raise crypt.AppIdentityError("Wrong origin. {}".format(domain)) if auth_id != idinfo['sub']: raise crypt.AppIdentityError("User IDs do not match.") except crypt.AppIdentityError as exception: app.handle_exception(exception) return json.jsonify(status='failure') except Exception as exception: # Catch all app.handle_exception(exception) return json.jsonify(status='failure') # Setup user auth user = models.User.query.filter_by(auth_id=auth_id).first() if user is None: # Add user (strip all special characters for now) username = ''.join(c for c in name if c.isalnum()) if not username or models.User.query.filter_by(username=username).first() is not None: # Generate a random one username = hashlib.sha1(auth_id).hexdigest()[:15] user = models.User( auth_id=auth_id, username=username, name=name, email=email, image_url=image_url, ) db.session.add(user) general_channel = models.Channel.query.filter_by(name=models.GENERAL_CHANNEL).first() general_channel.users.append(user) else: # Update user profile user.name = name user.email = email user.image_url = image_url # Create secure self-signed auth token that expires # http://pythonhosted.org/itsdangerous/ signer = TimestampSigner(app.config['SECRET_KEY']) auth_token = signer.sign(auth_id) # Commit and return db.session.commit() # Store session cookie so use does not need to refetch this expiration_seconds = app.config['AUTH_TOKEN_SECONDS'] response = make_response(json.jsonify(status='success', auth_id=auth_id, auth_token=auth_token)) # Check host to determine where to set cookie response.set_cookie(key='auth_token', value=auth_token, secure=True, path='/', domain=domain, max_age=expiration_seconds) return response
def generate_csrf(): s = TimestampSigner(app.config.get('SECRET_KEY')) token = s.sign(str(datetime.datetime.now())) return token
def genCdata(uid, secretkey): s = TimestampSigner(secretkey) cookie = s.sign(uid) return cookie
def generate_auth_token(self): s = TimestampSigner(current_app.config['SECRET_KEY']) token = s.sign(str(self.id)) return token