def createuser(): """Create an user""" username = click.prompt("Username", type=str) email = click.prompt("Email", type=str) password = click.prompt("Password", type=str, hide_input=True, confirmation_prompt=True) while True: role = click.prompt("Role [admin/user]", type=str) if role == "admin" or role == "user": break if click.confirm("Do you want to continue ?"): role = Role.query.filter(Role.name == role).first() if not role: raise click.UsageError("Roles not present in database") u = user_datastore.create_user(name=username, email=email, password=encrypt_password(password), roles=[role]) db.session.commit() if FSConfirmable.requires_confirmation(u): FSConfirmable.send_confirmation_instructions(u) print("Look at your emails for validation instructions.")
def validate_on_submit(self): if not CustomForm.validate_on_submit(self): return self.validation_error() self.user = g.datastore.find_user(username=self.username.data) if self.user is None: self.user = g.datastore.find_user(email=self.username.data) if self.user is None: self.username.errors.append( current_app.config['SECURITY_MSG_USER_DOES_NOT_EXIST'][0]) return self.validation_error() if not self.user.password: self.password.errors.append( current_app.config['SECURITY_MSG_PASSWORD_NOT_SET'][0]) return self.validation_error() if not verify_and_update_password(self.password.data, self.user): self.password.errors.append( current_app.config['SECURITY_MSG_INVALID_PASSWORD'][0]) return self.validation_error() if requires_confirmation(self.user): do_flash(*get_message('CONFIRMATION_REQUIRED')) return self.validation_error() if not self.user.is_active: do_flash(*current_app.config['SECURITY_MSG_DISABLED_ACCOUNT']) return self.validation_error() return self.validation_success()
def validate(self): if not super().validate(): return False self.user = find_user(self.username.data) if self.user is None: self.username.errors.append(get_message("USER_DOES_NOT_EXIST")[0]) # Reduce timing variation between existing and non-existing users hash_password(self.password.data) return False if not self.user.password: self.password.errors.append(get_message("PASSWORD_NOT_SET")[0]) # Reduce timing variation between existing and non-existing users hash_password(self.password.data) return False self.password.data = _security._password_util.normalize( self.password.data) if not self.user.verify_and_update_password(self.password.data): self.password.errors.append(get_message("INVALID_PASSWORD")[0]) return False self.requires_confirmation = requires_confirmation(self.user) if self.requires_confirmation: self.username.errors.append( get_message("CONFIRMATION_REQUIRED")[0]) return False if not self.user.is_active: self.username.errors.append(get_message("DISABLED_ACCOUNT")[0]) return False return True
def validate(self): """ Copy-pasted from flask_security and use the altered version of `verify_and_update_password`. """ if not super(LoginForm, self).validate(): return False self.user = _datastore.get_user(self.email.data) if self.user is None: self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0]) return False if not self.user.password: self.password.errors.append(get_message('PASSWORD_NOT_SET')[0]) return False if not verify_and_update_password(self.password.data, self.user): self.password.errors.append(get_message('INVALID_PASSWORD')[0]) return False if requires_confirmation(self.user): self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0]) return False if not self.user.is_active: self.email.errors.append(get_message('DISABLED_ACCOUNT')[0]) return False return True
def account_authenticate(user): """Authenticate an ACS callback. :param user: A user instance. :returns: ``True`` if the user is successfully authenticated. """ if not requires_confirmation(user): after_this_request(_commit) return login_user(user, remember=False) return False
def verify_login(self, user, password=None, **kwargs): """Verify the login via password.""" if not user.password: _abort(get_message("PASSWORD_NOT_SET")[0], "password") if not verify_and_update_password(password, user): _abort(get_message("INVALID_PASSWORD")[0], "password") if requires_confirmation(user): _abort(get_message("CONFIRMATION_REQUIRED")[0]) if not user.is_active: _abort(get_message("DISABLED_ACCOUNT")[0])
def validate(self): if not super(SignedMessageLoginForm, self).validate(): return False self.user = _user.find_beet_account_name(self.message.signed_by_name) if self.user and requires_confirmation(self.user): self.message.errors.append(get_message("CONFIRMATION_REQUIRED")[0]) return False if self.user and not self.user.is_active: self.message.errors.append(get_message("DISABLED_ACCOUNT")[0]) return False return True
def validate(self): """Validate LDAP logins against AD.""" if not super(LDAPLoginForm, self).validate(): return False if self.email.data.strip() == '': self.email.errors.append(get_message('USERID_NOT_PROVIDED')[0]) return False if self.password.data.strip() == '': self.password.errors.append( get_message('PASSWORD_NOT_PROVIDED')[0]) return False try: user_dn, ldap_data = _datastore.query_ldap_user(self.email.data) if user_dn is None: self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0]) return False if not _datastore.verify_password(user_dn, self.password.data): self.password.errors.append(get_message('INVALID_PASSWORD')[0]) return False ldap_email = ldap_data[config_value('LDAP_EMAIL_FIELDNAME')].value password = encrypt_password(self.password.data) if _datastore.find_user(email=ldap_email): self.user = _datastore.get_user(ldap_email) # note that this is being stored per user login self.user.password = password else: self.user = _datastore.create_user(email=ldap_email, password=password) _datastore.commit() except ldap3.LDAPExceptionError: self.password.errors.append(get_message('LDAP_SERVER_DOWN')[0]) self.user = _datastore.get_user(self.email.data) if not self.user.password: self.password.errors.append(get_message('PASSWORD_NOT_SET')[0]) return False if not verify_and_update_password(self.password.data, self.user): self.password.errors.append(get_message('INVALID_PASSWORD')[0]) return False if requires_confirmation(self.user): self.email.errors.append( get_message('CONFIRMATION_REQUIRED')[0]) return False if not self.user.is_active: self.email.errors.append(get_message('DISABLED_ACCOUNT')[0]) return False return True
def validate_on_submit(self): if not CustomForm.validate_on_submit(self): return self.validation_error() self.user = g.datastore.find_user(email=self.email.data) if not self.user: self.email.errors.append('Email Not Found') return self.validation_error() if requires_confirmation(self.user): do_flash(*get_message('CONFIRMATION_REQUIRED')) return self.validation_error() return self.update_success()
def oauth_authenticate(client_id, user, require_existing_link=False, remember=False): """Authenticate an oauth authorized callback.""" # Authenticate via the access token (access token used to get user_id) if not requires_confirmation(user): after_this_request(_commit) if login_user(user): if require_existing_link: account = RemoteAccount.get(user.id, client_id) if account is None: logout_user() return False return True return False
def test_web_login(self): user_details = self.create_user("*****@*****.**", "password") self.assertEquals(user_details[0], '*****@*****.**') user_obj = self.app.datastore.get_user('*****@*****.**') self.assertNotEquals(user_obj, None) self.assertEquals('*****@*****.**', user_obj.email) self.assertNotEquals(None, user_obj.password) self.assertTrue(user_obj.verify_and_update_password("password")) self.assertFalse(requires_confirmation(user_obj)) self.assertTrue(user_obj.is_active) login_response = self.login(*user_details) #self.assertTrue(current_user.is_authenticated) self.assertNotIn(b'USER = { }', login_response.data)
def validate(self): if not super(LoginForm, self).validate(): return False # Verify username field is not blank. We don't concern ourselves with email # because we don't use that to validate if self.username.data.strip() == '': self.username.errors.append('USERNAME NOT PROVIDED') return False # If the password field is left blank, fail. if self.password.data.strip() == '': self.password.errors.append('PASSWORD NOT PROVIDED') return False # set the user to be the user name in the field and look it up # in the database self.user = security.datastore.get_user(self.username.data) # Ensure the user exists in the database if self.user is None: self.username.errors.append('INCORRECT USERNAME/PASSWORD') return False # Ensure the password was set if not self.user.password: self.password.errors.append('PASSWORD WAS NOT SET') return False # Verify the password provided matches what is in the database for that user if not verify_and_update_password(self.password.data, self.user): self.password.errors.append('INCORRECT USERNAME/PASSWORD') return False # If user confirmation is enabled and the user has not confirmed, deny access if requires_confirmation(self.user): self.user.errors.append('CONFIRMATION REQUIRED') return False # Make sure that the user account is active and not disabled if not self.user.is_active: self.username.errors.append('DISABLED ACCOUNT') return False # If all other checks are passed, the user is valid return True
def validate(self): r = super(AdsClassicFallBackLoginForm, self).validate() if r is True: return r cu = None try: cu = ClassicUserInfo(self.email.data, self.password.data) except HTTPError: return False # if we can't contact ADS Classic, make it non-fatal if cu.is_authenticated(): # Classic did let them in.... if not hasattr( self, 'user') or self.user is None: # User does not exist yet user_manipulator.create(email=self.email.data, password=self.password.data, name=cu.get_name(), active=True) else: if not self.user.password: # password not set return False if not self.user.validate_password( self.password.data): # Invalid passwd self.user.password = self.password.data user_manipulator.save(self.user) if requires_confirmation(self.user): return False if not self.user.is_active() and cu.is_real_user( ): # Disabled account self.user.active = True user_manipulator.save(self.user) # revalidate return super(AdsClassicFallBackLoginForm, self).validate() elif cu.is_real_user( ): # they didn't get it, but the account at least exists... if self.user is None: user_manipulator.create(email=self.email.data, password=gen_salt(12), name=cu.get_name(), active=False) return False
def oauth_authenticate(client_id, user, require_existing_link=False): """Authenticate an oauth authorized callback. :param client_id: The client id. :param user: A user instance. :param require_existing_link: If ``True``, check if remote account exists. (Default: ``False``) :returns: ``True`` if the user is successfully authenticated. """ # Authenticate via the access token (access token used to get user_id) if not requires_confirmation(user): after_this_request(_commit) if login_user(user, remember=False): if require_existing_link: account = RemoteAccount.get(user.id, client_id) if account is None: logout_user() return False return True return False
def _try_local_auth(self): self.user = _datastore.find_user(username=self.email.data) if not self.user: self.email.errors.append(get_message("USER_DOES_NOT_EXIST")[0]) return False if not self.user.password: self.password.errors.append(get_message("PASSWORD_NOT_SET")[0]) return False if not verify_and_update_password(self.password.data, self.user): self.password.errors.append(get_message("INVALID_PASSWORD")[0]) return False if requires_confirmation(self.user): self.email.errors.append(get_message("CONFIRMATION_REQUIRED")[0]) return False if not self.user.is_active: self.email.errors.append(get_message("DISABLED_ACCOUNT")[0]) return False return True
def oauth_authenticate(client_id, user, require_existing_link=False, remember=False): """Authenticate an oauth authorized callback. :param client_id: The client id. :param user: A user instance. :param require_existing_link: If ``True``, check if remote account exists. (Default: ``False``) :returns: ``True`` if the user is successfully authenticated. """ # Authenticate via the access token (access token used to get user_id) if not requires_confirmation(user): after_this_request(_commit) if login_user(user, remember=remember): if require_existing_link: account = RemoteAccount.get(user.id, client_id) if account is None: logout_user() return False return True return False
def validate(self): self.user = _datastore.get_user(self.email.data) if self.user is None: self.email.validate(self) self.email.errors.append("User or password invalid.") return False if not verify_and_update_password(self.password.data, self.user): self.password.errors.append(get_message('INVALID_PASSWORD')[0]) return False if not self.user.password: self.password.errors.append(get_message('PASSWORD_NOT_SET')[0]) return False if requires_confirmation(self.user): self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0]) return False if not self.user.is_active: self.email.errors.append(get_message('DISABLED_ACCOUNT')[0]) return False return True
def validate(self): r = super(AdsClassicFallBackLoginForm, self).validate() if r is True: return r cu = None try: cu = ClassicUserInfo(self.email.data, self.password.data) except HTTPError: return False # if we can't contact ADS Classic, make it non-fatal if cu.is_authenticated(): # Classic did let them in.... if not hasattr(self, 'user') or self.user is None: # User does not exist yet user_manipulator.create(email=self.email.data, password=self.password.data, name=cu.get_name(), active=True) else: if not self.user.password: # password not set return False if not self.user.validate_password(self.password.data): # Invalid passwd self.user.password = self.password.data user_manipulator.save(self.user) if requires_confirmation(self.user): return False if not self.user.is_active() and cu.is_real_user(): # Disabled account self.user.active = True user_manipulator.save(self.user) # revalidate return super(AdsClassicFallBackLoginForm, self).validate() elif cu.is_real_user(): # they didn't get it, but the account at least exists... if self.user is None: user_manipulator.create(email=self.email.data, password=gen_salt(12), name=cu.get_name(), active=False) return False
def validate(self): from flask_security.utils import ( _datastore, get_message, hash_password, ) from flask_security.confirmable import requires_confirmation if not super(LoginForm, self).validate(): return False # try login using email self.user = _datastore.get_user(self.email.data) # if that didn't work try log in using the username if self.user is None: self.user = _datastore.get_user(self.username.data) if self.user is None: self.email.errors.append(get_message("USER_DOES_NOT_EXIST")[0]) # Reduce timing variation between existing and non-existing users hash_password(self.password.data) return False if not self.user.password: self.password.errors.append(get_message("PASSWORD_NOT_SET")[0]) # Reduce timing variation between existing and non-existing users hash_password(self.password.data) return False if not self.user.verify_and_update_password(self.password.data): self.password.errors.append(get_message("INVALID_PASSWORD")[0]) return False if requires_confirmation(self.user): self.email.errors.append(get_message("CONFIRMATION_REQUIRED")[0]) return False if not self.user.is_active: self.email.errors.append(get_message("DISABLED_ACCOUNT")[0]) return False return True
def validate(self): if not super(LoginForm, self).validate(): return False if not self.username.data.strip(): self.username.errors.append("Username not provided") return False if not self.password.data.strip(): self.password.errors.append( get_message("PASSWORD_NOT_PROVIDED")[0]) return False username = self.username.data self.user = _security.datastore.find_user(username=username) if not self.user: logger.warning("not found {} using username field, " "now using fallback with email".format(username)) self.user = _security.datastore.find_user(email=username) if self.user is None: self.username.errors.append(get_message("USER_DOES_NOT_EXIST")[0]) return False if not self.user.password: self.password.errors.append(get_message("PASSWORD_NOT_SET")[0]) return False if not verify_and_update_password(self.password.data, self.user): self.password.errors.append(get_message("INVALID_PASSWORD")[0]) return False if requires_confirmation(self.user): self.username.errors.append( get_message("CONFIRMATION_REQUIRED")[0]) return False if not self.user.is_active: self.username.errors.append(get_message("DISABLED_ACCOUNT")[0]) return False return True
def create(): """ Create a user. """ current_app.config["SERVER_NAME"] = current_app.config[ "REEL2BITS_HOSTNAME"] username = click.prompt("Username", type=str) email = click.prompt("Email", type=str) password = click.prompt("Password", type=str, hide_input=True, confirmation_prompt=True) while True: role = click.prompt("Role [admin/user]", type=str) if role == "admin" or role == "user": break if click.confirm("Do you want to continue ?"): role = Role.query.filter(Role.name == role).first() if not role: raise click.UsageError("Roles not present in database") u = user_datastore.create_user(name=username, email=email, password=hash_password(password), roles=[role]) actor = create_actor(u) actor.user = u actor.user_id = u.id db.session.add(actor) db.session.commit() if FSConfirmable.requires_confirmation(u): with current_app.app_context(): FSConfirmable.send_confirmation_instructions(u) print("Look at your emails for validation instructions.")
def validate(self): if not super(DeploymentLoginForm, self).validate(): participant = models.Participant.query.filter( models.Participant.participant_id == self.email.data.strip(), models.Participant.password == self.password.data.strip(), models.Participant.participant_set == g.event.participant_set).join(models.ParticipantRole).filter( models.ParticipantRole.name == '$FC').first() if participant: # get the field co-ordinator user and create it if necessary _user = _datastore.find_user(email=current_app.config.get( 'APOLLO_FIELD_COORDINATOR_EMAIL')) if not _user: _role = _datastore.find_or_create_role( 'field-coordinator', deployment=g.deployment) _user = _datastore.create_user( email=current_app.config.get( 'APOLLO_FIELD_COORDINATOR_EMAIL'), username='', password='', deployment=g.deployment, roles=[_role]) self.user = _datastore.get_user( current_app.config.get('APOLLO_FIELD_COORDINATOR_EMAIL')) session['participant'] = participant.id return True else: return False else: if self.email.data.strip() == '': self.email.errors.append(get_message('EMAIL_NOT_PROVIDED')[0]) return False if self.password.data.strip() == '': self.password.errors.append( get_message('PASSWORD_NOT_PROVIDED')[0]) return False # check by the user identity attributes defined in # the settings for identity_attribute in current_app.config.get( 'SECURITY_USER_IDENTITY_ATTRIBUTES'): kwargs = { 'deployment': g.deployment, identity_attribute: self.email.data } self.user = _datastore.find_user(**kwargs) if self.user: break if self.user is None: self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0]) return False if not self.user.password: self.password.errors.append(get_message('PASSWORD_NOT_SET')[0]) return False if not verify_and_update_password(self.password.data, self.user): self.password.errors.append(get_message('INVALID_PASSWORD')[0]) return False if requires_confirmation(self.user): self.email.errors.append( get_message('CONFIRMATION_REQUIRED')[0]) return False if not self.user.is_active: self.email.errors.append(get_message('DISABLED_ACCOUNT')[0]) return False return True
def idp_initiated(): user_email = None user_nic = None first_name = None last_name = None auth_servers = current_app.config.get('SECURITY_SAML_IDP_METADATA').split( ',') for server in auth_servers: saml_client = saml_client_for(server) try: authn_response = saml_client.parse_authn_request_response( request.form['SAMLResponse'], entity.BINDING_HTTP_POST) except sigver.MissingKey: continue else: break root = ET.fromstring(str(authn_response)) ns = { 'assertion': 'urn:oasis:names:tc:SAML:2.0:assertion', 'atributos': 'http://autenticacao.cartaodecidadao.pt/atributos' } for child in root.find('assertion:Assertion', ns).find('assertion:AttributeStatement', ns): try: if child.attrib[ 'Name'] == 'http://interop.gov.pt/MDC/Cidadao/CorreioElectronico': user_email = child.find('assertion:AttributeValue', ns).text elif child.attrib[ 'Name'] == 'http://interop.gov.pt/MDC/Cidadao/NICCifrado': user_nic = child.find('assertion:AttributeValue', ns).text elif child.attrib[ 'Name'] == 'http://interop.gov.pt/MDC/Cidadao/NomeProprio': first_name = child.find('assertion:AttributeValue', ns).text elif child.attrib[ 'Name'] == 'http://interop.gov.pt/MDC/Cidadao/NomeApelido': last_name = child.find('assertion:AttributeValue', ns).text else: pass except AttributeError: pass data = {'email': user_email} extras = {'extras': {'auth_nic': user_nic}} userUdata = datastore.find_user(**extras) or datastore.find_user(**data) if not userUdata: # Redirects to new custom registration form session['user_email'] = user_email session['user_nic'] = user_nic session['first_name'] = first_name session['last_name'] = last_name return redirect(url_for('saml.register')) elif requires_confirmation(userUdata): do_flash(*get_message('CONFIRMATION_REQUIRED')) return redirect(url_for('security.login')) elif userUdata.deleted: do_flash(*get_message('DISABLED_ACCOUNT')) return redirect(url_for('site.home')) else: login_user(userUdata) session['saml_login'] = True # do_flash(*get_message('PASSWORDLESS_LOGIN_SUCCESSFUL')) return redirect(url_for('site.home'))
def accounts(): """ Register an account The method is available to apps with a token obtained via the client credentials grant. It creates a user and account records, as well as an access token for the app that initiated the request. The method returns the access token, which the app should save for later. --- tags: - Accounts definitions: Token: type: object properties: access_token: type: string token_type: type: string scope: type: string created_at: type: integer responses: 200: description: Returns Token schema: $ref: '#/definitions/Token' """ if not current_app.config["REGISTRATION_ENABLED"]: abort(403) errors = {} # Get the bearer token bearer = None if "Authorization" in request.headers: b = request.headers.get("Authorization") b = b.strip().split(" ") if len(b) == 2: bearer = b[1] else: errors["bearer"] = ["API Bearer Authorization format issue"] else: current_app.logger.info( "/api/v1/accounts: no Authorization bearer given") if not request.json: abort(400) if "nickname" not in request.json: errors["nickname"] = ["nickname is missing"] if "email" not in request.json: errors["email"] = ["email is missing"] if "fullname" not in request.json: errors["fullname"] = ["fullname is missing"] if "password" not in request.json: errors["password"] = ["password is missing"] if "confirm" not in request.json: errors["confirm"] = ["password confirm is missing"] if "agreement" not in request.json: errors["agreement"] = ["agreement is missing"] if len(errors) > 0: return jsonify({"error": str(errors)}), 400 if forbidden_username(request.json["nickname"]): return jsonify( {"error": str({"nickname": ["this username cannot be used"]})}), 400 if request.json["password"] != request.json["confirm"]: return jsonify( {"error": str({"confirm": ["passwords doesn't match"]})}), 400 if "agreement" not in request.json: return jsonify({ "error": str({"agreement": ["you need to accept the terms and conditions"]}) }), 400 # Check if user already exists by local user username user = User.query.filter(User.name == request.json["username"]).first() if user: return jsonify({"error": str({"ap_id": ["has already been taken"]})}), 400 # Check if user already exists by old local user (Actors) user = Actor.query.filter( Actor.preferred_username == request.json["username"]).first() if user: return jsonify({"error": str({"ap_id": ["has already been taken"]})}), 400 # Check if user already exists by email user = User.query.filter(User.email == request.json["email"]).first() if user: return jsonify({"error": str({"email": ["has already been taken"]})}), 400 # Check username is valid # /^[a-zA-Z\d]+$/ if not username_is_legal.match(request.json["username"]): return jsonify({ "error": str({"ap_id": ["should contains only letters and numbers"]}) }), 400 # Proceed to register the user role = Role.query.filter(Role.name == "user").first() if not role: return jsonify({"error": "server error"}), 500 u = user_datastore.create_user( name=request.json["username"], email=request.json["email"], display_name=request.json["fullname"], password=hash_password(request.json["password"]), roles=[role], ) actor = create_actor(u) actor.user = u actor.user_id = u.id if "bio" in request.json: actor.summary = request.json["bio"] db.session.add(actor) db.session.commit() if FSConfirmable.requires_confirmation(u): FSConfirmable.send_confirmation_instructions(u) # get the matching item from the given bearer bearer_item = OAuth2Token.query.filter( OAuth2Token.access_token == bearer).first() if not bearer_item: abort(400) client_item = OAuth2Client.query.filter( OAuth2Client.client_id == bearer_item.client_id).first() if not client_item: abort(400) # https://github.com/lepture/authlib/blob/master/authlib/oauth2/rfc6749/grants/base.py#L51 token = authorization.generate_token(client_item.client_id, "client_credentials", user=u, scope=client_item.scope, expires_in=None) tok = OAuth2Token() tok.user_id = u.id tok.client_id = client_item.client_id # the frontend should request an app every time it doesn't have one in local storage # and this app should allow delivering a somewhat non usuable Token # token which gets sent to this endpoint and gets used to get back the right client_id # to associate in the database... tok.token_type = token["token_type"] tok.access_token = token["access_token"] tok.refresh_token = None tok.scope = token["scope"] tok.revoked = False tok.expires_in = token["expires_in"] db.session.add(tok) db.session.commit() return jsonify({**token, "created_at": tok.issued_at}), 200