def save_token(token_data, request, *args, **kwargs): # For the implicit flow # Check issue: https://github.com/lepture/flask-oauthlib/issues/209 if request.grant_type == 'authorization_code': user = request.user elif request.grant_type is None: # implicit flow user = session.user else: raise ValueError('Invalid grant_type') requested_scopes = set(token_data['scope'].split()) token = OAuthToken.find_first(OAuthApplication.client_id == request.client.client_id, OAuthToken.user == user, _join=OAuthApplication) if token is None: application = OAuthApplication.find_one(client_id=request.client.client_id) token = OAuthToken(application=application, user=user) db.session.add(token) token.access_token = token_data['access_token'] token.scopes = requested_scopes elif requested_scopes - token.scopes: logger.info('Added scopes to {}: {}'.format(token, requested_scopes - token.scopes)) # use the new access_token when extending scopes token.access_token = token_data['access_token'] token.scopes |= requested_scopes else: token_data['access_token'] = token.access_token token_data.pop('refresh_token', None) # we don't support refresh tokens so far token_data.pop('expires_in', None) # our tokens currently do not expire return token
def test_save_token_no_application(dummy_application, dummy_request, token_data): dummy_request.client.client_id = str(uuid4()) assert not OAuthApplication.find( client_id=dummy_request.client.client_id).count() with pytest.raises(NoResultFound): save_token(token_data, dummy_request)
def create_all_tables(db, verbose=False, add_initial_data=True): """Create all tables and required initial objects.""" from indico.modules.categories import Category from indico.modules.designer import TemplateType from indico.modules.designer.models.templates import DesignerTemplate from indico.modules.oauth.models.applications import OAuthApplication, SystemAppType from indico.modules.users import User if verbose: print(cformat('%{green}Creating tables')) db.create_all() if add_initial_data: if verbose: print(cformat('%{green}Creating system user')) db.session.add(User(id=0, is_system=True, first_name='Indico', last_name='System')) if verbose: print(cformat('%{green}Creating root category')) cat = Category(id=0, title='Home', protection_mode=ProtectionMode.public) db.session.add(cat) db.session.flush() if verbose: print(cformat('%{green}Creating default ticket template for root category ')) dtt = DesignerTemplate(category_id=0, title='Default ticket', type=TemplateType.badge, data=DEFAULT_TICKET_DATA, is_system_template=True) dbt = DesignerTemplate(category_id=0, title='Default badge', type=TemplateType.badge, data=DEFAULT_BADGE_DATA, is_system_template=True) cat.default_ticket_template = dtt cat.default_badge_template = dbt db.session.add(dtt) db.session.add(dbt) if verbose: print(cformat('%{green}Creating system oauth apps')) for sat in SystemAppType: if sat != SystemAppType.none: db.session.add(OAuthApplication(system_app_type=sat, **sat.default_data)) db.session.commit()
def _process(self): config = Config.getInstance() # QRCode (Version 6 with error correction L can contain up to 106 bytes) qr = qrcode.QRCode(version=6, error_correction=qrcode.constants.ERROR_CORRECT_M, box_size=4, border=1) checkin_app_client_id = config.getCheckinAppClientId() checkin_app = OAuthApplication.find_first( client_id=checkin_app_client_id) qr_data = { "event_id": self.event_new.id, "title": self.event_new.title, "date": format_date(self.event_new.start_dt_local ), # XXX: switch to utc+isoformat? "server": { "baseUrl": config.getBaseURL(), "consumerKey": checkin_app.client_id, "auth_url": url_for('oauth.oauth_authorize', _external=True), "token_url": url_for('oauth.oauth_token', _external=True) } } json_qr_data = json.dumps(qr_data) qr.add_data(json_qr_data) qr.make(fit=True) qr_img = qr.make_image() output = BytesIO() qr_img.save(output) output.seek(0) return send_file('config.png', output, 'image/png')
def save_token(token_data, request, *args, **kwargs): # For the implicit flow # Check issue: https://github.com/lepture/flask-oauthlib/issues/209 if request.grant_type == 'authorization_code': user = request.user elif request.grant_type is None: # implicit flow user = session.user else: raise ValueError('Invalid grant_type') requested_scopes = set(token_data['scope'].split()) token = OAuthToken.find_first( OAuthApplication.client_id == request.client.client_id, OAuthToken.user == user, _join=OAuthApplication) if token is None: application = OAuthApplication.find_one( client_id=request.client.client_id) token = OAuthToken(application=application, user=user) db.session.add(token) token.access_token = token_data['access_token'] token.scopes = requested_scopes elif requested_scopes - token.scopes: logger.info('Added scopes to %s: %s', token, requested_scopes - token.scopes) # use the new access_token when extending scopes token.access_token = token_data['access_token'] token.scopes |= requested_scopes else: token_data['access_token'] = token.access_token token_data.pop('refresh_token', None) # we don't support refresh tokens so far token_data.pop('expires_in', None) # our tokens currently do not expire return token
def _process(self): # QRCode (Version 6 with error correction L can contain up to 106 bytes) qr = qrcode.QRCode( version=6, error_correction=qrcode.constants.ERROR_CORRECT_M, box_size=4, border=1 ) checkin_app = OAuthApplication.find_one(system_app_type=SystemAppType.checkin) qr_data = { "event_id": self.event.id, "title": self.event.title, "date": self.event.start_dt.isoformat(), "version": 1, "server": { "base_url": config.BASE_URL, "consumer_key": checkin_app.client_id, "auth_url": url_for('oauth.oauth_authorize', _external=True), "token_url": url_for('oauth.oauth_token', _external=True) } } json_qr_data = json.dumps(qr_data) qr.add_data(json_qr_data) qr.make(fit=True) qr_img = qr.make_image() output = BytesIO() qr_img.save(output) output.seek(0) return send_file('config.png', output, 'image/png')
def _process_args(self): try: UUID(hex=request.args['client_id']) except ValueError: raise NoResultFound self.application = OAuthApplication.find_one( client_id=request.args['client_id'])
def celery_cmd(args): # remove the celery shell command next(funcs for group, funcs, _ in command_classes if group == 'Main').remove('shell') del CeleryCommand.commands['shell'] if args and args[0] == 'flower': # Somehow flower hangs when executing it using CeleryCommand() so we simply exec it directly. # It doesn't really need the celery config anyway (besides the broker url) try: import flower # noqa: F401 except ImportError: print(cformat('%{red!}Flower is not installed')) sys.exit(1) app = OAuthApplication.find_one(system_app_type=SystemAppType.flower) if not app.redirect_uris: print( cformat( '%{yellow!}Authentication will fail unless you configure the redirect url for the {} OAuth ' 'application in the administration area.').format( app.name)) print( cformat('%{green!}Only Indico admins will have access to flower.')) print( cformat( '%{yellow}Note that revoking admin privileges will not revoke Flower access.' )) print(cformat('%{yellow}To force re-authentication, restart Flower.')) auth_args = [ '--auth=^Indico Admin$', '--auth_provider=indico.core.celery.flower.FlowerAuthHandler' ] auth_env = { 'INDICO_FLOWER_CLIENT_ID': app.client_id, 'INDICO_FLOWER_CLIENT_SECRET': app.client_secret, 'INDICO_FLOWER_AUTHORIZE_URL': url_for('oauth.oauth_authorize', _external=True), 'INDICO_FLOWER_TOKEN_URL': url_for('oauth.oauth_token', _external=True), 'INDICO_FLOWER_USER_URL': url_for('users.authenticated_user', _external=True) } if config.FLOWER_URL: auth_env['INDICO_FLOWER_URL'] = config.FLOWER_URL args = ['celery', '-b', config.CELERY_BROKER] + args + auth_args env = dict(os.environ, **auth_env) os.execvpe('celery', args, env) elif args and args[0] == 'shell': print(cformat('%{red!}Please use `indico shell`.')) sys.exit(1) else: CeleryCommand(celery).execute_from_commandline(['indico celery'] + args)
def load_client(client_id): try: UUID(hex=client_id) except ValueError: raise InvalidClientIdError app = OAuthApplication.find_first(client_id=client_id) if not app.is_enabled: raise DisabledClientIdError return app
def validate_name(self, field): query = OAuthApplication.find(name=field.data) if self.application: query = query.filter( db.func.lower(OAuthApplication.name) != self.application.name.lower()) if query.count(): raise ValidationError( _("There is already an application with this name"))
def _create_application(name, **params): params.setdefault('client_id', unicode(uuid4())) params.setdefault('default_scopes', 'read:user') params.setdefault('redirect_uris', 'http://localhost:10500') params.setdefault('is_trusted', True) application = OAuthApplication(name=name, **params) db.session.add(application) db.session.flush() return application
def _process(self): form = ApplicationForm(obj=FormDefaults(is_enabled=True)) if form.validate_on_submit(): application = OAuthApplication() form.populate_obj(application) db.session.add(application) db.session.flush() logger.info("Application %s created by %s", application, session.user) flash(_("Application {} registered successfully").format(application.name), 'success') return redirect(url_for('.app_details', application)) return WPOAuthAdmin.render_template('app_new.html', form=form)
def _check_ticket_app_enabled(self): config = Config.getInstance() checkin_app_client_id = config.getCheckinAppClientId() if checkin_app_client_id is None: flash(_("indico-checkin client_id is not defined in the Indico configuration"), 'warning') return False checkin_app = OAuthApplication.find_first(client_id=checkin_app_client_id) if checkin_app is None: flash(_("indico-checkin is not registered as an OAuth application with client_id {}") .format(checkin_app_client_id), 'warning') return False return True
def run(self, args): # disable the zodb commit hook update_session_options(db) # remove the celery shell command next(funcs for group, funcs, _ in command_classes if group == 'Main').remove('shell') del CeleryCommand.commands['shell'] if args and args[0] == 'flower': # Somehow flower hangs when executing it using CeleryCommand() so we simply exec it directly. # It doesn't really need the celery config anyway (besides the broker url) try: import flower except ImportError: print cformat('%{red!}Flower is not installed') sys.exit(1) client_id = Config.getInstance().getFlowerClientId() if client_id: app = OAuthApplication.find_first(client_id=client_id) if app is None: print cformat('%{red!}There is no OAuth application with the client id {}.').format(client_id) sys.exit(1) elif 'read:user' not in app.default_scopes: print cformat('%{red!}The {} application needs the read:user scope.').format(app.name) sys.exit(1) print cformat('%{green!}Only Indico admins will have access to flower.') print cformat('%{yellow}Note that revoking admin privileges will not revoke Flower access.') print cformat('%{yellow}To force re-authentication, restart Flower.') auth_args = ['--auth=^Indico Admin$', '--auth_provider=indico.core.celery.flower.FlowerAuthHandler'] auth_env = {'INDICO_FLOWER_CLIENT_ID': app.client_id, 'INDICO_FLOWER_CLIENT_SECRET': app.client_secret, 'INDICO_FLOWER_AUTHORIZE_URL': url_for('oauth.oauth_authorize', _external=True), 'INDICO_FLOWER_TOKEN_URL': url_for('oauth.oauth_token', _external=True), 'INDICO_FLOWER_USER_URL': url_for('users.authenticated_user', _external=True)} else: print cformat('%{red!}WARNING: %{yellow!}Flower authentication is disabled.') print cformat('%{yellow!}Having access to Flower allows one to shutdown Celery workers.') print auth_args = [] auth_env = {} args = ['celery', '-b', Config.getInstance().getCeleryBroker()] + args + auth_args env = dict(os.environ, **auth_env) os.execvpe('celery', args, env) elif args and args[0] == 'shell': print cformat('%{red!}Please use `indico shell`.') sys.exit(1) else: CeleryCommand(celery).execute_from_commandline(['indico celery'] + args)
def celery_cmd(args): # remove the celery shell command next(funcs for group, funcs, _ in command_classes if group == 'Main').remove('shell') del CeleryCommand.commands['shell'] if args and args[0] == 'flower': # Somehow flower hangs when executing it using CeleryCommand() so we simply exec it directly. # It doesn't really need the celery config anyway (besides the broker url) try: import flower except ImportError: print cformat('%{red!}Flower is not installed') sys.exit(1) app = OAuthApplication.find_one(system_app_type=SystemAppType.flower) if not app.redirect_uris: print cformat('%{yellow!}Authentication will fail unless you configure the redirect url for the {} OAuth ' 'application in the administration area.').format(app.name) print cformat('%{green!}Only Indico admins will have access to flower.') print cformat('%{yellow}Note that revoking admin privileges will not revoke Flower access.') print cformat('%{yellow}To force re-authentication, restart Flower.') auth_args = ['--auth=^Indico Admin$', '--auth_provider=indico.core.celery.flower.FlowerAuthHandler'] auth_env = {'INDICO_FLOWER_CLIENT_ID': app.client_id, 'INDICO_FLOWER_CLIENT_SECRET': app.client_secret, 'INDICO_FLOWER_AUTHORIZE_URL': url_for('oauth.oauth_authorize', _external=True), 'INDICO_FLOWER_TOKEN_URL': url_for('oauth.oauth_token', _external=True), 'INDICO_FLOWER_USER_URL': url_for('users.authenticated_user', _external=True)} if config.FLOWER_URL: auth_env['INDICO_FLOWER_URL'] = config.FLOWER_URL args = ['celery', '-b', config.CELERY_BROKER] + args + auth_args env = dict(os.environ, **auth_env) os.execvpe('celery', args, env) elif args and args[0] == 'shell': print cformat('%{red!}Please use `indico shell`.') sys.exit(1) else: CeleryCommand(celery).execute_from_commandline(['indico celery'] + args)
def _getAnswer(self): config = Config.getInstance() checkin_app_client_id = config.getCheckinAppClientId() if checkin_app_client_id is None: raise NoReportError(_("indico-checkin client_id is not defined in the Indico configuration")) checkin_app = OAuthApplication.find_first(client_id=checkin_app_client_id) if checkin_app is None: raise NoReportError( _("indico-checkin is not registered as an OAuth application with client_id {}").format( checkin_app_client_id ) ) # QRCode (Version 6 with error correction L can contain up to 106 bytes) qr = QRCode(version=6, error_correction=constants.ERROR_CORRECT_M, box_size=4, border=1) baseURL = config.getBaseSecureURL() if config.getBaseSecureURL() else config.getBaseURL() qr_data = { "event_id": self._conf.getId(), "title": self._conf.getTitle(), "date": format_date(self._conf.getAdjustedStartDate()), "server": { "baseUrl": baseURL, "consumerKey": checkin_app.client_id, "auth_url": url_for("oauth.oauth_authorize", _external=True), "token_url": url_for("oauth.oauth_token", _external=True), }, } json_qr_data = json.dumps(qr_data) qr.add_data(json_qr_data) qr.make(fit=True) qr_img = qr.make_image() output = StringIO() qr_img._img.save(output, format="png") im_data = output.getvalue() return "data:image/png;base64,{0}".format(base64.b64encode(im_data))
def _process(self): config = Config.getInstance() # QRCode (Version 6 with error correction L can contain up to 106 bytes) qr = qrcode.QRCode( version=6, error_correction=qrcode.constants.ERROR_CORRECT_M, box_size=4, border=1 ) checkin_app_client_id = config.getCheckinAppClientId() checkin_app = OAuthApplication.find_first(client_id=checkin_app_client_id) base_url = config.getBaseSecureURL() if config.getBaseSecureURL() else config.getBaseURL() qr_data = { "event_id": self._conf.getId(), "title": self._conf.getTitle(), "date": format_date(self._conf.getAdjustedStartDate()), "server": { "baseUrl": base_url, "consumerKey": checkin_app.client_id, "auth_url": url_for('oauth.oauth_authorize', _external=True), "token_url": url_for('oauth.oauth_token', _external=True) } } json_qr_data = json.dumps(qr_data) qr.add_data(json_qr_data) qr.make(fit=True) qr_img = qr.make_image() output = BytesIO() qr_img.save(output) output.seek(0) return send_file('config.png', output, 'image/png')
def validate_name(self, field): query = OAuthApplication.find(name=field.data) if self.application: query = query.filter(db.func.lower(OAuthApplication.name) != self.application.name.lower()) if query.count(): raise ValidationError(_("There is already an application with this name"))
def _process(self): applications = OAuthApplication.find().order_by( db.func.lower(OAuthApplication.name)).all() return WPOAuthAdmin.render_template('apps.html', applications=applications)
def _checkParams(self): self.application = OAuthApplication.get(request.view_args['id'])
def _process_args(self): self.application = OAuthApplication.get(request.view_args['id'])
def _create_oauth_apps(): for sat in SystemAppType: if sat != SystemAppType.none: db.session.add( OAuthApplication(system_app_type=sat, **sat.default_data)) db.session.commit()
def test_save_token_no_application(dummy_application, dummy_request, token_data): dummy_request.client.client_id = unicode(uuid4()) assert not OAuthApplication.find(client_id=dummy_request.client.client_id).count() with pytest.raises(NoResultFound): save_token(token_data, dummy_request)
def _process(self): applications = OAuthApplication.find().order_by(db.func.lower(OAuthApplication.name)).all() return WPOAuthAdmin.render_template('apps.html', applications=applications)
def _checkParams(self): try: UUID(hex=request.args['client_id']) except ValueError: raise NoResultFound self.application = OAuthApplication.find_one(client_id=request.args['client_id'])