How to use pyoicd with multiple blueprints
Closed this issue · 5 comments
My Flask project is growing and I want to split my major blueprint up into smaller components.
Is it possible to use pyoidc for this?
When I register multiple blueprints, an exception occurs immediately:
File "C:\Users\az27355\Miniconda3\envs\backoffice_nova\lib\site-packages\flask\app.py", line 1283, in add_url_rule
"existing endpoint function: %s" % endpoint
AssertionError: View function mapping is overwriting an existing endpoint function: redirect_uri
# init.py
[...]
app = Flask(__name__, instance_relative_config=False)
with app.app_context():
from .main import main_routes, sub_routes, kmd_nova_routes # import routes after initializing db object
app.register_blueprint(main_routes.main_bp)
app.register_blueprint(sub_routes.sub_bp)
app.register_blueprint(kmd_nova_routes.nova_bp)
return app
# in each blueprint
[...]
auth = OIDCAuthentication({PROVIDER_NAME1: PROVIDER_CONFIG})
auth.init_app(current_app)
[...]
It should be possible. But only one OIDCAuthentication
instance and and one call auth.init_app
should be made, i.e. it shouldn't be done in each blueprint.
See for example #81 for one way to structure it.
I was looking at #81 but I didn't understand it, and in the last post by OP (esune) it sounds like he abandoned the issue.
So I made this minimal, reproducible example:
https://github.com/andanders/pyoidc_blueprints
However is it sane? Is it safe? Is it close enough to best practices?
You can clone, fill config.py and run.
Additional questions:
- As you can see in the configuration I'm using
SERVER_NAME
instad ofOIDC_REDIRECT_URI
simply because I couldn't get the latter to work. - In
__init__.py
I wonder if it is better to do
auth.init_app(app)
app.auth = auth
inside or outside with app.app_context():
. Functionally it seems to do the same.
Unfortunately I don't have time right now to check your example in detail, but I did take a quick look: the code looks reasonable to me, and if it works after your testing I'd say it's safe. 🙂
For your additional questions:
- What problem did you encounter when using
OIDC_REDIRECT_URI
? Any error message, stacktrace, etc.? It expects a different value thanSERVER_NAME
, namely the full URL for the endpoint to be used, see the example app. OIDCAuthentication.init_app
shouldn't be necessary to run withinapp.app_context()
so can run it outside of it.
I figured out the problem with OIDC_REDIRECT_URI
: I was using an incorrect URL.
It works with OIDC_REDIRECT_URI = 'http://localhost:5000/redirect_uri'
I also had to delete the SERVER_NAME
.
however I get an Internal Server Error in my production environment when I log out:
App constructed with Arg 'env' = 'None'
[2020-09-15 13:15:47,518] ERROR in app: Exception on /logout [GET]
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/usr/local/lib/python3.7/site-packages/flask_pyoidc/flask_pyoidc.py", line 242, in wrapper
if flask.request.args['state'] != flask.session.pop('end_session_state'):
File "/usr/local/lib/python3.7/site-packages/werkzeug/datastructures.py", line 269, in pop
rv = super(UpdateDictMixin, self).pop(key)
KeyError: 'end_session_state'
Great that you got the redirect URI part working!
Your new error seems unrelated to this issue, so could you please create a new issue for it? 🙂
And please include all details you have about it - does the error always happen, how does your final config look like, etc.