Exemple #1
0
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
Exemple #2
0
    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))
Exemple #3
0
    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'])
Exemple #4
0
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
Exemple #5
0
    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')
Exemple #6
0
    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)
Exemple #7
0
    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)
Exemple #8
0
    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)