puiterwijk / flask-oidc Goto Github PK
View Code? Open in Web Editor NEWOpenID Connect support for Flask
License: BSD 2-Clause "Simplified" License
OpenID Connect support for Flask
License: BSD 2-Clause "Simplified" License
The documentation and the code examples direct me to write:
from flask.ext.oidc import OpenIDConnect
With flask-oidc == 1.4.0 this will produce the error ModuleNotFoundError: No module named 'flask.ext'
It appears one needs to write
from flask_oidc import OpenIDConnect
instead.
Please let me emphasize that as a newbie to python-flask and oidc it is especially frustrating to have introducing tutorial code giving errors like this :P
Illegal character in query at index 42: http://localhost:5000/oidc_callback?state={"csrf_token": "OaYJMU9HSJVpZyJoJMcXCtwgQAG2xxx/", "destination": "eyJhbGciOiJIUzxxx.Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9wcml2YXRlIg.hjUDDvxxxEZpV5ILsdNvealTfdDUgoYPflpxxxupMRQ"}
The method redirect_to_auth_server
where it does extra_params=urlencode(extra_params)
, is not working as expected.
Could there be option to configure the use of the userinfo_uri or not to use it?
CoreOS OpenId Connect Provider (https://github.com/coreos/dex) didn't implement the userinfo endpoint because it's optional.
In order to get this library to work with coreos openId connect provider, I had to comment out lines 188 thru 199
(https://github.com/puiterwijk/flask-oidc/blob/master/flask_oidc/__init__.py#L188-L199) for it to work with coreos openid connect provider.
I'm using the library against keycloak for authentication to secure the REST API endpoints. If a user accesses one of many REST API endpoints, he is redirected to the keycloak page. Following are the settings, of which only OVERWRITE_REDIRECT_URI matters for this issue:
app.config.update({ 'SECRET_KEY': 'keycloak client secret key', 'TESTING': True, 'DEBUG': True, 'OIDC_CLIENT_SECRETS': resource_filename(__name__, 'client_secrets.json'), 'OIDC_ID_TOKEN_COOKIE_SECURE': False, 'OIDC_REQUIRE_VERIFIED_EMAIL': False, 'OIDC_OPENID_REALM': '<realm name>', 'OIDC_INTROSPECTION_AUTH_METHOD': 'client_secret_post', 'OIDC_TOKEN_TYPE_HINT': 'access_token', 'OVERWRITE_REDIRECT_URI': 'http://myappp:8000' })
oidc.init_app(app)
If I access an endpoint such as https://myapp:8000/api/v1/myendpoint, then the user is upon authentication redirected to the above configured value of OVERWRITE_REDIRECT_URI. However, I'd like the redirection to be to the URI from which the request originated i.e. https://myapp:8000/api/v1/myendpoint
Is it possible assure that the user is redirected to the original page or not?
Sometimes the IdP returns non-json results on the UserInfo page (most notably when it was signed) as it will be a JWT.
We should handle those responses and error out (another ticket will be filed to support signed UserInfo responses).
Possibly related to #42
Using flask-oidc in a web application against our enterprise ID server. Our id token includes group information that can be quite extensive in the case the user belongs to 100s of groups or more.
In one particular case, we're generating a cookie of size 4119 bytes.. and it appears chrome is ignoring this cookie, and therefore we get thrown into a 302 re-direct loop as the client repeatedly tries to access /, gets redirected to the oidc callback which creates a cookie chrome is going to ignore, and the browser tries / again...
I believe the assumption that the cookie (serialized JWT oidc_id_token) will be < 4k is flawed, and if so, not sure there is a clean work around. In our case, I was able to subclass the JWT serializer, and remove all the group membership info before serialization. This works, but binds us to knowing the internals of this package as well as what is being returned by our auth server.
additional info... chrome fails, firefox/ie work w/ the 4119 byte cookie above. other users have more group information associated with them, but haven't been through the web app yet.
For access_token based API calls, there's no way if getting any information, as get_access_token uses the sub of the id_token. If a user's not logged in (e.g. API call with Bearer token), then it blows up. Looking up the access token from the header, and passing it to oidc._get_token_info(token) does introspect and give the token details though. Is there something wrong with this approach?
I was wondering if you could please incorporate #72 and get a new build on PyPi? Last one was in April. Thank you!
In the Resource server paragraph, the docs state:
"Also, if you have implemented an API that can should be able to accept tokens
issued by the OpenID Connect provider, just decorate those API functions with. . . "
I believe this should read:
"Also, if you have implemented an API that should be able to accept tokens
issued by the OpenID Connect provider, just decorate those API functions with. . ."
I would be happy to make this change if it is needed.
Hi,
The error is in function _is_id_token_valid(). If the id_token['aud'] is a list of one it treats it as though it was a list of multiple audiences and tries to require the azp field.
This needs to be corrected with a check for the len() if aud is a list.
Thanks.
When any ID token or user info endpoint call results in data greater than 4kb the cookie storage fails. This limits the authorization and identity data that can be relayed by the authorization server to the client arbitrarily.
flask-oidc
creates two JWS signers using the Flask secret key:
flask-oidc/flask_oidc/__init__.py
Lines 179 to 183 in 6876792
In addition, Flask itself creates a signer [using the same key].(https://github.com/pallets/flask/blob/7e714bd28b6e96d82b2848b48cf8ff48b517b09b/flask/sessions.py#L330-L332)
In general, it's unsafe to reuse a cryptographic key for multiple purposes. The proper construction is to use a KDF like HKDF to derive separate keys for each application.
I'm not sure if this is actually exploitable in this case, but if it is, one shape would look like:
OIDC_ID_TOKEN_COOKIE_NAME
cookie, which is certainly surprising at best.I haven't verified that the outputs are sufficiently compatible for the attack to actually work, but ideally the code wouldn't rely on details of slightly-differing output formats for an important security property.
I'm seeing a problem anywhere this library is using client secret basic as the auth mechanism. The issue boils down to:
bas = 'foo:bar'
bytes = bytearray(bas, 'utf-8')
s = 'Basic %s' % b64encode(bytes)
s
"Basic b'Zm9vOmJhcg=='"
s2 = 'Basic %s' % b64encode(bytes).decode('utf-8')
s2
'Basic Zm9vOmJhcg=='
In python 3.6.4, serializing bytes is outputting b'actual_value', which is then failing authentication. Adding a .decode('utf-8') results in a string, and the b'' isn't added anymore. This doesn't manifest in python 2.
The following works in both python 2 and 3:
bas = 'foo:bar'
bytes = bytearray(bas, 'utf-8')
s = str('Basic %s' % b64encode(bytes).decode('utf-8'))
s
Would this be something you're willing to incorporate? I can get a PR ready for this if so. (I think this affects #44 as well).
Right now, the documentation does not mention settings at all. However, if you inspect the source, you'll discover there are quite a few settings that are used.
I don't know if it's the expected behaviour or not...
I have this flask app (Fedora Hubs) that is designed to be left open for a while and auto-refreshes the page contents. To avoid the user being disconnected, I have setup a call to a /ping
URL that the Javascript makes every minute. This /ping
url is not decorated, but since it's inside the Flask app and flask_oidc is used, it should benefit from the before_request
hook that is automatically setup.
This hook calls authenticate_or_redirect()
which should automatically refresh the OIDC token using the refresh token, except it apparently never happens, or does not work. I'll try to print some stuff to see what's wrong here.
Google recently deprecate oauth2client
in favor of google-auth. Since this library leans so heavily on the oauth2client, it might be good to deprecate this library or, at the very least, warn of the deprecation of oauth2client
.
Combining flask-oidc with Flask-RESTful for Anitya, we've run into a problem where the error responses that flask-oidc pre-renders to JSON strings are then rendered again as encoded JSON text responses by Flask-RESTful: fedora-infra/anitya#443
The lowest impact solution that occurred to me is to have accept_token
accept an extra parameter (defaulting to json.dumps
) that defines how the error rendering happens.
It appears that OpenIDConnect has no object method to obtain access/refresh token. The only way I can figure out appears to be getting the credentials from credentials_store:
oidc = OpenIDConnect()
(...code validating/obtaining id_token...)
sub = oidc.user_getfield("sub")
credentials = oidc.credentials_store[sub]
access_token = credentials["access_token"]
refresh_token = credentials["refresh_token"]
I believe flask-oidc should provide method to obtain access/refresh token easily.
Hi,
I would like to use this project to test an OpenID Connect Identity Provider that I am developing, based on the Django OIDC Provider.
Not all Identity Providers provide a client_secrets.json
file, so it isn't clear to me how to get that or what values to put in it.
Also, when setting up the client in my identity provider, I need to provide information about which flow is being used, and what the redirect URI(s) are, and I'm not sure what to put in.
If the README had just a few sentences about how to use this with a custom identity provider, that would be great.
Thanks.
While trying to use oidc-register with an instance of ipsilon, I failed to use oidc-register to retrieve client secrets. The reason for that was that ipsilon (in default config) doesn't respond to the endpoint hardcoded at [1]. Therefore I'd like to propose that the name of the endpoint (e.g. the current .well-known/openid-configuration
) should be configurable (e.g. with a commandline argument).
(What worked for me was replacing that value with openidc/wellknown_openid_configuration
).
Thanks for considering!
[1]
flask-oidc/flask_oidc/discovery.py
Line 42 in 2c66a0d
I'm attempting to adapt the Hubs OIDC code for use in Anitya, and ran into the following error trying to run oidc-register under a Python 3.5 venv:
$ oidc-register --debug https://iddev.fedorainfracloud.org/ http://localhost:5000
Error discovering OP information
the JSON object must be str, not 'bytes'
ERROR:oidc-register:Error caught when discovering OP information:
Traceback (most recent call last):
File "/home/ncoghlan/.virtualenvs/anitya/lib/python3.5/site-packages/flask_oidc/registration_util.py", line 65, in main
OP = discovery.discover_OP_information(args.provider_url)
File "/home/ncoghlan/.virtualenvs/anitya/lib/python3.5/site-packages/flask_oidc/discovery.py", line 43, in discover_OP_information
return json.loads(content)
File "/usr/lib64/python3.5/json/__init__.py", line 312, in loads
s.__class__.__name__))
TypeError: the JSON object must be str, not 'bytes'
Should the logout() process remove the entry from the custom credential store (if using), or is it assumed that would be tracked and expunged on a duration?
I am deploying my testing OIDC webapp which is mounted to /oidedemo in uwsgi, but I found that the OIDC id token cookie is set to / instead of /oidcdemo.
As per flask Response.set_cookie, if "path" is not set it default to /, which I believe it's unreasonable for privacy and security. (I have several independent application running on each server, and it's better that every application cannot read other's cookies)
I believe flask-oidc should let the user to configure cookie path instead of missing it entirely.
We have no way of easily modifying the extra parameters when constructing the auth_url.
In OpenIDConnect::redirect_to_auth_server there is a local variable that adds parameters to the auth url -
extra_params = { 'state': urlsafe_b64encode(json.dumps(state).encode('utf-8')), }
I currently modify the auth_url via my client_secrets.json, but it would be useful to do this programmatically (e.g. In production I would like to add the parameter prompt=consent but not in development)
Right now, the documentation mentions an accept_token decorator, but provides no details on how a client should use this. I assume this is some sort of standard, but there's no indication of that in the docs.
With my PC clock 5 seconds behind the true time, authentication fails at is_id_token_valid
, "steps 9, 10". I think there ought to be some allowance for clock skew.
(But to fix it locally, I set my clock forward 5.5. seconds.)
(Actually, what's the problem with the local machine's system time being before the authentication provider's system time at the creation of the token?)
I see in the code that a memory based credential store is used by default and the existing docs mention in passing what to do but this is not clear to me. Could you document how to implement this via OIDC_CREDENTIALS_STORE?
"Note that you should probably provide the library with a place to store the credentials it has retrieved for the user. These need to be stored in a place where the user themselves or an attacker can not get to them. To provide this, give an object that has setitem and getitem dict APIs implemented as second argument to the init() call. Without this, the library will only work on a single thread, and only retain sessions until the server is restarted."
https://flask-oidc.readthedocs.io/en/latest/#flask_oidc.OpenIDConnect.init_app
Hey Jeremy,
sorry for the undescriptive title. Since Google is shutting down their OpenID provider and I'm the master of procrastination, I had to hurry porting some of my apps that relied on it for login over to OpenID Connect. I found your project here, but wanted to minimize the changes I had to make in the individual apps. So, I made some changes.
I didn't think opening a pull request against your repo would have been a good idea as the changes are obviously backwards-incompatible, but I still wanted to let you know as a courtesy.
Most of the changes are contained in this commit if you fancy cherry-picking anything from it:
passy@26c6721
Thanks for the project!
The _get_token_info
method of the OpenIDConnect
class currently uses 'Bearer' as
the value for the token_type_hint
parameter.
See:
flask-oidc/flask_oidc/__init__.py
Line 748 in b5c9c1e
According to the spec, only access_token
or refresh_token
are allowed as values for the token_type_hint
parameter.
See:
https://tools.ietf.org/html/rfc7662
Values for this field are defined in the "OAuth Token Type Hints" registry defined
in OAuth Token Revocation [RFC7009].
The typ
field in the JWT must be mapped to the following token_type_hint
values:
Another option may be to not set the token_type_hint
parameter at all.
See also:
https://connect2id.com/products/server/docs/api/token-introspection
I stumbled upon this issue whilst trying to use Keycloak in combination with flask-oidc. When I send the token info request without the token_type_hint
parameter (by patching the flask-oidc lib) then the token info can be retrieved from Keycloak token_introspection_endpoint
.
I'm looking to use this with Hydra. When handling oidc_callback, I get an error:
127.0.0.1 - - [22/Nov/2017 17:48:25] "GET /oidc_callback?code=EOG_WJio6_5E632BPlq8AMbV7z_gwIKTbYWxz5NIvgw.ULGZ9UBhO26ZtBds-wnMJ5rMN9wC35NQbV-CEIk7RYA&scope=openid&state=eyJjc3JmX3Rva2VuIjogIjJZR2JsbzR5TGlqc0lSZ2NvZXplU3dFcDhHMmFwUklBIiwgImRlc3RpbmF0aW9uIjogImV5SmhiR2NpT2lKSVV6STFOaUo5LkltaDBkSEE2THk5c2IyTmhiR2h2YzNRNk5UQXdNQzlpYjI4aS5xUU9OYmNyNlVuVGROY1ltLXQwa3ZUam9JcnFQbDAzbUxVU1hSQjNQTFhFIn0%3D HTTP/1.1" 500 -
Error on request:
Traceback (most recent call last):
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/werkzeug/serving.py", line 209, in run_wsgi
execute(self.server.app)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/werkzeug/serving.py", line 197, in execute
application_iter = app(environ, start_response)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/flask_oidc/__init__.py", line 650, in _oidc_callback
credentials = flow.step2_exchange(code)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/oauth2client/_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "/mnt/e/ashicX/.conda/envs/flask/lib/python3.6/site-packages/oauth2client/client.py", line 2089, in step2_exchange
raise FlowExchangeError(error_msg)
oauth2client.client.FlowExchangeError: invalid_requestThe request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed
On the hydra logs, I see this:
time="2017-11-22T17:48:25Z" level=info msg="started handling request" method=POST remote="172.30.0.1:42492" request=/oauth2/token
time="2017-11-22T17:48:25Z" level=error msg="An error occurred" error="HTTP authorization header missing or invalid: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed"
time="2017-11-22T17:48:25Z" level=info msg="completed handling request" measure#http://localhost:4444.latency=126861 method=POST remote="172.30.0.1:42492" request=/oauth2/token status=400 text_status="Bad Request" took="126.861µs"
It appears hydra wants "code" to be in the Authorization Header. ory/hydra#174 would suggest as much. Is there a way around this? It appears the (now deprecated) oauth client is putting the code in the POST body.
On Hubs I get this traceback sometimes:
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1641, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1544, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1637, in full_dispatch_request
rv = self.preprocess_request()
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1837, in preprocess_request
rv = func()
File "/usr/lib/python3.6/site-packages/flask_oidc/__init__.py", line 324, in _before_request
self.authenticate_or_redirect()
File "/usr/lib/python3.6/site-packages/flask_oidc/__init__.py", line 362, in authenticate_or_redirect
credentials.refresh(httplib2.Http())
File "/usr/lib/python3.6/site-packages/oauth2client/client.py", line 545, in refresh
self._refresh(http)
File "/usr/lib/python3.6/site-packages/oauth2client/client.py", line 749, in _refresh
self._do_refresh_request(http)
File "/usr/lib/python3.6/site-packages/oauth2client/client.py", line 786, in _do_refresh_request
self.access_token = d['access_token']
KeyError: 'access_token'
I've printed the value of the variable d
and it's {'error_description': 'Something went wrong refreshing', 'error': 'invalid_grant'}
.
Just importing from flask_oidc import OpenIDConnect
fails with
ImportError: cannot import name TimedJSONWebSignatureSerializer
And it seems that TimedJSONWebSignatureSerializer
is not even included anymore in ItsDangerous anymore according to http://pythonhosted.org/itsdangerous/
Working on Anitya's OIDC integration, I'm sending the access token to the server as part of the request's query string. The token validation decorator correctly finds it there, and sets the flask global g.oidc_token_info
. However, the global that the rest of flask-oidc is looking for is g.oidc_id_token
, and it never checks g.oidc_token_info
at all (even as a fallback), so I need to pass the access token explictly to the API as follows: APP.oidc.user_getfield('user_id', access_token)
.
access_token
is retrieved from the request using flask-reqparse:
_BASE_ARG_PARSER = reqparse.RequestParser(trim=True, bundle_errors=True)
_BASE_ARG_PARSER.add_argument('access_token', type=str)
And then in the request itself, the initial parser is created via _BASE_ARG_PARSER.copy()
But when I do that, the call to user_getfield
fails with the following traceback:
File "/home/ncoghlan/fedoradevel/anitya/anitya/api_v2.py", line 65, in post
user_id=APP.oidc.user_getfield('user_id', access_token),
File "/home/ncoghlan/.virtualenvs/anitya/lib/python3.5/site-packages/flask_oidc/__init__.py", line 167, in user_getfield
info = self.user_getinfo([field], access_token)
File "/home/ncoghlan/.virtualenvs/anitya/lib/python3.5/site-packages/flask_oidc/__init__.py", line 196, in user_getinfo
all_info = self._retrieve_userinfo(access_token)
File "/home/ncoghlan/.virtualenvs/anitya/lib/python3.5/site-packages/flask_oidc/__init__.py", line 241, in _retrieve_userinfo
info = _json_loads(content)
File "/home/ncoghlan/.virtualenvs/anitya/lib/python3.5/site-packages/flask_oidc/__init__.py", line 52, in _json_loads
return json.loads(content)
File "/usr/lib64/python3.5/json/__init__.py", line 319, in loads
return _default_decoder.decode(s)
File "/usr/lib64/python3.5/json/decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib64/python3.5/json/decoder.py", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
The debug logs show the following response from Ipsilon:
flask_oidc: DEBUG: Retrieved user info: b'<!DOCTYPE html>\n<!--[if IE 8]><html class="ie8 login-pf"><![endif]-->\n<!--[if gt IE 8]><!-->\n<html class="login-pf">\n<!--<![endif]-->\n <head>\n <title>Internal Error</title>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <link href="/ui/css/ipsilon.css" rel="stylesheet" media="screen, print">\n <link href="/ui/css/styles.css" rel="stylesheet" media="screen, print">\n </head>\n <body>\n <a href="/" id="badge" tabindex="-1">\n <img src="/ui/img/logo.svg" alt="Ipsilon IdP" />\n </a>\n <div class="container">\n <div class="row">\n <div class="col-sm-12">\n <div id="brand">\n <img src="/ui/img/brand-lg.png" alt="Ipsilon">\n </div>\n </div>\n \n<div class="col-sm-12">\n <h1>500 - Internal Server Error</h1>\n \n <p>Ipsilon encountered an unexpected internal error while trying to\n fulfill your request.</p>\n \n <p>Please retry again.</p>\n <p>If the error persists, contact the server administrator to resolve\n the problem.</p>\n</div>\n\n </div>\n </div>\n </body>\n</html>'
Hi,
because of a security incident, I had to replace SECRET_KEY
of my server (Pagure 4.0.3) using flask-oidc
1.4.0. On redeploy with the new secret key, previously logged in users started getting this error:
[Thu May 24 09:00:44.419300 2018] [:error] [pid 31] 2018-05-24 09:00:44,351 [ERROR] flask.app: Exception on /rpms/setup [GET]
[Thu May 24 09:00:44.419316 2018] [:error] [pid 31] Traceback (most recent call last):
[Thu May 24 09:00:44.419318 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/flask/app.py", line 2292, in wsgi_app
[Thu May 24 09:00:44.419320 2018] [:error] [pid 31] response = self.full_dispatch_request()
[Thu May 24 09:00:44.419322 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
[Thu May 24 09:00:44.419324 2018] [:error] [pid 31] rv = self.handle_user_exception(e)
[Thu May 24 09:00:44.419326 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/flask/app.py", line 1718, in handle_user_exception
[Thu May 24 09:00:44.419328 2018] [:error] [pid 31] reraise(exc_type, exc_value, tb)
[Thu May 24 09:00:44.419330 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/flask/app.py", line 1811, in full_dispatch_request
[Thu May 24 09:00:44.419332 2018] [:error] [pid 31] rv = self.preprocess_request()
[Thu May 24 09:00:44.419333 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/flask/app.py", line 2087, in preprocess_request
[Thu May 24 09:00:44.419335 2018] [:error] [pid 31] rv = func()
[Thu May 24 09:00:44.419337 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/flask_oidc/__init__.py", line 406, in _before_request
[Thu May 24 09:00:44.419338 2018] [:error] [pid 31] self.authenticate_or_redirect()
[Thu May 24 09:00:44.419340 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/flask_oidc/__init__.py", line 426, in authenticate_or_redirect
[Thu May 24 09:00:44.419342 2018] [:error] [pid 31] id_token = self._get_cookie_id_token()
[Thu May 24 09:00:44.419344 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/flask_oidc/__init__.py", line 352, in _get_cookie_id_token
[Thu May 24 09:00:44.419346 2018] [:error] [pid 31] return self.cookie_serializer.loads(id_token_cookie)
[Thu May 24 09:00:44.419347 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/itsdangerous.py", line 795, in loads
[Thu May 24 09:00:44.419349 2018] [:error] [pid 31] self, s, salt, return_header=True)
[Thu May 24 09:00:44.419351 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/itsdangerous.py", line 749, in loads
[Thu May 24 09:00:44.419353 2018] [:error] [pid 31] self.make_signer(salt, self.algorithm).unsign(want_bytes(s)),
[Thu May 24 09:00:44.419354 2018] [:error] [pid 31] File "/usr/lib/python2.7/site-packages/itsdangerous.py", line 374, in unsign
[Thu May 24 09:00:44.419356 2018] [:error] [pid 31] payload=value)
[Thu May 24 09:00:44.419358 2018] [:error] [pid 31] BadSignature: Signature 'o3c13YeSK_1_Mqrf9t7HoCi-tSXlkCBl6fW2JC0RHA8' does not match
Users who weren't logged in previously could access the server and log in just fine. I think this error should be caught by flask-oidc and user logged out as consequence of it. Does that make sense?
Hi.
flask-oidc==1.3.0
python 3.6.5
flask 0.12.2
ubuntu 16.4.3
I setup everything to login with keycloak. Everything worked as expected if run against keycloak over HTTP.
Then I configured keycloak over HTTPS with a certificate created from a self signed CA:
::ffff:172.18.0.11 - - [2018-03-31 21:19:23] "GET / HTTP/1.1" 302 2133 0.031266
Traceback (most recent call last):
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/gevent/pywsgi.py", line 935, in handle_one_response
self.run_application()
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/gevent/pywsgi.py", line 908, in run_application
self.result = self.application(self.environ, self.start_response)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/flask_oidc/__init__.py", line 650, in _oidc_callback
credentials = flow.step2_exchange(code)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/oauth2client/_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/oauth2client/client.py", line 2054, in step2_exchange
http, self.token_uri, method='POST', body=body, headers=headers)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/oauth2client/transport.py", line 282, in request
connection_type=connection_type)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/httplib2/__init__.py", line 1514, in request
(response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/httplib2/__init__.py", line 1264, in _request
(response, content) = self._conn_request(conn, request_uri, method, body, headers)
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/httplib2/__init__.py", line 1187, in _conn_request
conn.connect()
File "/root/.virtualenvs/spy-registry-kjDCNykl/lib/python3.6/site-packages/httplib2/__init__.py", line 1013, in connect
self.sock = self._context.wrap_socket(sock, server_hostname=self.host)
File "/opt/python36/lib/python3.6/ssl.py", line 407, in wrap_socket
_context=self, _session=session)
File "/opt/python36/lib/python3.6/ssl.py", line 814, in __init__
self.do_handshake()
File "/opt/python36/lib/python3.6/ssl.py", line 1068, in do_handshake
self._sslobj.do_handshake()
File "/opt/python36/lib/python3.6/ssl.py", line 689, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833)
Sat Mar 31 21:19:23 2018 {'REMOTE_ADDR': '::ffff:172.18.0.11', 'REMOTE_PORT': '46558', 'HTTP_HOST': '10.100.100.10:6000', (hidden keys: 30)} failed with SSLError
I suppose the problem is in these rows (flask_oidc/__init__.py
, method _oidc_callback
):
# make a request to IdP to exchange the auth code for OAuth credentials
flow = self._flow_for_request()
credentials = flow.step2_exchange(code)
id_token = credentials.id_token
I think flask tries to communicate with keycloak and the SSL handshake fails.
Custom CA cert is imported in system ca store where flask runs.
I tried to use the following env vars:
but no way to get rid of the issue.
I tried to follow the code, but I missed myself in it.
Thanks
The configuration variable OIDC_CLIENT_SECRETS is not documented here: https://flask-oidc.readthedocs.io/en/latest/ but a very important one for using the framework.
When trying to initialize flask-oidc in my application, I am seeing this error:
When debugging, I can see in the source code for flask-oidc that the dict recieved from my client_secrets.json file is being converted to a list, then below the code is trying to access 'issuer' from that list.
Since you cannot get key 'issuer' from a list of values, this is breaking the application.
The application is using python 3.6.
What's the right way to logout the user? Explicitly expire the oidc_id_token cookie?
The only token expiration check and token refresh happens at authenticate_or_redirect
, however this method is deprecated and there is, as far as I know, no alternative method to refresh tokens in this library.
Been no activity for some time, and no new cut of the latest version to pypi. Can we assume that this depo is dead?
Hi, I wanted to know if there's any option to select individual mail addresses instead of a whole domain or vice versa: Excluding individuals from my own domain.
Thank you.
It would be useful to create state-less application to expose to the state
field (or some field in it) to the client.
Note: rats is using oidc.redirect_to_auth_server(next_url)
to trigger the login: https://pagure.io/rats/blob/2f271f93d35089217f14b46d45f2128e4b4864dc/f/rats/ui/ui_app.py#_78
Thanks! :)
Currently the load_secrets function will always look for a file to open and read. Is there a reason for not allowing this function to load the secrets from a dictionary passed in instead of loading from a file?
I do not want to save a static file on my root directory with all the secrets. I would like to be able to obtain the secrets programatically and not have to store any secrets on the file system.
I'd love to see a basic example or a documentation of using this
This smells like a massive security flaw. What does it mean? What impact does not checking issuer have? Can flask-oidc be considered secure if it's not checking the issuer?
The oauth2client is deprecated https://github.com/google/oauth2client.
This project should move away from it and to the suggested oauthlib (https://oauthlib.readthedocs.io/en/latest/)
Does it exist a method to only refresh the token?
I would like to refresh information in the credentials store (access_token and refresh_token) with an API, I can read the tokens and using them to obtain a new token. How can I write it to credentials store?
Flask-OIDC expects the id_token to not be None, but it will be None if the openid scope isn't requested.
No helpful exception is raised when this occurs (it results in a AttributeError since NoneType doesn't have get
). It would be much better to explicitly handle the error and raise an exception notifying the developer of their error.
According to the docs there seems to be no way to get a hand at the access_token
of the current user.
It would be very helpful if flask-oidc would provide a easy way to retrieve an access_token
for the current user to make requests to other services.
Running oidc-discover
on Python3 can lead to a traceback:
ERROR:oidc-register:Error caught when discovering OP information:
Traceback (most recent call last):
File "[...]/lib/python3.5/site-packages/flask_oidc/registration_util.py", line 65, in main
OP = discovery.discover_OP_information(args.provider_url)
File "[...]/lib/python3.5/site-packages/flask_oidc/discovery.py", line 43, in discover_OP_information
return json.loads(content)
File "/usr/lib64/python3.5/json/__init__.py", line 312, in loads
s.__class__.__name__))
TypeError: the JSON object must be str, not 'bytes'
This is because httplib2
returns the content as bytes, not strings, and json.loads()
expects strings. I have a patch to fix this, I'll submit a PR right now.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.