Best pattern for AWS Cognito / React frontend / Django Rest backend - python

Struggling to get this fully working - here is my app workflow:
React frontend - user authenticates w/ Cognito directly (using AWS Amplify) - I've got this working fine. The frontend needs to handle this, as it makes separate direct calls to other AWS services.
DRF backend - React then makes API calls to DRF endpoints using Amplify.API, which includes the x-amz-security-token in the request header (this appears to be the Session Token returned by Amplify's call to the cognito-idp service). So now the backend has the Session Token (but not the Access Token or Refresh Token)
The backend then simply needs to verify that the frontend user (whose authenticated identity I assume is represented by the Session Token) is a valid and currently authenticated user according to Cognito. So the backend needs to make a separate call to Cognito to verify this.
This is where I'm failing - I've looked at django-warrant, but I can't discern from the documentation whether this is appropriate for my use case (or even how to really use it - the default setup suggested results in various boto3 errors to do w/ lack of credentials, etc.). I've also looked at warrant and directly at boto3 and botocore but it is not clear to me where to make all this happen. Am I missing seeing some kind of is_user_valid and is_session_token_valid methods in these libraries?
If someone knows how to do this directly w/ django-warrant it would help, and if not a little advice on the best way forward would also be appreciated (do I write my own authentication backed or middleware to intercept the request, authenticate somehow w/ boto3 or botocore, or what?)
Many thanks

Related

Flask Backend with React Frontend, Using OAuth

This question's being asked a ton before, but I really don't think there's a clear answer anywhere (that I've read, anyway).
The Set Up
I have a Flask backend, solely serving an API. I've configured OAuth (with Google), using LoginManager. The login flow works perfectly, and I end up with session cookie, which permits me to access endpoints decorated with the #login_required decorator.
The frontend is to be written separately in React.
The Complication
The cookie set by going through the OAuth flow does not get used by the frontend doing the calling. All calls from the frontend to the backend end up with a 401, because unsurprisingly, the URL for the cookie is not the same as the URL for the backend which set it.
Idea
I have an unprotected /login endpoint, which I allow the frontend to call. Similarly the /login/callback endpoint can be called to finish the flow, and get back tokens. Could these somehow be used safely with the frontend, but with the flow still happening in the backend?
Compromise
What we've ended up with now, is the frontend doing the OAuth flow completely, then sending the token it gets along with every single call. The backend then does a check with Google every time to see if the token is indeed valid for who the frontend says it is.
This is less than ideal.
What is the recommended and correct way of separating the frontend and backend, but keeping the auth in the backend?

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

Securing Google Cloud Functions using WSO2

I'm writing an application (web and mobile) where I would like to use WSO2 for user authentication, authorization and SSO.
My mobile app will authenticate the users against the WSO2-is.
All the API's used by the app are google cloud functions written in python.
I would like to bring a security layer to my GCF's.
From my understanding I can use WSO2-am as a bridge between the app and the GCF to provide security, but I would like to leverage the high scalability of the GCF archicteture and avoid the WSO2-am being a bottleneck.
Is it possible use the WSO2-am and make the GCF to check the permissions access against it, allowing the app calling the API directly instead of using the WSO2-am as a bridge ?
If yes, may you provide some documentation/blogpost/whatever that could help ?
In WSO2 APIM, the gateway does all the authentication and authorization stuff when the requests go through it (to the backend).
So, in the case of,
(1) OAuth2 tokens, the gateway talks to the key manager to validate the token, subscription (API-to-Application) and token scopes.
(2) Self-contained JWT tokens, the gateway can do all these validations itself.
So now in your case, since you don't want to send the requests through the gateway, you have to do what gateway does, within the cloud function itself. In that case, the JWT tokens will be the best choice as they can be validated without connecting to the key manager.
In addition to that, the gateway keeps a token cache so that it doesn't have to validate the same token again and again. You can have a similar cache (if possible) within your cloud functions too. However, in your case, you will have to externalize the cache due to the short-lifetime nature of cloud functions.
Here is the gateway code[1] which does the token, scopes and subscription validations. You can use it as a guide to write yours.
[1] https://github.com/wso2/carbon-apimgt/blob/master/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java

Django - allow anonymous API usage on localhost

I'm making an Ajax call in the UI to the API, so the localhost needs to be able to query the API. Users of the platform should be able to access the API, but need to use a token I already provide.
Is there a way to allow anonymous API usage locally only?
I looked into JWT and it does not seem to be the right fit.
As I've pointed out in the comments, JWTs should suffice in this case as, from what I've understood, you're not handling any extremely sensitive data (which can be hashed and not exposable to the user using JWTs as well) but want to validate each request. Using the same link you can check the validity of a token in their debugger.

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

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 :)

Categories

Resources