juanifioren / django-oidc-provider Goto Github PK
View Code? Open in Web Editor NEWOpenID Connect and OAuth2 provider implementation for Djangonauts.
Home Page: http://django-oidc-provider.readthedocs.org
License: MIT License
OpenID Connect and OAuth2 provider implementation for Djangonauts.
Home Page: http://django-oidc-provider.readthedocs.org
License: MIT License
Address should not be returned here
({'status': '200', 'server': 'WSGIServer/0.1 Python/2.7.9', 'pragma':
'no-cache', 'cache-control': 'no-store', 'date': 'Tue, 16 Aug 2016
09:20:38 GMT', 'x-frame-options': 'SAMEORIGIN', 'content-type':
'application/json'}, '{"sub": "3", "address": {}}')
http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
The README
shows the following in settings.py
:
# Used to log the user in.
# See: https://docs.djangoproject.com/en/1.7/ref/settings/#login-url
LOGIN_URL = '/accounts/login/'
but it is not clear why LOGIN_URL
is required or what it should be set to ('/accounts/login/' ?).
I am trying to install this on Windows 10 and receiving the following error:
error: Microsoft Visual C++ 10.0 is required (Unable to find vcvarsall.bat).
Visual C++ 10.0 comes with Visual Studio 10 which is no longer available. Have you run into this? Do you know of a workaround? Thanks!
Hi,
Can you please change the code in the v3 branch importing Crypto to Cryptodome?
I think the Crypto package is no longer maintained (last commit was two years ago).
As reference you can take a look at:
rohe/pyjwkest@d676d16
Best regards!
Hi,
I'm using the same project and getting "Redirect URI Error" when submitting the following request.
redirect_uri is present in the query string. please advise.
I have a project that already uses python-jose, and I'd like to use django-oidc-provider as well. It seems a shame to have multiple implementations of JWT running around, so that there are possibly-conflicting transitive dependencies and interoperability concerns.
It's possible to have library users choose their transitive dependency by using extra_requires:
e.g.
https://github.com/jazzband/django-constance/blob/8f71bca1924df04274475dd013253ebfee633e93/docs/index.rst#installation
https://github.com/jazzband/django-constance/blob/8f71bca1924df04274475dd013253ebfee633e93/setup.py#L54
Would you consider this approach? I can do a PR if it sounds like a good idea.
I have question to handling POST request in https://github.com/juanifioren/django-oidc-provider/blob/v0.3.x/oidc_provider/views.py#L104 ?
89: def post(self, request, *args, **kwargs):
90:
91: authorize = AuthorizeEndpoint(request)
92:
93: allow = True if request.POST.get('allow') else False
94:
95: try:
96: authorize.validate_params()
97:
98: if not allow:
99: raise AuthorizeError(authorize.params.redirect_uri,
100: 'access_denied',
101: authorize.grant_type)
102:
103: # Save the user consent given to the client.
104: authorize.set_client_user_consent()
And some additional questions:
Why You validating params before checking "allow" in POST ?. Is where any spec saying that "allow" must be in POST request ?
Actually the client generate ID Token using RS256 which is the default algorithm according:
http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
Would be deseable to add support for HS256 and another common algorithms to the client configuration.
I found some errors running the test suite with tox
in the v0.2.x branch without making any changes to the code on python 3.4, for example:
ERROR: test_idtoken_sign_validation (oidc_provider.tests.test_token_endpoint.TokenTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/pabluk/dev/projects/django-oidc-provider-pabluk/oidc_provider/tests/test_token_endpoint.py", line 314, in test_idtoken_sign_validation
SIGKEYS = self._get_keys()
File "/home/pabluk/dev/projects/django-oidc-provider-pabluk/oidc_provider/tests/test_token_endpoint.py", line 97, in _get_keys
response = JwksView.as_view()(request)
File "/home/pabluk/dev/projects/django-oidc-provider-pabluk/.tox/py34-django18/lib/python3.4/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/home/pabluk/dev/projects/django-oidc-provider-pabluk/.tox/py34-django18/lib/python3.4/site-packages/django/views/generic/base.py", line 89, in dispatch
return handler(request, *args, **kwargs)
File "/home/pabluk/dev/projects/django-oidc-provider-pabluk/oidc_provider/views.py", line 192, in get
'n': long_to_base64(public_key.n).decode('utf-8'),
AttributeError: 'str' object has no attribute 'decode'
Comparing the dependencies used in the latest travis run with python 3.4, I saw that it installed pyjwkest-1.0.5
and my tox tests install pyjwkest-1.0.6
following the requirement pyjwkest>=1.0.3,<1.1
of setup.py
.
Then looking at the changes in rohe/pyjwkest@1.0.5...1.0.6 I found this commit rohe/pyjwkest@42b52e7 that seems to change the type of value returned by long_to_base64()
.
We wanted to use multiple keys (per client) and it appears that the library only allows one.
Is there a plan to support multiple keys?
Thanks,
-r
Currently all clients registered by django-oidc-provider require a client secret, however some clients are not capable of keeping secrets confidential (specifically: downloadable apps).
If the client has approved the request previously, subsequent requests are auto-approved by django-oidc-provider. I recommend not auto-approving requests for non-confidential clients that use URI schemes with no authority (i.e. non-https schemes). This could be achieved by adding an "App" client type with no secret provisioned, so that requests from such clients could be processed differently.
If it's useful to anyone, I've been working on a project using django-oidc-provider with django-allauth for authentication. It uses the ExtraScopeClaims class to include information from the social identity providers and the user's group membership in the UserInfo endpoint. It still needs more testing and documentation, but overall seems to work. It's up at https://github.com/wayward710/django-oidc-allauth
String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token.
The nonce in the returned ID Token is compared to the hash of the session cookie to detect ID Token replay by third parties. Use of the nonce is OPTIONAL when using the code flow.
Consider adding few examples for beginners
The idea is to have both django-oidc-provider
and djangorestframework
working on a same project providing Authentication with OpenID Connect and Authorization with OAuth2.
Any help is welcomed.
Adding full support for Django 1.8.*.
I think this would be a cool feature. Also create an "action" for re-generate SECRET's.
Any opinion is welcomed.
I get an import error installing DOP on Django 1.6, it's because JsonResponse is available only from >= django 1.7
while investigating an issue with public key and signing, I noticed that test_idtoken_sign_validation is always passing because it's not doing an assert.
It appears that current implementation contains only "alg" in the token header.
E.g.
{"alg":"RS256")
Should include kid and look like:
{"alg":"RS256","kid":"1f8965c7a3f36d7ed39b1f95cb5143dd"}
I believe the issue is with encode_id_token method in utils/token.py. It should be calculating kid and passing it as an argument to RSAKey constructor.
in section: 3.1.2.3. Authorization Server Authenticates End-User we can read:
The Authorization Server MUST attempt to Authenticate the End-User in the following cases:
- The End-User is not already Authenticated.
- The Authentication Request contains the
prompt
parameter with the valuelogin
. In this case, the Authorization Server MUST reauthenticate the End-User even if the End-User is already authenticated.The Authorization Server MUST NOT interact with the End-User in the following case:
- The Authentication Request contains the
prompt
parameter with the valuenone
. In this case, the Authorization Server MUST return an error if an End-User is not already Authenticated or could not be silently Authenticated.
This parameter being ignored.
Maybe something like this patch will help. Only my worries is the last part about log out the user to force login screen.
*** django-rest-auth/rest_auth/views.py 2016-03-30 13:24:33.793060288 +0000
--- django-rest-auth/rest_auth/views.py 2016-03-30 13:24:23.457060791 +0000
***************
*** 2,7 ****
--- 2,8 ----
from Crypto.PublicKey import RSA
from django.contrib.auth.views import redirect_to_login, logout
+ from django.contrib.auth import logout as auth_logout
from django.core.urlresolvers import reverse
from django.http import JsonResponse
from django.shortcuts import render
***************
*** 60,65 ****
--- 61,67 ----
self.params.scope = query_dict.get('scope', '').split()
self.params.state = query_dict.get('state', '')
self.params.nonce = query_dict.get('nonce', '')
+ self.params.prompt = query_dict.get('prompt', '')
def validate_params(self):
try:
***************
*** 85,90 ****
--- 87,98 ----
raise AuthorizeError(self.params.redirect_uri, 'invalid_request',
self.grant_type)
+ if self.is_authentication and self.params.prompt == 'none' and not self.request.user.is_authenticated():
+ raise AuthorizeError(self.params.redirect_uri, 'login_required', self.grant_type)
+
+ if self.is_authentication and self.params.prompt == 'login':
+ auth_logout(self.request)
+
clean_redirect_uri = urlsplit(self.params.redirect_uri)
clean_redirect_uri = urlunsplit(clean_redirect_uri._replace(query=''))
if not (clean_redirect_uri in self.client.redirect_uris):
As the spec says:
ID Tokens MUST be signed using JWS and optionally both signed and then encrypted using JWS and JWE respectively, thereby providing authentication, integrity, non-repudiation, and optionally, confidentiality, per Section 16.14.
Read more here.
It appears that we're unable to integrate a Java client to the jwks endpoint to validate the ID token.
The issues is logged here but it boils down to incompatible base64 encoding of modulus of public key. Java client can't decode what Python endpoint creates.
https://github.com/rohe/pyjwkest/issues/36
Any advice would be appreciated.
Thanks
In the Authentication Request, if users previously gave consent to some client
(for a specific list of scopes) and because they might be prompted for the same
authorization multiple times.
I have some doubts.
¿Could be acceptable to skip it?.
¿Works on both auth code and implicit flows?.
Am hearing opinions about it. Thanks.
Per http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig:
OpenID Providers supporting Discovery MUST make a JSON document available at the path formed by concatenating the string
/.well-known/openid-configuration
to the Issuer. The syntax and semantics of .well-known are defined in RFC 5785 [RFC5785] and apply to the Issuer value when it contains no path component. openid-configuration MUST point to a JSON document compliant with this specification and MUST be returned using theapplication/json
content type.
Currently there is no view for /.well-known/openid-configuration
.
pyoidc does support this feature and other libraries expect that as well: django-oidc-auth and AWS.
Adding full support for Python 3.*.
A client has requested that tokens/codes should no longer be usable if the same client has a newer one for that user, to allow for less possible attack vectors.
Before I begin implementing a solution I thought I would check here to see if:
a) this would be something you would be interested in merging in and, if so,
b) you had any preferences on implementation
I imagine the two possible solutions would be to set the old code/token to have expired long ago, or just delete it outright from the database.
Any feedback/suggestions/questions would be appreciated.
Any reason not to leverage pyoidc?
The README states:
Despite that implementation MUST support TLS. You can make request without using SSL. There is no control on that.
If you want to suggest to the users, something like this:
https://github.com/rdegges/django-sslify can be used to prevent non SSL connections.
An alternative of using Authorization: Bearer
HTTP header:
POST /openid/userinfo/
Host: localhost:8000
Authorization: Bearer 9a01043111f84e18a8ef392771592a59
The idea is to implement this.
GET /openid/userinfo/?access_token=9a01043111f84e18a8ef392771592a59
Adding full support for Django 1.6.* at least.
Following the documentation to create the example project, I've found this error with the creatersakey
management command using Python 3.4 and the branch v0.2.x:
$ python manage.py creatersakey
Traceback (most recent call last):
File "/home/pabluk/dev/projects/django-oidc-provider/venv/lib/python3.4/site-packages/oidc_provider/management/commands/creatersakey.py", line 15, in handle
f.write(key.exportKey('PEM'))
TypeError: must be str, not bytes
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/pabluk/dev/projects/django-oidc-provider/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
utility.execute()
File "/home/pabluk/dev/projects/django-oidc-provider/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 330, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/pabluk/dev/projects/django-oidc-provider/venv/lib/python3.4/site-packages/django/core/management/base.py", line 390, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/pabluk/dev/projects/django-oidc-provider/venv/lib/python3.4/site-packages/django/core/management/base.py", line 441, in execute
output = self.handle(*args, **options)
File "/home/pabluk/dev/projects/django-oidc-provider/venv/lib/python3.4/site-packages/oidc_provider/management/commands/creatersakey.py", line 18, in handle
self.stdout.write('Something goes wrong: ' + e.message)
AttributeError: 'TypeError' object has no attribute 'message'
Running the same command in Python 2.7 works as expected.
Hi Juan,
I'm using your app to split a project into multiple smaller projects but we develop all the clients so asking for user consent is irrelevant for us. Would it make sense to add a setting (OIDC_ALWAYS_SKIP_CONSENT?) to completely bypass it?
I can provide a pull request if you're interested.
In the mean time, I'm planning to implement it by adding UserConsent objects on User create and Client create and OIDC_SKIP_CONSENT_EXPIRE = 99999.
OIDC_IDTOKEN_SUB_GENERATOR should handle string pointing to function not direct reference to function.
Currently I'm force to write something like in settings.py
:
from my_app.tools import my_sub_generator
OIDC_IDTOKEN_SUB_GENERATOR = lambda user: my_sub_generator(user)
I think better solution is to use:
OIDC_IDTOKEN_SUB_GENERATOR = 'my_app.tools.my_sub_generator'
Thanks for creating the new branch for the dynamic registration. Is there anything you need me to do with it at this point, or is it just waiting to be merged?
When redirect uri pattern follows AngularJs URI pattern the redirect breaks. For example, our client's callback URI looks something like https://www.somewebsite.com/#auth.
It appears that the following line:
query_fragment = parse_qs(uri.fragment)
in authorize.py is dropping "auth" in fragment.
Result is redirect to https://www.somewebsite.com/#token_type...
From resource server (RS), is there a way to validate the access token?
Thanks,
-r
To well support native apps, it's recommended to support the PKCE OAuth extension.
Adding full support for Django 1.9.
Translate in french
I think this commit broke it: rohe/pyjwkest@3292070
I wonder if it's a bug in pyjwkest or something which can be fixed in oidc provider.
As we can read in this section of the OAuth2 Spec:
Clients in possession of a client password MAY use the HTTP Basic
authentication scheme as defined in [RFC2617] to authenticate with
the authorization server.
Actually, we are only supporting the include of client credentials in the request-body.
So, HTTP Basic authentication scheme SHOULD be implemented.
Hi.
The latest version 0.2.2 is not accessible from PyPI:
Collecting django-oidc-provider==0.2.2 (from -r /opt/python/ondeck/app/requirements.txt (line 3))
Could not find a version that satisfies the requirement django-oidc-provider==0.2.2 (from -r /opt/python/ondeck/app/requirements.txt (line 3)) (from versions: 0.0.1, 0.0.2, 0.0.3, 0.0.5, 0.0.6, 0.0.7, 0.1.0, 0.1.1, 0.1.2, 0.2.0, 0.2.1)
It looks like you may have forgotten to commit the last DB migrations to your repo. I get a request when I run the runserver that your code needs migrations. I did makemigrations on your code and it fixed this. When I want to upgrade to a future version, of your code, there will be collisions with migrations, since we both will be making migrations on the same change set.
You may want to check this out and fix it ASAP before too many people run into this issue.
As we can read in the OAuth2 spec: https://tools.ietf.org/html/rfc6749#section-7
The resource server MUST validate the
access token and ensure that it has not expired and that its scope
covers the requested resource.
So, the provider MUST ensure that the access token has (at least) openid
in their scope list.
I was developing a example with that project and I realised that both Token or UserInfo endpoint are not checking if the code / access token has expired or not. Just checks for that code / token in the database.
(In the token endpoint checks for the expiration, but if the token has not be used, and the first time is used has expired the response is successful response as well)
Do you think to change that in the future? Or there is a reason to do like that?
I fix that just adding a check in the validate_params functions, but I would like to heard yours answers before.
I'm interested in using this library but I can't find any roadmap indicating when it should be production ready. Please advise.
Regards
-r
I think that the issuer value sent by /.well-known/openid-configuration/
is wrong:
$ curl "https://id.seminar.io/openid/.well-known/openid-configuration/" | python -m json.tool
{
"authorization_endpoint": "https://id.seminar.io/openid/authorize",
"end_session_endpoint": "https://id.seminar.io/openid/logout",
"id_token_signing_alg_values_supported": [
"RS256"
],
"issuer": "https://id.seminar.io/openid/.well-known/openid-configuration",
"jwks_uri": "https://id.seminar.io/openid/jwks",
"response_types_supported": [
"code",
"id_token",
"id_token token"
],
"subject_types_supported": [
"public"
],
"token_endpoint": "https://id.seminar.io/openid/token",
"token_endpoint_auth_methods_supported": [
"client_secret_post",
"client_secret_basic"
],
"userinfo_endpoint": "https://id.seminar.io/openid/userinfo"
}
using the oic library I see this error:
>>> client.provider_config("https://id.seminar.io/openid/")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/pabluk/temp/venv/local/lib/python2.7/site-packages/oic/oic/__init__.py", line 917, in provider_config
self.handle_provider_config(pcr, issuer, keys, endpoints)
File "/home/pabluk/temp/venv/local/lib/python2.7/site-packages/oic/oic/__init__.py", line 868, in handle_provider_config
pcr)
oic.exception.IssuerMismatch: 'https://id.seminar.io/openid' != 'http://id.seminar.io/openid/.well-known/openid-configuration'
>>>
and looking at https://github.com/juanifioren/django-oidc-provider/blob/v0.2.3/oidc_provider/lib/utils/common.py#L23:L24 I see that the value returned by reverse('oidc_provider:provider_info')
has no ending slash:
>>> from django.core.urlresolvers import reverse
>>> reverse('oidc_provider:provider_info')
u'/openid/.well-known/openid-configuration'
>>> reverse('oidc_provider:provider_info').split('/.well-known/openid-configuration/')
[u'/openid/.well-known/openid-configuration']
so it's never split.
Also related with issue #65.
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.