def setup_user(email, groups=None, default_role='View'): from security_monkey import app, db user = User.query.filter(User.email == email).first() if user: return user role = default_role groups = groups or [] if groups: if app.config.get('ADMIN_GROUP') and app.config.get( 'ADMIN_GROUP') in groups: role = 'Admin' elif app.config.get('JUSTIFY_GROUP') and app.config.get( 'JUSTIFY_GROUP') in groups: role = 'Justify' elif app.config.get('VIEW_GROUP') and app.config.get( 'VIEW_GROUP') in groups: role = 'View' # if we get an sso user create them an account user = User(email=email, active=True, role=role) db.session.add(user) db.session.commit() db.session.refresh(user) return user
def post(self): if "onelogin" not in current_app.config.get("ACTIVE_PROVIDERS"): return "Onelogin is not enabled in the config. See the ACTIVE_PROVIDERS section.", 404 auth = OneLogin_Saml2_Auth(self.req, current_app.config.get("ONELOGIN_SETTINGS")) self.reqparse.add_argument('return_to', required=False, default=current_app.config.get('WEB_PATH')) self.reqparse.add_argument('acs', required=False) self.reqparse.add_argument('sls', required=False) args = self.reqparse.parse_args() return_to = args['return_to'] if args['acs'] != None: # valids the SAML response and checks if successfully authenticated if self._consumer(auth): email = auth.get_attribute( current_app.config.get("ONELOGIN_EMAIL_FIELD"))[0] user = User.query.filter(User.email == email).first() # if we get an sso user create them an account if not user: user = User( email=email, active=True, role=current_app.config.get('ONELOGIN_DEFAULT_ROLE') # profile_picture=profile.get('thumbnailPhotoUrl') ) db.session.add(user) db.session.commit() db.session.refresh(user) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) login_user(user) db.session.commit() db.session.refresh(user) self_url = OneLogin_Saml2_Utils.get_self_url(self.req) if 'RelayState' in request.form and self_url != request.form[ 'RelayState']: return redirect(auth.redirect_to( request.form['RelayState']), code=302) else: return redirect(current_app.config.get('BASE_URL'), code=302) else: return dict(message='OneLogin authentication failed.'), 403 elif args['sls'] != None: return dict(message='OneLogin SLS not implemented yet.'), 405 else: return redirect(auth.login(return_to=return_to))
def test_toggle_active_user(self): test_user = User(email='*****@*****.**') test_user.role = 'View' test_user.active = False db.session.add(test_user) db.session.commit() manager.handle('manage.py', [ 'toggle_active_user', '--email', '*****@*****.**', '--active', 'True' ]) assert User.query.filter( User.email == '*****@*****.**').first().active manager.handle('manage.py', ['toggle_active_user', '--email', '*****@*****.**']) assert not User.query.filter( User.email == '*****@*****.**').first().active with pytest.raises(SystemExit): manager.handle('manage.py', ['toggle_active_user', '--email', 'notauser'])
def load_user(email): """ For Flask-Login, returns the user object given the userid. :return: security_monkey.datastore.User object """ app.logger.info("Inside load_user!") user = User.query.filter(User.email == email).first() if not user: user = User(email=email) db.session.add(user) db.session.commit() db.session.close() user = User.query.filter(User.email == email).first() return user
def test_create_user(self): existing_user = User(email='*****@*****.**', active=True, role='View') db.session.add(existing_user) db.session.commit() db.session.refresh(existing_user) user1 = setup_user('*****@*****.**') self.assertEqual(existing_user.id, user1.id) self.assertEqual(existing_user.role, user1.role) user2 = setup_user('*****@*****.**') self.assertEqual(user2.email, '*****@*****.**') self.assertEqual(user2.role, 'View') self.app.config.update(ADMIN_GROUP='test_admin_group', JUSTIFY_GROUP='test_justify_group', VIEW_GROUP='test_view_group') admin_user = setup_user('*****@*****.**', ['test_admin_group']) justify_user = setup_user('*****@*****.**', ['test_justify_group']) view_user = setup_user('*****@*****.**', ['test_view_group']) self.assertEqual(admin_user.role, 'Admin') self.assertEqual(justify_user.role, 'Justify') self.assertEqual(view_user.role, 'View')
def post(self): if "ping" not in current_app.config.get("ACTIVE_PROVIDERS"): return "Ping is not enabled in the config. See the ACTIVE_PROVIDERS section.", 404 default_state = 'clientId,{client_id},redirectUri,{redirectUri},return_to,{return_to}'.format( client_id=current_app.config.get('PING_CLIENT_ID'), redirectUri=current_app.config.get('PING_REDIRECT_URI'), return_to=current_app.config.get('WEB_PATH')) self.reqparse.add_argument('code', type=str, required=True) self.reqparse.add_argument('state', type=str, required=False, default=default_state) args = self.reqparse.parse_args() client_id = args['state'].split(',')[1] redirect_uri = args['state'].split(',')[3] return_to = args['state'].split(',')[5] if not validate_redirect_url(return_to): return_to = current_app.config.get('WEB_PATH') # take the information we have received from the provider to create a new request params = { 'client_id': client_id, 'grant_type': 'authorization_code', 'scope': 'openid email profile address', 'redirect_uri': redirect_uri, 'code': args['code'] } # you can either discover these dynamically or simply configure them access_token_url = current_app.config.get('PING_ACCESS_TOKEN_URL') user_api_url = current_app.config.get('PING_USER_API_URL') # the secret and cliendId will be given to you when you signup for the provider basic = base64.b64encode( bytes('{0}:{1}'.format(client_id, current_app.config.get("PING_SECRET")))) headers = {'Authorization': 'Basic {0}'.format(basic.decode('utf-8'))} # exchange authorization code for access token. r = requests.post(access_token_url, headers=headers, params=params) id_token = r.json()['id_token'] access_token = r.json()['access_token'] # fetch token public key header_data = fetch_token_header_payload(id_token)[0] jwks_url = current_app.config.get('PING_JWKS_URL') # retrieve the key material as specified by the token header r = requests.get(jwks_url) for key in r.json()['keys']: if key['kid'] == header_data['kid']: secret = get_rsa_public_key(key['n'], key['e']) algo = header_data['alg'] break else: return dict(message='Key not found'), 403 # validate your token based on the key it was signed with try: current_app.logger.debug(id_token) current_app.logger.debug(secret) current_app.logger.debug(algo) jwt.decode(id_token, secret.decode('utf-8'), algorithms=[algo], audience=client_id) except jwt.DecodeError: return dict(message='Token is invalid'), 403 except jwt.ExpiredSignatureError: return dict(message='Token has expired'), 403 except jwt.InvalidTokenError: return dict(message='Token is invalid'), 403 user_params = dict(access_token=access_token, schema='profile') # retrieve information about the current user. r = requests.get(user_api_url, params=user_params) profile = r.json() user = User.query.filter(User.email == profile['email']).first() # if we get an sso user create them an account if not user: user = User(email=profile['email'], active=True, role='View' # profile_picture=profile.get('thumbnailPhotoUrl') ) db.session.add(user) db.session.commit() db.session.refresh(user) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) login_user(user) return redirect(return_to, code=302)
def post(self): if "google" not in current_app.config.get("ACTIVE_PROVIDERS"): return "Google is not enabled in the config. See the ACTIVE_PROVIDERS section.", 404 default_state = 'clientId,{client_id},redirectUri,{redirectUri},return_to,{return_to}'.format( client_id=current_app.config.get("GOOGLE_CLIENT_ID"), redirectUri=api.url_for(Google), return_to=current_app.config.get('WEB_PATH')) self.reqparse.add_argument('code', type=str, required=True) self.reqparse.add_argument('state', type=str, required=False, default=default_state) args = self.reqparse.parse_args() client_id = args['state'].split(',')[1] redirect_uri = args['state'].split(',')[3] return_to = args['state'].split(',')[5] if not validate_redirect_url(return_to): return_to = current_app.config.get('WEB_PATH') access_token_url = 'https://accounts.google.com/o/oauth2/token' people_api_url = 'https://www.googleapis.com/plus/v1/people/me/openIdConnect' args = self.reqparse.parse_args() # Step 1. Exchange authorization code for access token payload = { 'client_id': client_id, 'grant_type': 'authorization_code', 'redirect_uri': redirect_uri, 'code': args['code'], 'client_secret': current_app.config.get('GOOGLE_SECRET') } r = requests.post(access_token_url, data=payload) token = r.json() # Step 1bis. Validate (some information of) the id token (if necessary) google_hosted_domain = current_app.config.get("GOOGLE_HOSTED_DOMAIN") if google_hosted_domain is not None: current_app.logger.debug( 'We need to verify that the token was issued for this hosted domain: %s ' % (google_hosted_domain)) # Get the JSON Web Token id_token = r.json()['id_token'] current_app.logger.debug('The id_token is: %s' % (id_token)) # Extract the payload (header_data, payload_data) = fetch_token_header_payload(id_token) current_app.logger.debug('id_token.header_data: %s' % (header_data)) current_app.logger.debug('id_token.payload_data: %s' % (payload_data)) token_hd = payload_data.get('hd') if token_hd != google_hosted_domain: current_app.logger.debug('Verification failed: %s != %s' % (token_hd, google_hosted_domain)) return dict(message='Token is invalid %s' % token), 403 current_app.logger.debug('Verification passed') # Step 2. Retrieve information about the current user headers = {'Authorization': 'Bearer {0}'.format(token['access_token'])} r = requests.get(people_api_url, headers=headers) profile = r.json() user = User.query.filter(User.email == profile['email']).first() # if we get an sso user create them an account if not user: user = User(email=profile['email'], active=True, role='View' # profile_picture=profile.get('thumbnailPhotoUrl') ) db.session.add(user) db.session.commit() db.session.refresh(user) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) login_user(user) return redirect(return_to, code=302)
def post(self): if "google" not in current_app.config.get("ACTIVE_PROVIDERS"): return "Google is not enabled in the config. See the ACTIVE_PROVIDERS section.", 404 default_state = 'clientId,{client_id},redirectUri,{redirectUri},return_to,{return_to}'.format( client_id=current_app.config.get("GOOGLE_CLIENT_ID"), redirectUri=api.url_for(Google), return_to=current_app.config.get('WEB_PATH') ) self.reqparse.add_argument('code', type=str, required=True) self.reqparse.add_argument('state', type=str, required=False, default=default_state) args = self.reqparse.parse_args() client_id = args['state'].split(',')[1] redirect_uri = args['state'].split(',')[3] return_to = args['state'].split(',')[5] if not validate_redirect_url(return_to): return_to = current_app.config.get('WEB_PATH') access_token_url = 'https://accounts.google.com/o/oauth2/token' people_api_url = 'https://www.googleapis.com/plus/v1/people/me/openIdConnect' args = self.reqparse.parse_args() # Step 1. Exchange authorization code for access token payload = { 'client_id': client_id, 'grant_type': 'authorization_code', 'redirect_uri': redirect_uri, 'code': args['code'], 'client_secret': current_app.config.get('GOOGLE_SECRET') } r = requests.post(access_token_url, data=payload) token = r.json() # Step 2. Retrieve information about the current user headers = {'Authorization': 'Bearer {0}'.format(token['access_token'])} r = requests.get(people_api_url, headers=headers) profile = r.json() user = User.query.filter(User.email == profile['email']).first() # if we get an sso user create them an account if not user: user = User( email=profile['email'], active=True, role='View' # profile_picture=profile.get('thumbnailPhotoUrl') ) db.session.add(user) db.session.commit() db.session.refresh(user) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) login_user(user) return redirect(return_to, code=302)