How to create an API with a "remember me" function in Flask? - python

I'm going to build an API in Flask for a (to be created) app which will be built using PhoneGap. In the API many calls will need authentication.
To get into the topic I was reading this tutorial on creating authentication for a Flask-built API. In this tutorial they first show how a user can use basic password authentication for every call, after which token based authentication is introduced.
As far as I understand, the client who calls the API should simply get a token and authenticate every subsequent call with that. In the meantime, the client should keep track of time and either get a new token every 9 minutes (before the old token expires) or simply keep on calling with the token until the client gets an Unauhorized Access message. Am I understanding this correctly?
Moving on, I wonder how it works with Apps on which you login on your phone and then are always logged in whenever you open the app (like for example the Facebook app). This is obviously more convenient to the user than always needing to provide the username/password and I would like to implement something like that as well. I wonder though; how is a permanent logged in feature like this implemented on the server side? Is it done by providing the password and username for every call, or using a never expiring token, or yet a different way?
All tips are welcome!

I've done what you want to do with:
Flask-security https://pythonhosted.org/Flask-Security/:
To manage users and permissions.
Flask-oauth-lib https://flask-oauthlib.readthedocs.org/en/latest/:
Provide oauth functionnality.
So, you have to take a look at Oauth flow, implements a user backend (like Flask-security) and implements an oauth server (with flask oauth lib for example) and bind it to your user backend.
After that, it's oauth standard flow. You just have to give the right token on each api calls and TADA !
With this way you can also, if you want, give access to your api to third-party app thanks to oAuth :)

Related

How to sign in with Firebase Auth using python

I'm trying to make an app and I can't figure out how to sign in to a user with the python library firebase_admin. I don't have any code as of this moment. Let me know if you can help me out.
The Firebase Admin SDK is designed to be used in a trusted environment, such as your development machine, a server you control, or Cloud Functions/Cloud Run. It gets its authorization from its context or from a credentials file that you provide to it, and which gives it full, administrative access to the project. Therefor it doesn't need, and doesn't have a way, to sign in as a specific user.
If your use-case requires that you sign a user in to Firebase from your Python code, you can consider calling the REST API to authenticate. But the use-case for this would typically be to then pass the ID token you receive back to a user (similar to the use-case in creating custom tokens).

Microsoft MSAL React SPA, and RESTful Django API

I don't know why I can't find confirmation in the docs, maybe I am not navigating them correctly, although MSAL seems to have options to fit it into any application. This is my first time integrating a SAML sso procedure into any of my web-apps. I am just looking for some clarity on the correct, and secure way to verify the person attempting to login, is actually logged in with the IDP.
I am confused at the part after confirmation of login is given to my redirect API, I currently have it all happening on the front-end, then submitting the response to my back-end. Which is a RESTful API built with Django, and postgres database. At this point, I am thinking I need to verify my accessToken for authenticity, but I am unsure if I should be creating another PublicClient instance in python, and then sending the same commands to the IDP.
To guess at this point, I'm thinking this is wrong, as I need to verify the token, rather than get another Access and Refresh token. I'm thinking I just need to verify there is a session open with the IDP, and that the Access Token matches. Can anyone shed some light on this, possibly provide even just some direction.
The client Python Django Web App uses the Microsoft Authentication Library (MSAL) to sign-in and obtain an Access Token from Azure AD.
The access token is used as a bearer token to authorize the user to call the Python Flask Web API protected by Azure AD.
The Python Flask Web API then receives a token for Azure Resource Management API using the On-Behalf-Of flow.
To learn more about handing access token validation at the API layer, look into this sample walkthrough: https://github.com/Azure-Samples/ms-identity-python-on-behalf-of#about-the-code
https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens#validating-tokens

Accessing the HipChat API With Username and Password

I'm attempting to write a simple script that I can run from my command line that will send warning messages to certain users on HipChat, and I've run into some issues around authentication. Ideally, I'd like to have the script prompt the user for their HipChat username and password, and use them to log into the Hipchat API. However, it seems that Hipchat doesn't offer this functionality, and I'm not sure what to do.
The documentation seems to suggest I manually generate a token, and use that instead. While this is definitely an option, it seems a little less user friendly, so I wanted to double check that there wasn't an alternative before going ahead. I want to avoid the installation and OAuth flows as much as possible (I don't think they're an option).
Any thoughts? I'm open to alternative suggestions, although it really seems like Basic Auth or simple token generation would be an option.
The hipchat APIs don't support username+password as authentication, for security reasons (you don't want your password flowing through every API call).
The OAuth flow you mention is used for the integrations. If you want to try the API manually (or to script them), there's a simpler auth flow:
Generate an API token by going to https://hipchat.com/account/api (make sure to select the right scopes for the APIs you want to call)
Call the API with the token as an authorization header Authorization: Bearer YOUR_TOKEN
[Much less secure] Or add your authorization token to the API URL as a query parameter: https://hipchat.com/v2/room?auth_token=YOUR_TOKEN
Full information is available here: https://developer.atlassian.com/hipchat/guide/hipchat-rest-api

Django OAuth2 provider and resources on different servers?

I'm looking to set up Django to use OAuth2 to authenticate users for a service that I'm running, but I'm having a bit of difficulty understanding how the tokens are passed around.
I've been working my way through this tutorial: https://django-oauth-toolkit.readthedocs.org/en/0.7.0/tutorial/tutorial_01.html. I've been able to get a server up and running as the OAuth provider, and it seems to be working as it should. I'm able to log in to it and set up an application. The difficulty I'm having is figuring out how the various tokens are passed around.
Suppose that my OAuth provider is sitting on one server - let's call this Provider.com - and my service that I'm wanting authenticated is on service.com. When a user first tries to make a request to the service, they first need to authenticate against the Provider. So they click on a login button which directs them to Provider.com. They enter their credentials. If everything is set up correctly on the server, they should be presented with a prompt that gives them a chance to allow or deny Service.com from accessing their account on Provider.com. Supposing that they click Allow, they are then redirected to Service.com, and are given a token. On future calls to Service.com, they pass in the token, and are, in theory, able to make authenticated calls.
The problem I'm having understanding is this: At what point do the Provider and the Service communicate? If a call comes in to the Service, how does it know that the authentication token passed in with the call is valid? There's know way it could know that a particular token is valid unless: A) it recognizes that same token from a previous call which was also authenticated or B) it talks to the OAuth 2 provider and verifies the authenticity of the token.
A diagram like the one found here shows the process in the browser:
At the end of this, it has the Client App sending the authentication code, client id, and client secret to the OAuth2 provider. In the previously mentioned tutorial, it isn't really clear how this is actually done. In the tutorial, the provider and the service are on the same machine, and it would appear that they also share the same database.
This this brings about my question: How does one host a Django-based OAuth provider on a separate server than the resource/service being accessed? Is this possible?
From this other post, it indicates that this might not be possible: https://stackoverflow.com/a/26656538/1096385 Is that indeed the case, at least with the existing Django OAuth2 provider framework?
It depends on the oauth2 flow you're using. It seems like you're using authentication code.
In that case:
service.com sends the browser to provider.com for user authentication (uri contains service.com client_id and redirect_uri)
User authenticates on provider.com, then the browser is redirected to service.com's redirect_uri with a ?code parameter.
On your server side, handle this code parameter and ask for a token with it.
See https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#web-server-apps

How to make 'access_type=offline' / server-only OAuth2 operations on GAE/Python?

This post is a followup to How to do OAuth-requiring operations in a GAE cron job?, where I realized I'm mis-using the #oauth_required decorator from OAuth2DecoratorFromClientSecrets.
As described by the OAuth 2.0 explained presentation, Oauth 2.0 solves the problem of:
Building a service...
... accessed by a user...
... and accessing the user's data from a third party.
That's what #oauth_required abstracts, and it does it well (currently my app "works": if I trigger the refresh page, I'm being asked to authorize access to my youtube data to my app, and the rest follows). But that's not what I want! My app does something simpler, which is creating a youtube playlist every day with my credentials and without any user input. So to compare to the above 3-tier negociation, I want:
A service
... accessed by users
... but only accessing "server-owned" YouTube playlist data. I don't want any access to the user's YouTube data, I just want to modify a playlist I (i.e. me / a userid persisted by the server) own.
But I still need help to do that; here is my current state:
After a few searches I learned that what I want to do is called Offline Access (emphasis mine, which is almost exactly my use case):
"In some cases, your application may need to access a Google API when the user is not present. Examples of this include backup services and applications that make blogger posts exactly at 8am on Monday morning. This style of access is called offline, and web server applications may request offline access from a user. The normal and default style of access is called online."...
→ So I should keep doing what I'm doing right now, keep requesting access to my YouTube account, but do it using the type_access=offline flag to get a token, and persist/use it for subsequent requests.
The Offline Access and Using a Refresh Token sections make total sense, but stay at a general HTTP level. Being still a newbie, I don't see how to integrate those principles into my Python code, and I didn't find any sample Python code around....
→ Could anyone help me with one Python example illustrating how and where to use this flag?
... and in particular, after studying oauth2client.appengine.OAuth2Decorator.oauth_required, I'm still not sure if I can bend it to my case, or if I should do my own thing.
→ What do you think?
Thanks for your time; if needed I'm also hanging out on irc://irc.freenode.net/#appengine as ronj.
Offline access is the default when retrieving tokens; you may have noticed this in the OAuth dialog that comes up:
Perform these operations when I'm not using the application
When your user accepts the OAuth dialog in a method decorated with decorator.oauth_required the credentials for that user will be stored in the datastore, including the refresh token.
Once you have one of these credentials objects, you can use it so authorize an HTTP object for calling APIS:
import httplib2
http = credentials.authorize(httplib2.Http())
and once authorized, it will do all the work for you. So if the access_token is expired, the first API response will be a 401 and so the credentials object will use the refresh_token to get a new access_token and make the request again.
If you know the user ID, you can retrieve the credentials from the datastore as described in How to do OAuth-requiring operations in a GAE Task Queue?:
from oauth2client.appengine import CredentialsModel
from oauth2client.appengine import StorageByKeyName
credentials = StorageByKeyName(
CredentialsModel, user_id, 'credentials').get()
Note/Gotcha:
If a user has already authorized your client ID, the subsequent times you perform OAuth for these users they will not see the OAuth dialog and you won't be given a refresh token. A refresh token can only be given if they go through the OAuth dialog, but since the user had already authorized your client ID, the spec assumes you would already have a refresh token around.
This often comes up when developers are testing OAuth, since they will go through the flow multiple times with a test account and after accepting the 2nd, 3rd, 4th, ... times, they never see the refresh token. A simple way around this is to use approval_prompt=force as an argument to the OAuth2Decorator constructor. This will force the OAuth dialog to appear every time you perform OAuth for a user.
However, this will not cause the dialog to show up every time a request is served for a given user; this would be a TERRIBLE user experience. Instead, the SACSID cookie from the request can be used (by the client library and some App Engine libraries) to determine who the current user is. Once the the library knows that current user, it can get your existing stored token/credentials for that user from the datastore and no jarring dialog will be needed.

Categories

Resources