AWS Cognito as Django authentication back-end for web site - python

My reading of Cognito is that it can be used in place of a local Django admin database to authenticate users of a website. However I am not finding any soup-to-nuts examples of a basic "Hello, World" app with a login screen that goes through Cognito. I would very much appreciate it if someone could post an article that shows, step-by-step, how to create a Hello World Django app and a Cognito user pool, and then how to replace the default authentication in Django with a call to AWS Cognito.
In particular I need to know how to gather the information from the Cognito admin site that is needed to set up a call to Cognito API to authenticate a user.
There are two cases to consider: App user login to App, and Admin login to django Admin URL of site. I assume that I would want to use Cognito for both cases, otherwise I am leaving a potential hole where the Admin URL is using a weaker login technology.
Current answers on AWS forums and StackExchange either say:
(1) It is a waste of time to use Cognito for authenticating a website, it is only for access to AWS resources
(2) It is not a waste of time. I am about to give up. I have gone as far as creating a sample Cognito user pool and user groups, and of scouring the web for proper examples of this use case. (None found, or I wouldn't be writing.)
(3) https://github.com/capless/warrant, https://github.com/metametricsinc/django-warrant are two possible solution from the aws forums.

If you are reading this, you probably googled "aws cognito django" xD.
I just want to share what I did in order to get this thing to work:
Django-Warrant. Great aws cognito wrapper package.
Make sure to understand your current User model structure. If you use custom user model, don't forget to map it using COGNITO_ATTR_MAPPING setting.
Change your authentication to support 3rd party connectivity. When you get from the client some Cognito token, convert it into your own token using oAuth/JWT/Session.
Rethink your login/register process. Do you want different registration? The django-warrant package supports it...
At the end of the day, this is a GREAT solution for fast authentication.

To add to the accepted answer, there is a simple but very important extra step that I found was necessary to take to use django-warrant with Django 2.0:
The conditional in backend.py in the root package needs to be changed from:
if DJANGO_VERSION[1] > 10
to:
if DJANGO_VERSION[1] > 10 or DJANGO_VERSION[0] > 1:
Using django-warrant with Zappa and AWS Lambda:
The project I am working on also uses Zappa to enable the serverless deployment of my Django app to AWS Lambda. Although the above code fixed django-warrant for me when testing locally, after deploying the app to the Lambda environment, I had another significant issue stemming from some of django-warrant's supporting packages - primarily related to python-jose-pycryptodome, which django-warrant uses during the authentication process. The issue showed itself in the form of a FileNotFound error related to the Crypto._SHA256 file. This error appears to have been caused because pycryptodome expects different files to be available in the Crypto package at runtime on Windows (which I am developing on) and Linux (the Lambda environment) respectively. I ended up solving this issue by downloading the Linux version of pycryptodome and merging its Crypto package with the Crypto package from the Windows version.
TLDR: If you want to use django-warrant with AWS Lambda and you are developing on a Windows machine, make sure to download the Linux version of pycryptodome and merge its Crypto package with the same from the Windows version.
Note: The versions of pycryptodome and python-jose (not python-jose-cryptodome) that I ended up using to achieve the above were 3.7.2 and 3.0.1 respectively.

Related

How does the `gcloud` CLI use OAuth2 to authenticate a user?

I'm trying to mimic the flow for authenticating with GCP using the gcloud CLI in a Go project. In this case, I can't just shell out to gcloud using the os package because I have to assume it's not installed on the system. I also need to avoid having the user go in and set an OAuth2 client_id and client_secret in the developer console since the gcloud CLI doesn't seem to require it.
I was trying to look through the Python code for gcloud and I can sort of see what it's doing but it's a bit difficult to follow since I'm not super experienced in Python and it seems like there are many layers of abstraction in the authentication code that are a bit hard to break through.
I can see the GCP URLs (the ones that you open in the browser when doing gcloud auth login) have a client_id but they don't have a client_secret. They also look like they do PKCE but I'm not super familiar with how that works. I also can't figure out exactly where they get the client_id from. If it's somehow bundled with the gcloud CLI I can't find it anywhere.

Command line user interface instead of web-based interface for django?

I have built a web platform with Django. Users with Staff status can log into Django-admin through their web browsers and add, remove or alter different objects, upload files, etc.
Now I want to build a command line tool to enable users to do these tasks via command line. The users need to authenticate in command line, and then use different commands to perform their target operation.
Think a command line git client to github.
Of course it's possible to authenticate and send form data using request or cURL. But is there any standard, better way of doing this? Is there any utility/library for this, maybe a Django/python one?
This looks like a '2-component' thing.
API
You will have to expose the desired functionality via an (RESTful) API.
Two common and very good libraries are tastypie and Django REST Framework.
They help you building APIs in a fast and flexible way - think about it as 'Django admin' for APIs.
Client
For request handling I would suggest to have a look at the python-requests library.
PS:
If you're interested - we did build a (quick, ugly, dirty & buggy) python client that interacts with our Django based service platform. You can find it on GitHub

Access Google cloud endpoints on a non-existent version label

I have two apps, my_app and my_endpoint_app. I can access my_endpoint_app with any version label in the URL I want and it will automatically route to the default version if it does not match an existing version.
Example:
https://josh-dot-my_endpoint_app.appspot.com/ will respond with the default version since there is no josh version deployed.
If I try to do the same with a Google Cloud Endpoint service call, I get a Not Found error.
Example:
The unsuccessful https://josh-dot-my_endpoint_app.appspot.com/_ah/api/myendpoint vs the working https://my_endpoint_app.appspot.com/_ah/api/myendpoint
I have a couple of Google AppEngine applications that communicate with each other via Cloud Endpoints.
Under normal usage this is OK because I know the version beforehand and avoid these errors. In our development environment, this falls apart. In order to support feature branches and testing in isolation, we push our code up to appspot using the -V switch of appcfg.py.
Example:
appcfg.py -A my_app -V josh update .
Now I can access my feature branch at https://josh-dot-my_app.appspot.com. In order to support some version label hackery, I dynamically calculate the right endpoint app to call with something like s/my_app/my_endpont_app/g and then make my service calls there. This fails because of the dynamic version label not existing. If I push a version label with that name it completes as expected.
Is there any way to get Cloud Endpoints to answer on non-existent version label hostnames?
Scenarios that I want to support
https://my_endpoint_app.appspot.com/_ah/api/myendpoint
Main application URL, routes to default version
https://josh-dot-my_endpoint_app.appspot.com/_ah/api/myendpoint
Version does not exist, should route to default version
https://new-feature-dot-my_endpoint_app.appspot.com/_ah/api/myendpoint
Version new-feature exists, should route to new-feature version so that we can test new code in isolation before merging into the main code branch. This would be internal apis that the current endpoints might make use of without changing what the endpoint accomplishes. (performance improvements, etc)
You can reroute any Url to any module/version via the dispatch file.

using dropbox as a server for my django app

I dont know if at all i make any sense, but this popped up in my mind. Can we use the 2gb free hosting of dropbox to put our django app over there and do some hacks to run our app?
No, it's not possible.
If you want to use dropbox as the hosting, you can put static pages, meaning just the html files with CSS and javascript because those files can be retrieved by doing a simple GET request.
Hosting a python code is not possible as it requires server side calculations & dropbox is just for saving files.
See the official wiki for the available hosts. https://code.djangoproject.com/wiki/DjangoFriendlyWebHosts
The point you need to understand is: can you run django without djagno installed? Can django be installed on a usb-drive? Dropbox is but a cloud storage service NOT cloud hosting service. To store you do not require RAM and processors while for hosting you do.
Hence the answer is NO. If you are okay with configuring apache etc. you can go for VPS. If not try some managed servers. If you dont want to spend much and are looking at free hosting solutions for django a few of them are:
kodingen.com
shellmix.com
http://0x2a-dc.com/index.php?name=shop&cat=6
http://www.heliohost.org/home/
http://bitnami.org/cloud
https://www.alwaysdata.com/
more data:
http://freedjangohosting.com/
http://djangohosting.com/
https://code.djangoproject.com/wiki/DjangoFriendlyWebHosts
Yes its possible! PythonAnywhere.com offers that!
What pythonanywhere does is pretty simple. They integrate your dropbox account with their one. When you want to create a Django app, all you got to do is, direct the platform to store the app in your dropbox folder!
Now, you can open your Django app in your PC and edit it (wait for some time to sync)..restart the app, it works! I practically tried.
Tip: There are many cloud platforms which offer great services for free. Openshift, Heroku, Google App Engine are to name a few!
No, you can't use DropBox to serve a Django Website, as doing so requires Python code to be run, when DropBox is only for saving & serving files.
You can, however, find free hosting for your Django needs, among which:
Heroku, originally meant for Ruby hosting, but now allows you to do Python hosting. I didn't find it particularly easy to use with Django though.
ep.io, Python-specific hosting, but invite-only for the moment - it's possible to get an invite by sending an email, explaining your project & your needs though. Offers you free SSL on *.ep.io, which is pretty nice, and they've got great service.
Dotcloud, not platform specific, but my personal favorite. It's pretty easy to get started, and the CLI allows you to do a lot (but the downside is that you need it a lot too). If you're not afraid of CLI, it's great.
Being said its not possible from dropbox to do that you can use very simple cloud hosting as told ahead,
I might be late for answer but you can get free cloud hosting from Linux Fedora company called RedHat. Their cloud product is available for free which supports django hosting. I tried it my own
Openshift Free Cloud Hosting
In addition to what Thomas posted, some other options for free django hosting:
Amazon Compute Instance (free for one year, free sign up).
Google App Engine (free limits,django howto).
OpenShift (django howto).

Is it possible to deploy one GAE application from another GAE application?

In order to redeploy a GAE application, I currently have to install the GAE deployment tools on the system that I am using for deployment. While this process is relatively straight forward, the deployment process is a manual process that does not work from behind a firewall and the deployment tools must be installed on every machine that will be used for updating GAE apps. A more ideal solution would be if I could update a GAE application from another GAE application that I have deployed previously. This would remove the need to have multiple systems configured to deploy apps.
Since the GAE deployment tools are written in Python and the GAE App Engine supports Python, is it possible to modify appcfg.py to work from within GAE? The use case would be to pull a project from GitHub or some other online repository and update one GAE application from another GAE app. If this is not possible, what is the limiting constraint?
Is it possible? Yes. The protocol appcfg uses to update apps is entirely HTTP-based, so there's absolutely no reason you couldn't write an app that's capable of deploying other apps (or redeploying itself - self-modifying code)! You may even be able to reuse large parts of appcfg.py to do it.
Is it easy? Probably not. It's quite likely you'll need to understand a decent chunk of appcfg's internals, and the RPCs it uses to upload new apps - not a trivial undertaking. You'll also need to store your credentials in the app, in all likelihood - though you can use a role account that is and admin only for the apps it's deploying to minimize risk there.
One limiting constraint could be the protocol that the python sdk uses to communicate with the GAE servers. If it only uses HTTP, you might be OK. but if it's anything else, you might be out of luck because you can't open a socket directly from within GAE.
What problem did you have by trying to update behind a firewall?
I've got some, but finally I manage to work around them.
About your question, the constraint is that you cannot write files into a GAE app, so even though you could possibly pull from the VCS you can't write those pulled files.
So you would have to update from outside the GAE in first place.
Anyway every machine that needs to update the GAE should have the SDK anyway just to see if they changes work.
So, If you really want to do this you have two alternatives:
Host your own "updater" site and istall the SDK there, then when you want to update log into your side ( or run a script ) and do the remote update.
Although I don't know Amazon EC2 well, I think you can do pretty much the same thing as op 1 from there.
Finally I think the password to update has to be typed always. ( you could have the SDK of the App engine and modify that, because it is open source )

Categories