0% found this document useful (0 votes)
34 views6 pages

Authentication and Authorisation Cognito in Flask

This document provides a step-by-step guide for integrating AWS Cognito authentication in a Flask application, including setting up token validation and creating decorators for route protection. It also explains how to handle group validation for authorized access while allowing flexibility for routes that do not require group checks. The approach ensures both authentication and authorization are effectively managed using decorators, making it adaptable for various API requirements.

Uploaded by

Rahul Mishra
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views6 pages

Authentication and Authorisation Cognito in Flask

This document provides a step-by-step guide for integrating AWS Cognito authentication in a Flask application, including setting up token validation and creating decorators for route protection. It also explains how to handle group validation for authorized access while allowing flexibility for routes that do not require group checks. The approach ensures both authentication and authorization are effectively managed using decorators, making it adaptable for various API requirements.

Uploaded by

Rahul Mishra
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 6

https://pypi.

org/project/pycognito/

https://chatgpt.com/c/71bc6b74-e2be-4198-a293-872e57bc9d28

To handle authentication and authorization in a Flask application with AWS Cognito,


you’ll need to manually verify the JWT tokens provided by Cognito. Here's a step-
by-step guide on how to achieve this:

1. Set Up Flask Application


First, make sure you have Flask installed in your environment. If not, you can
install it using pip:

bash
Copy code
pip install Flask
2. Install Required Libraries
You'll need additional libraries for decoding and verifying JWT tokens. Install
pycognito and requests for this:

bash
Copy code
pip install pycognito requests
3. Configure Flask to Use Cognito
Create a configuration file or set environment variables for your AWS Cognito
settings. You’ll need the following information:

User Pool ID
App Client ID
Region
python
Copy code
import os

COGNITO_USER_POOL_ID = os.getenv('COGNITO_USER_POOL_ID')
COGNITO_APP_CLIENT_ID = os.getenv('COGNITO_APP_CLIENT_ID')
COGNITO_REGION = os.getenv('COGNITO_REGION')
4. Set Up Token Validation
Create a utility function to validate the JWT tokens. You’ll need to fetch the
public keys from Cognito to verify the token's signature.

python
Copy code
import requests
from pycognito import Cognito
from flask import request, jsonify, Flask

app = Flask(__name__)

def get_public_keys():
jwks_url =
f"https://cognito-idp.{COGNITO_REGION}.amazonaws.com/{COGNITO_USER_POOL_ID}/.well-
known/jwks.json"
response = requests.get(jwks_url)
response.raise_for_status()
return response.json()
def verify_token(token):
keys = get_public_keys()
cognito_user = Cognito(COGNITO_USER_POOL_ID, COGNITO_APP_CLIENT_ID)
return cognito_user.verify_token(token, keys)
5. Create an Authentication Decorator
You can create a decorator to protect your routes and ensure they are accessed only
by authenticated and authorized users.

python
Copy code
from functools import wraps
from flask import request, jsonify

def authenticate(f):
@wraps(f)
def wrapper(*args, **kwargs):
token = request.headers.get('Authorization')
if not token:
return jsonify({"message": "Missing token"}), 401

try:
# Remove "Bearer " prefix if present
if token.startswith("Bearer "):
token = token[7:]

# Verify token
claims = verify_token(token)
if claims is None:
return jsonify({"message": "Invalid token"}), 401

# Add claims to request context if needed


request.user = claims
except Exception as e:
return jsonify({"message": str(e)}), 401

return f(*args, **kwargs)

return wrapper
6. Protect Your Routes
Use the authenticate decorator to protect your routes:

python
Copy code
@app.route('/update_fcm_token', methods=['POST'])
@authenticate
def update_fcm_token():
# Your logic here
return jsonify({"message": "Token updated successfully"}), 200
7. Run Your Flask Application
Run your Flask application as usual:

python
Copy code
if __name__ == '__main__':
app.run(debug=True)
8. Testing
Make sure to test your protected routes by sending requests with the Authorization
header set to a valid Cognito token.
Summary
Token Validation: Fetch public keys from Cognito and use them to verify the JWT
tokens.
Decorator: Create a decorator to check for the presence and validity of the token
before granting access to the route.
Integration: Use the decorator on routes you want to protect.
This approach ensures that only authenticated and authorized users can access your
Flask API endpoints.

You said:
what if i have to check groups from cognito and then provide access to authorised
person
like i did in aws chalice

@app.route('/add_m_user', methods=['POST'], authorizer=authorizer,


cors=cors_config)
def create_item():
try:

cognito_groups = app.current_request.context["authorizer"]["claims"]
["cognito:groups"]
print(cognito_groups)
groups = ["Superadmin", "Admin"]
if cognito_groups not in groups:

err = {}
err["code"] = "401"
err['message'] = "This Authorization error"
return Response.respond(err)
except Exception as e:
err = {}
err["code"] = "401"
err['message'] = "Authorization error"
ChatGPT said:
ChatGPT
To check Cognito user groups and provide access based on group membership in a
Flask application, you can extend the authentication decorator to include group
validation. Here’s how you can achieve this:

1. Set Up Group Validation


First, update your verify_token function to extract user claims, including group
information, from the token.

python
Copy code
import jwt
from flask import request, jsonify, Flask

app = Flask(__name__)

def get_public_keys():
jwks_url =
f"https://cognito-idp.{COGNITO_REGION}.amazonaws.com/{COGNITO_USER_POOL_ID}/.well-
known/jwks.json"
response = requests.get(jwks_url)
response.raise_for_status()
return response.json()

def verify_token(token):
keys = get_public_keys()
try:
# Decode token using public keys
header = jwt.get_unverified_header(token)
key = next(key for key in keys['keys'] if key['kid'] == header['kid'])
public_key = jwt.algorithms.RSAAlgorithm.from_jwk(key)
decoded_token = jwt.decode(token, public_key, algorithms=['RS256'],
audience=COGNITO_APP_CLIENT_ID)
return decoded_token
except Exception as e:
print(f"Token verification failed: {e}")
return None
2. Create a Group Validation Decorator
Extend the authenticate decorator to check for specific groups:

python
Copy code
from functools import wraps

def authorize(groups):
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
token = request.headers.get('Authorization')
if not token:
return jsonify({"message": "Missing token"}), 401

try:
# Remove "Bearer " prefix if present
if token.startswith("Bearer "):
token = token[7:]

# Verify token
claims = verify_token(token)
if claims is None:
return jsonify({"message": "Invalid token"}), 401

# Check user groups


cognito_groups = claims.get("cognito:groups", [])
if not any(group in cognito_groups for group in groups):
return jsonify({"message": "Unauthorized access"}), 403

# Add claims to request context if needed


request.user = claims
except Exception as e:
return jsonify({"message": f"Authorization error: {str(e)}"}), 401

return f(*args, **kwargs)

return wrapper
return decorator
3. Protect Routes with Group Validation
Apply the authorize decorator to your routes, specifying the groups that are
allowed:
python
Copy code
@app.route('/add_m_user', methods=['POST'])
@authorize(groups=["Superadmin", "Admin"])
def create_item():
# Your logic here
return jsonify({"message": "User added successfully"}), 200
4. Testing
Test your protected routes by sending requests with the Authorization header set to
a valid Cognito token. Ensure that only users in the specified groups can access
the routes.

Summary
Token Validation: Decode and verify the JWT token using public keys.
Group Validation: Check the cognito:groups claim to ensure the user belongs to the
required groups.
Decorators: Use decorators to protect routes and enforce both authentication and
authorization.
This approach allows you to handle both authentication and authorization based on
Cognito user groups in your Flask application.

You said:
there may be a possibility that group checking is not necessary for few apis then
how to handle?
ChatGPT said:
ChatGPT
If you have some APIs where group checking is not required, you can design your
decorators to be flexible, allowing group validation to be optional. Here’s how you
can adapt your Flask application to handle both cases:

1. Modify the authorize Decorator


Adjust the authorize decorator to accept an optional list of groups. If no groups
are provided, the decorator will skip the group validation:

python
Copy code
from functools import wraps
from flask import request, jsonify

def authorize(groups=None):
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
token = request.headers.get('Authorization')
if not token:
return jsonify({"message": "Missing token"}), 401

try:
# Remove "Bearer " prefix if present
if token.startswith("Bearer "):
token = token[7:]

# Verify token
claims = verify_token(token)
if claims is None:
return jsonify({"message": "Invalid token"}), 401

# Check user groups if provided


if groups:
cognito_groups = claims.get("cognito:groups", [])
if not any(group in cognito_groups for group in groups):
return jsonify({"message": "Unauthorized access"}), 403

# Add claims to request context if needed


request.user = claims
except Exception as e:
return jsonify({"message": f"Authorization error: {str(e)}"}), 401

return f(*args, **kwargs)

return wrapper
return decorator
2. Use the Decorator in Routes
Apply the authorize decorator to routes where group checking is required, and omit
the groups parameter for routes where group checking is not necessary:

python
Copy code
@app.route('/add_m_user', methods=['POST'])
@authorize(groups=["Superadmin", "Admin"])
def create_item():
# Your logic here
return jsonify({"message": "User added successfully"}), 200

@app.route('/public_resource', methods=['GET'])
@authorize()
def public_resource():
# This route does not require group checking
return jsonify({"message": "Public resource accessed"}), 200
3. Handle Routes without Token Validation
If you have routes that don’t require any authentication or authorization, simply
omit the authorize decorator:

python
Copy code
@app.route('/open_resource', methods=['GET'])
def open_resource():
# This route is open to everyone
return jsonify({"message": "Open resource accessed"}), 200
Summary
Flexible Decorator: Modify the decorator to handle both group validation and non-
group validation scenarios by making the groups parameter optional.
Selective Application: Apply the authorize decorator with or without groups as
needed based on the route requirements.
No Validation Routes: Simply omit the authorize decorator for routes where
authentication and authorization are not required.
This approach allows you to use a single decorator for both protected and
unprotected routes, streamlining your code and maintaining flexibility.

You might also like