Dropbox and Django SSO using SAML - django

Summary
I am looking to use Dropbox SSO functionality by using the authentication from a Django site. Note that I'm not looking to use SAML as a backend for my Django site.
Resources
1) Dropbox Custom SSO help page: https://www.dropbox.com/en/help/1921#custom
2) Creating a SAML response: https://robinelvin.wordpress.com/2009/09/04/saml-with-django/
3) Struggled to find any examples from Google of people doing this kind of SSO. Lots of links about people using SAML as a Django backend.
Question
In the dropbox admin settings I can add my X509 certificate and the login link. This means that when you try to login into Dropbox using SSO it nicely forwards you to my Django site's login page using a GET request with a SAMLRequest in the querystring.
However, my understanding is that I now need to, once the user is authenticated on the Django site, fire a POST request back to Dropbox at their SAML login link with a SAMLResponse in the post data. Using the second resource above I believe I can create the SAMLResponse xml but I am unsure how to redirect the user to the dropbox SAML login link with the SAML data from my Django view.
Any help much appreciated.

Managed to get the functionality I needed using django-saml2-idp https://github.com/peopledoc/django-saml2-idp
Good documentation on installing here: https://github.com/peopledoc/django-saml2-idp/blob/master/doc/INSTALL.txt
Settings in the Dropbox Admin console required the X509 certificate and then the login url set to: https://****.com/idp/login
Note that I had issues installing the M2Crypto dependency so used an Ubuntu package via:
sudo apt-get install python-m2crypto
Additionally I'm using Django 1.9.6 so needed to make overrides to the views.py, urls.py, and registry.py files to make them compatible (various import statements needed updating and the urls changed to the new list format rather than using patterns).
Created a Dropbox Processor as follows:
import base64
import zlib
from saml2idp import base
from saml2idp.xml_render import _get_assertion_xml
def get_assertion_dropbox_xml(parameters, signed=False):
return _get_assertion_xml(ASSERTION_DROPBOX, parameters, signed)
ASSERTION_DROPBOX = (
'<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" '
'ID="${ASSERTION_ID}" '
'IssueInstant="${ISSUE_INSTANT}" '
'Version="2.0">'
'<saml:Issuer>${ISSUER}</saml:Issuer>'
'${ASSERTION_SIGNATURE}'
'${SUBJECT_STATEMENT}'
'<saml:Conditions NotBefore="${NOT_BEFORE}" NotOnOrAfter="${NOT_ON_OR_AFTER}">'
'<saml:AudienceRestriction>'
'<saml:Audience>${AUDIENCE}</saml:Audience>'
'</saml:AudienceRestriction>'
'</saml:Conditions>'
'<saml:AuthnStatement AuthnInstant="${AUTH_INSTANT}"'
'>'
'<saml:AuthnContext>'
'<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>'
'</saml:AuthnContext>'
'</saml:AuthnStatement>'
'${ATTRIBUTE_STATEMENT}'
'</saml:Assertion>'
)
class Processor(base.Processor):
def _decode_request(self):
"""
Decodes _request_xml from _saml_request.
"""
self._request_xml = zlib.decompress(base64.b64decode(self._saml_request), -15)
def _format_assertion(self):
self._assertion_xml = get_assertion_dropbox_xml(self._assertion_params, signed=False)
Which you register in your settings.py file as follows:
SAML2IDP_CONFIG = {
'autosubmit': True,
'certificate_file': '/****/certificate.pem',
'private_key_file': '/****/private-key.pem',
'issuer': 'https://www.****.com',
'signing': True,
}
sampleSpConfig = {
'acs_url': 'https://www.dropbox.com/saml_login',
'processor': 'dropbox.Processor',
}
SAML2IDP_REMOTES = {
'sample': sampleSpConfig,
}
Works like a dream. Hope this helps somebody out there.

Related

WooCommerce webhooks with Django Rest Framework

I am trying to integrate WooCommerce webhooks with Django but without success. I found a solution to a similar issue, but still cant make it work.
The thing is that, Woocomerce is generating this secret key automatically. I guess that I have to hard code it by myself in the admin panel ?
Also about the code bellow(solution found in the web), Django is complaining that request has no property payload. I guess that it must be data ?
mport base64
import hashlib
import hmac
request_sig = request.headers.get("x-wc-webhook-signature")
signature = hmac.new(<your_secret_key>.encode(), request.payload, hashlib.sha256).digest()
if hmac.compare_digest(
request_sig.encode(), base64.b64encode(signature)
):
return True
return False
enter code here

Django all auth facebook login with Use Strict Mode for Redirect URIs

Hi I am trying to implement Facebook login for my website using Django Allauth.
As we can no longer disable Use Strict Mode for Redirect URIs I am getting an error when I try to login via facebook.
The callback URL formed at the time of Facebook login is of this format -
https://example.com/accounts/facebook/login/callback/?code=AQB7W48oY-1XxZv2xU9iahxS80ZPs4oBNLlXWTY7Y93dclyIElEPG-jWKB5ELV7Pv11ckcRYg3L67Wfcz6xqC8yhNLBaFaOQjd4F2AEp8nfScltnY3LoY79g9NjtslCSbQnSlc_hDdBm_rxQtScz-rLChNvAJaky3KYMG_USSTkm9qdyvw5lIMdcIHQjz3CTF8KdgmuFG1T8_WvVqdGDEpfhC_PD7w5tnkcChBEowHnWR656DYa1wrMR1fbP2rqxBocNn6fKPCy_GM_DZynPp8mx0F0YP55vzw2Kv8KchB2nxCaHwQ4dRvJq785w5CfCgDVc6REhbc3CNG2KqZxdxjuG&state=eukVyjHYk04X#_=_
This URL contains the query params code and state because of which it is not an exact match and I checked it via Redirect URI to Check which reported it as invalid.
So on the authentication_error.html I get the following error.
{'provider': 'facebook', 'code': 'unknown', 'exception':
OAuth2Error('Error retrieving access token:
b'{"error":{"message":"Can\'t load URL: The domain of this URL
isn\'t included in the app\'s domains. To be able to load this
URL, add all domains and sub-domains of your app to the App Domains
field in your app
settings.","type":"OAuthException","code":191,"fbtrace_id":"AxoTkIBeoUSKsxuWvMx-Wg4"}}'',)}
My Valid OAuth Redirect URIs has the following URL's
https://example.com/accounts/facebook/login/callback/
https://www.example.com/accounts/facebook/login/callback/
Please help me with this issue, I have looked into all the existing issue but haven't found a solution.
For anyone facing a similar issue, it could be because you missed to add this line to your settings.py file.
ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'https'

How to show email prefilled in google oauth sign in form

I am using WSO2 as identity server and google authenticator as the identity provider. Login is working correctly. On my web application, I am asking the user to enter his email and then showing google login form. I want to show this email to be prefilled this form. Thanks.
You can do it. For that, you need to customize the OpenIDConnectAuthenticator.java to pass the login_hint to google.
Clone https://github.com/wso2-extensions/identity-outbound-auth-oidc.git.
It is recommended to checkout to the org.wso2.carbon.identity.application.authenticator.oidc version in your server(you can find it in IS_HOME/repository/components/dropins/)
Add these lines before response.sendRedirect(loginPage); in OpenIDConnectAuthenticator.java
String[] usernames = context.getAuthenticationRequest().getRequestQueryParam("username");
if (usernames != null && usernames.length > 0) {
loginPage = loginPage + "&login_hint=" + usernames[0];
}
These lines will get the username from the authentication initiation request and send it as login_hint to google.
Build the component using the following command.
mvn clean install
This will create org.wso2.carbon.identity.application.authenticator.oidc-5.1.17.jar in target folder.
Replace the existing org.wso2.carbon.identity.application.authenticator.oidc-.jar in the IS_HOME/repository/components/dropins folder.
Restart the IS server
When sending authentication request to IS append username=senthalank#gmail.com as url param
For example,
https://localhost:9443/oauth2/authorize?response_type=code&client_id=<cliend_id>&redirect_uri=http://localhost:8080/playground2/oauth2client&scope=openid&username=senthalank#gmail.com

django socialauth twitter , google oauth , facebook does not work

This is my first post, and I have a problem I could not make it work django OMAB socialauth of three things I just need to google, facebook, and twitter, google works well with open id, but not much twitter and I put in my
settings. py:
TWITTER_CONSUMER_KEY = '00' this is no real
TWITTER_CONSUMER_SECRET = '00' this is no real
FACEBOOK_APP_ID = '' ihave no key
FACEBOOK_API_SECRET = ''
LINKEDIN_CONSUMER_KEY = ''
LINKEDIN_CONSUMER_SECRET = ''
ORKUT_CONSUMER_KEY = ''
ORKUT_CONSUMER_SECRET = ''ihave no key
GOOGLE_OAUTH2_CLIENT_ID = ''
GOOGLE_OAUTH2_CLIENT_SECRET = ''
SOCIAL_AUTH_CREATE_USERS = True
SOCIAL_AUTH_FORCE_RANDOM_USERNAME = False
SOCIAL_AUTH_DEFAULT_USERNAME = 'socialauth_user'
SOCIAL_AUTH_COMPLETE_URL_NAME = 'socialauth_complete'
LOGIN_ERROR_URL = '/login/error/'
#SOCIAL_AUTH_USER_MODEL = 'app.CustomUser'
SOCIAL_AUTH_ERROR_KEY = 'socialauth_error'
GITHUB_APP_ID = ''
GITHUB_API_SECRET = ''
FOURSQUARE_CONSUMER_KEY = ''
FOURSQUARE_CONSUMER_SECRET = ''
LOGIN_URL = '/login-form/'
LOGIN_REDIRECT_URL = '/'
LOGIN_ERROR_URL = '/login-error/'
I am using the example that comes in the zip of OMAB socialauth django , but not working.
When I created my twitter app, I wrote my domain www.sisvei.com , I am testing locally socialauth django ie 127.0.0.1:8000, then sign in with twitter sends me to this url:
http://127.0.0.1:8000/login/error/ and a message saying is the Incorrect authentication service
this happens with facebook and google oauth and oauth2
I'm new to django and I this much work comprising this part of django socialath hopefully help me, thank you very much.
You need to be more specific on "why it doesn't work". Where are you getting the errors?
When debugging a third-party oauth/openid app in Django, generally it boils down to:
configuration & keys - did you make sure to obtain all of the necessary API keys for the services you will be using, and to add them to your configuration?
urls - did you remember to add the necessary urlpatterns to your base urls.py file?
authentication setup on the server - often, you'll need to have a file available or respond with a specific header when the authentication service hits your server. Have you checked to make sure that is set up?
databases - have you run syncdb after installing the app? Are all the tables set up?
templates - if the third party app requires you to set up templates, do you have them set up?
custom views - are you using custom views? If so, try using the built-in views that came with the third party app first, to see if they work
After those are confirmed, you're going to want to be able to see what requests are taking place. Use the debugger included in Chrome/Safari, or get the web developer add-on for Firefox, and look at the network requests as they happen. Do you see HTTP responses other than 200 (say, 404, 500, 403, etc?) those mean that the services aren't responding correctly.
From your error, it looks like you have not correctly set up your callback URL on Twitter. It should be sending you to www.sisvei.com, not 127.0.0.1. Alternatively, check the URL when you get to the Twitter login page -- is the callback URL in the URL, and is it pointing to 127.0.0.1? Then Django is sending it the wrong callback URL.
Finally this:
I wrote my domain www.sisvei.com python does not support this
Is unclear. As far as I know, Python doesn't care what the domain is.
WAIT A MINUTE ...
Are you using runserver? Are you getting the following error?
Error: "www.sisvei.com" is not a valid port number or address:port pair.
If so, there is an easy fix! Just run it like so:
python manage.py runserver www.sisvei.com:80
That should resolve your error if that's what's happening. You're probably running it as
python manage.py runserver 127.0.0.1
127.0.0.1 is a reserved IP address that points back to localhost, your own computer. As a result, it is not possible to use it for authentication or any other purpose outside of programs running on your own machine. See this article for more info.
I'm not sure, but I might be having similar problems, oscar. For me, SocialAuth was generating an AuthenticationURL for facebook, foursquare and hotmail, but not for google, twitter or any of the other address it supports. I think it may be something wrong with the API, so I posted an issue on the social-auth google group...you may want to check there to see if anyone updates!!
https://code.google.com/p/socialauth/issues/detail?id=282&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Summary%20Modified

Django-social-auth google oauth token usage

I'm using Django-socila-auth plugin. It uses google API for Oauth 1.0 Authentication. Question is have anybody used it with google python API (gdata). I mean how to apply auth session_token, stored in django-social-auth model to my api call.
Can you help me with code to get this token from model and apply to gdata.PhotoService() instance. For now it is like this:
#getting model instance from django-social-auth model
association = Association.objects.get(user=request.user)
google_session_token=association.handle
google_secret=association.secret
#token string from django-social-auth
#model Association field "handle" looks like:
#google_session_token = '.......XG84PjwytqJkvr8WQhDxm1w-JplWK5zPndSHB13f.........'
gd_client = gdata.photos.service.PhotosService()
gd_client.debug = 'true'
gd_client.auth_token = google_session_token
#image.image is a file field, but problem not in this.
#it tries to send file in debug text.
#It just recieves 403 unauthorised callback.
photo = gd_client.InsertPhotoSimple(
'/data/feed/api/user/default/albumid/default', 'New Photo',
'Uploaded using the API', image.image, content_type='image/jpeg')
I'm recieving error
403 Invalid token string.
I understand that it needs secret too but how to apply it to API for auth?(To receive authorization to post photos.). BTW I added Picassa feed URL, as an option string for social-auth to ask permissions, so token I have asks for Picassa feed permissions when authorizing with google.
BTW. Google tutorial I've used is: here
I understand it's Oauth 1.0 rather than AusSub, but question is:
how to authenticate with token and secret I have and post a photo with this permission?
Just to answer my own problem. I used wrong way to do it, because problem in 'gd_client' and AuthSub.
It must check token on server. And it can not do it on localhost. You need to look ahead to Oauth/Oauth2 for better debugging and so on... No matter that it is much complex than AuthSub