Skip to main content

Flask: API Authentication with JWT

Flask: API Authentication with JWT

JSON Web Tokens (JWT) provide a secure, stateless method for authenticating API requests in Flask, enabling robust user authentication and authorization. Building on Flask Authentication, Flask User Registration, Flask User Login and Logout, Flask Password Hashing with Flask-Bcrypt, Flask Role-Based Access Control, Flask Protecting Routes with Flask-Login, Flask Managing User Sessions, Flask Using Flask Sessions, Flask Session Security, Flask Custom Session Backends, Flask Querying the Database, Flask Relationships in Models, Flask APIs and Microservices, Flask Building REST APIs with Flask-RESTful, and Flask Handling JSON Data, JWT authentication integrates with Flask-RESTful, Flask-JWT-Extended, Flask-SQLAlchemy, and NumPy Array Operations for secure API development. This tutorial explores Flask API authentication with JWT, covering token generation, validation, role-based access, and practical applications in RESTful APIs and microservices.


01. Why Use JWT for API Authentication?

JWT is a compact, self-contained token format that securely transmits information between parties. Benefits for Flask APIs include: - Stateless: No server-side session storage, ideal for microservices. - Secure: Digitally signed to ensure integrity and authenticity. - Flexible: Encodes user data (e.g., roles) for authorization. - Scalable: Works across distributed systems and cross-origin requests. JWT is widely used in applications like e-commerce APIs, task management systems, or IoT backends, complementing Flask-Login and custom session backends for secure user management.

Example: Basic JWT Authentication

from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, jwt_required, create_access_token

app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'jwt-secret-123'
jwt = JWTManager(app)

@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    if data.get('username') == 'admin' and data.get('password') == 'secret':
        access_token = create_access_token(identity='admin')
        return jsonify({'access_token': access_token})
    return jsonify({'error': 'Invalid credentials'}), 401

@app.route('/api/protected', methods=['GET'])
@jwt_required()
def protected():
    return jsonify({'message': 'Protected endpoint accessed'})

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/login with {"username": "admin", "password": "secret"}:
{"access_token": "eyJ..."}

GET /api/protected with Authorization: Bearer <token>:
{"message": "Protected endpoint accessed"}

GET /api/protected without token:
{"msg": "Missing Authorization Header"}

Explanation:

  • create_access_token - Generates a JWT for authenticated users.
  • jwt_required - Protects endpoints, requiring a valid JWT.
  • JWTManager - Configures JWT handling with a secret key.

02. Key Techniques for JWT Authentication

Flask with Flask-JWT-Extended provides powerful tools for JWT-based authentication. Below is a summary of key techniques and their applications:

Technique Description Use Case
Token Generation Create JWTs for authenticated users User login
Token Validation Verify JWT integrity and expiry Secure endpoints
Role-Based Access Restrict access by user roles Admin vs. user access
Database Integration Store user data for authentication Persistent user management
Refresh Tokens Extend session with refresh tokens Long-lived sessions


2.1 Token Generation

Example: Generating JWT

from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, create_access_token
from flask_bcrypt import Bcrypt

app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'jwt-secret-456'
jwt = JWTManager(app)
bcrypt = Bcrypt(app)

users = {'alice': bcrypt.generate_password_hash('password123').decode('utf-8')}

@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not request.is_json or not username or not password:
        return jsonify({'error': 'Invalid input'}), 400
    if username in users and bcrypt.check_password_hash(users[username], password):
        access_token = create_access_token(identity=username)
        return jsonify({'access_token': access_token})
    return jsonify({'error': 'Invalid credentials'}), 401

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/login with {"username": "alice", "password": "password123"}:
{"access_token": "eyJ..."}

POST /api/login with {"username": "alice", "password": "wrong"}:
{"error": "Invalid credentials"}

POST /api/login with {}:
{"error": "Invalid input"}

Explanation:

  • Validates JSON input and authenticates users with Flask-Bcrypt.
  • Generates a JWT with user identity for secure access.

2.2 Token Validation

Example: Validating JWT

from flask import Flask, jsonify
from flask_jwt_extended import JWTManager, jwt_required, get_jwt_identity

app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'jwt-secret-789'
jwt = JWTManager(app)

@app.route('/api/protected', methods=['GET'])
@jwt_required()
def protected():
    current_user = get_jwt_identity()
    return jsonify({'message': f'Access granted for {current_user}'})

if __name__ == '__main__':
    app.run(debug=True)

Output:

GET /api/protected with Authorization: Bearer <valid_token>:
{"message": "Access granted for alice"}

GET /api/protected with invalid token:
{"msg": "Invalid token"}

GET /api/protected without token:
{"msg": "Missing Authorization Header"}

Explanation:

  • jwt_required - Ensures a valid JWT is present.
  • get_jwt_identity - Retrieves the user identity from the token.

2.3 Role-Based Access Control

Example: JWT with Role-Based Access

from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, get_jwt
from flask_bcrypt import Bcrypt

app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'jwt-secret-101'
jwt = JWTManager(app)
bcrypt = Bcrypt(app)

users = {
    'alice': {'password': bcrypt.generate_password_hash('password123').decode('utf-8'), 'role': 'admin'},
    'bob': {'password': bcrypt.generate_password_hash('password456').decode('utf-8'), 'role': 'user'}
}

@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not request.is_json or not username or not password:
        return jsonify({'error': 'Invalid input'}), 400
    if username in users and bcrypt.check_password_hash(users[username]['password'], password):
        access_token = create_access_token(identity=username, additional_claims={'role': users[username]['role']})
        return jsonify({'access_token': access_token})
    return jsonify({'error': 'Invalid credentials'}), 401

@app.route('/api/admin', methods=['GET'])
@jwt_required()
def admin_only():
    claims = get_jwt()
    if claims['role'] != 'admin':
        return jsonify({'error': 'Admin access required'}), 403
    return jsonify({'message': 'Admin endpoint accessed'})

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/login with {"username": "alice", "password": "password123"}:
{"access_token": "eyJ..."}

GET /api/admin with alice's token:
{"message": "Admin endpoint accessed"}

POST /api/login with {"username": "bob", "password": "password456"}:
{"access_token": "eyJ..."}

GET /api/admin with bob's token:
{"error": "Admin access required"}

Explanation:

  • additional_claims - Embeds role information in the JWT.
  • get_jwt - Retrieves claims to enforce role-based access.

2.4 Database Integration with SQLAlchemy

Example: JWT with SQLAlchemy

from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, jwt_required, create_access_token
from flask_bcrypt import Bcrypt

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['JWT_SECRET_KEY'] = 'jwt-secret-202'
db = SQLAlchemy(app)
jwt = JWTManager(app)
bcrypt = Bcrypt(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(120), nullable=False)
    role = db.Column(db.String(20), nullable=False, default='user')

@app.route('/api/register', methods=['POST'])
def register():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    role = data.get('role', 'user')
    if not request.is_json or not username or not password:
        return jsonify({'error': 'Invalid input'}), 400
    if User.query.filter_by(username=username).first():
        return jsonify({'error': 'Username exists'}), 400
    user = User(username=username, password_hash=bcrypt.generate_password_hash(password).decode('utf-8'), role=role)
    db.session.add(user)
    db.session.commit()
    return jsonify({'message': 'User created'}), 201

@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not request.is_json or not username or not password:
        return jsonify({'error': 'Invalid input'}), 400
    user = User.query.filter_by(username=username).first()
    if user and bcrypt.check_password_hash(user.password_hash, password):
        access_token = create_access_token(identity=user.id, additional_claims={'role': user.role})
        return jsonify({'access_token': access_token})
    return jsonify({'error': 'Invalid credentials'}), 401

@app.route('/api/users/<int:user_id>', methods=['GET'])
@jwt_required()
def get_user(user_id):
    user = User.query.get_or_404(user_id)
    return jsonify({'id': user.id, 'username': user.username, 'role': user.role})

with app.app_context():
    db.create_all()

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/register with {"username": "alice", "password": "password123", "role": "admin"}:
{"message": "User created"}

POST /api/login with {"username": "alice", "password": "password123"}:
{"access_token": "eyJ..."}

GET /api/users/1 with Authorization: Bearer <token>:
{"id": 1, "username": "alice", "role": "admin"}

Explanation:

  • Uses Flask-SQLAlchemy for persistent user storage.
  • Combines registration, login, and protected endpoints with JWT.

2.5 Refresh Tokens

Example: JWT with Refresh Tokens

from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, create_refresh_token, jwt_refresh_token_required
from flask_bcrypt import Bcrypt

app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'jwt-secret-303'
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = 900  # 15 minutes
app.config['JWT_REFRESH_TOKEN_EXPIRES'] = 2592000  # 30 days
jwt = JWTManager(app)
bcrypt = Bcrypt(app)

users = {'alice': bcrypt.generate_password_hash('password123').decode('utf-8')}

@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not request.is_json or not username or not password:
        return jsonify({'error': 'Invalid input'}), 400
    if username in users and bcrypt.check_password_hash(users[username], password):
        access_token = create_access_token(identity=username)
        refresh_token = create_refresh_token(identity=username)
        return jsonify({'access_token': access_token, 'refresh_token': refresh_token})
    return jsonify({'error': 'Invalid credentials'}), 401

@app.route('/api/refresh', methods=['POST'])
@jwt_refresh_token_required()
def refresh():
    current_user = get_jwt_identity()
    new_access_token = create_access_token(identity=current_user)
    return jsonify({'access_token': new_access_token})

@app.route('/api/protected', methods=['GET'])
@jwt_required()
def protected():
    current_user = get_jwt_identity()
    return jsonify({'message': f'Access granted for {current_user}'})

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/login with {"username": "alice", "password": "password123"}:
{"access_token": "eyJ...", "refresh_token": "eyJ..."}

POST /api/refresh with Authorization: Bearer <refresh_token>:
{"access_token": "eyJ..."}

GET /api/protected with Authorization: Bearer <access_token>:
{"message": "Access granted for alice"}

Explanation:

  • create_refresh_token - Generates a long-lived token for refreshing access tokens.
  • jwt_refresh_token_required - Protects the refresh endpoint.

2.6 Insecure JWT Implementation

Example: Insecure JWT Authentication

from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, jwt_required, create_access_token

app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'weak'  # Insecure key
jwt = JWTManager(app)

@app.route('/api/login', methods=['POST'])
def login():
    # No input validation or secure password check
    data = request.get_json()
    access_token = create_access_token(identity=data['username'])
    return jsonify({'access_token': access_token})

@app.route('/api/protected', methods=['GET'])
@jwt_required()
def protected():
    return jsonify({'data': 'Sensitive data exposed'})

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/login with {"username": "alice"}:
{"access_token": "eyJ..."}

GET /api/protected with Authorization: Bearer <token>:
{"data": "Sensitive data exposed"}

Explanation:

  • Weak secret key and no password validation make the API vulnerable.
  • Exposes sensitive data without role-based checks.
  • Solution: Use a strong secret key, validate inputs, and implement role-based access.

03. Effective Usage

3.1 Recommended Practices

  • Use Flask-JWT-Extended with strong secret keys, Flask-Bcrypt for password hashing, and Flask-SQLAlchemy for user storage.

Example: Comprehensive JWT Authentication

from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, create_refresh_token, jwt_refresh_token_required, get_jwt_identity, get_jwt
from flask_bcrypt import Bcrypt
from flask_restful import Api, Resource, reqparse

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///secure_api.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['JWT_SECRET_KEY'] = 'jwt-secret-404'
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = 900  # 15 minutes
app.config['JWT_REFRESH_TOKEN_EXPIRES'] = 2592000  # 30 days
db = SQLAlchemy(app)
api = Api(app)
jwt = JWTManager(app)
bcrypt = Bcrypt(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(120), nullable=False)
    role = db.Column(db.String(20), nullable=False, default='user')

class RegisterResource(Resource):
    parser = reqparse.RequestParser()
    parser.add_argument('username', type=str, required=True, help='Username is required')
    parser.add_argument('password', type=str, required=True, help='Password is required')
    parser.add_argument('role', type=str, default='user', help='Role (user/admin)')

    def post(self):
        args = self.parser.parse_args()
        if User.query.filter_by(username=args['username']).first():
            return {'error': 'Username exists'}, 400
        user = User(
            username=args['username'],
            password_hash=bcrypt.generate_password_hash(args['password']).decode('utf-8'),
            role=args['role']
        )
        db.session.add(user)
        db.session.commit()
        return {'message': 'User created'}, 201

class LoginResource(Resource):
    parser = reqparse.RequestParser()
    parser.add_argument('username', type=str, required=True, help='Username is required')
    parser.add_argument('password', type=str, required=True, help='Password is required')

    def post(self):
        if not request.is_json:
            return {'error': 'Content-Type must be application/json'}, 400
        args = self.parser.parse_args()
        user = User.query.filter_by(username=args['username']).first()
        if user and bcrypt.check_password_hash(user.password_hash, args['password']):
            access_token = create_access_token(identity=user.id, additional_claims={'role': user.role})
            refresh_token = create_refresh_token(identity=user.id)
            return {'access_token': access_token, 'refresh_token': refresh_token}
        return {'error': 'Invalid credentials'}, 401

class RefreshResource(Resource):
    @jwt_refresh_token_required()
    def post(self):
        current_user = get_jwt_identity()
        new_access_token = create_access_token(identity=current_user, additional_claims={'role': User.query.get(current_user).role})
        return {'access_token': new_access_token}

class AdminResource(Resource):
    @jwt_required()
    def get(self):
        claims = get_jwt()
        if claims['role'] != 'admin':
            return {'error': 'Admin access required'}, 403
        users = User.query.all()
        return [{'id': u.id, 'username': u.username, 'role': u.role} for u in users]

api.add_resource(RegisterResource, '/api/register')
api.add_resource(LoginResource, '/api/login')
api.add_resource(RefreshResource, '/api/refresh')
api.add_resource(AdminResource, '/api/admin')

with app.app_context():
    db.create_all()

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/register with {"username": "frank", "password": "secure123", "role": "admin"}:
{"message": "User created"}

POST /api/login with {"username": "frank", "password": "secure123"}:
{"access_token": "eyJ...", "refresh_token": "eyJ..."}

POST /api/refresh with Authorization: Bearer <refresh_token>:
{"access_token": "eyJ..."}

GET /api/admin with Authorization: Bearer <access_token>:
[{"id": 1, "username": "frank", "role": "admin"}]
  • Combines Flask-RESTful, Flask-JWT-Extended, Flask-SQLAlchemy, and Flask-Bcrypt.
  • Implements registration, login, refresh tokens, and role-based access.
  • Validates JSON inputs and secures endpoints.

3.2 Practices to Avoid

  • Avoid weak secret keys, unvalidated inputs, or missing role-based checks.

Example: Insecure JWT API

from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, jwt_required, create_access_token

app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'weak'  # Insecure key
jwt = JWTManager(app)

@app.route('/api/login', methods=['POST'])
def login():
    # No validation or secure password check
    data = request.get_json()
    access_token = create_access_token(identity=data['username'])
    return jsonify({'access_token': access_token})

@app.route('/api/data', methods=['GET'])
@jwt_required()
def data():
    return jsonify({'data': 'Sensitive data exposed'})

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/login with {"username": "alice"}:
{"access_token": "eyJ..."}

GET /api/data with Authorization: Bearer <token>:
{"data": "Sensitive data exposed"}
  • Weak key and no authentication logic make the API vulnerable.
  • Solution: Use strong keys, validate inputs, and enforce role-based access.

04. Common Use Cases in Web Development

4.1 E-commerce Authentication API

Secure an e-commerce API with JWT for user and admin access.

Example: E-commerce Authentication

from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, get_jwt
from flask_bcrypt import Bcrypt

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///ecommerce.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['JWT_SECRET_KEY'] = 'jwt-secret-505'
db = SQLAlchemy(app)
jwt = JWTManager(app)
bcrypt = Bcrypt(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(120), nullable=False)
    role = db.Column(db.String(20), nullable=False, default='user')

class Product(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    price = db.Column(db.Float, nullable=False)

@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not request.is_json or not username or not password:
        return jsonify({'error': 'Invalid input'}), 400
    user = User.query.filter_by(username=username).first()
    if user and bcrypt.check_password_hash(user.password_hash, password):
        access_token = create_access_token(identity=user.id, additional_claims={'role': user.role})
        return jsonify({'access_token': access_token})
    return jsonify({'error': 'Invalid credentials'}), 401

@app.route('/api/products', methods=['POST'])
@jwt_required()
def add_product():
    claims = get_jwt()
    if claims['role'] != 'admin':
        return jsonify({'error': 'Admin access required'}), 403
    data = request.get_json()
    name = data.get('name')
    price = data.get('price')
    if not name or not isinstance(price, (int, float)):
        return jsonify({'error': 'Name and valid price required'}), 400
    product = Product(name=name, price=price)
    db.session.add(product)
    db.session.commit()
    return jsonify({'id': product.id, 'name': product.name, 'price': product.price}), 201

@app.route('/api/products', methods=['GET'])
@jwt_required()
def get_products():
    products = Product.query.all()
    return jsonify([{'id': p.id, 'name': p.name, 'price': p.price} for p in products])

with app.app_context():
    db.create_all()

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/login with {"username": "admin", "password": "secure123"}:
{"access_token": "eyJ..."}

POST /api/products with {"name": "Laptop", "price": 999.99} and admin token:
{"id": 1, "name": "Laptop", "price": 999.99}

GET /api/products with any valid token:
[{"id": 1, "name": "Laptop", "price": 999.99}]

Explanation:

  • Restricts product creation to admins using JWT role claims.
  • Allows all authenticated users to view products.

4.2 Task Management Authentication API

Secure a task management API with JWT for user-specific access.

Example: Task Management Authentication

from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, get_jwt_identity
from flask_bcrypt import Bcrypt

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///tasks.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['JWT_SECRET_KEY'] = 'jwt-secret-606'
db = SQLAlchemy(app)
jwt = JWTManager(app)
bcrypt = Bcrypt(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(120), nullable=False)

class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    user_id = db.Column(db.Integer, nullable=False)

@app.route('/api/register', methods=['POST'])
def register():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not request.is_json or not username or not password:
        return jsonify({'error': 'Invalid input'}), 400
    if User.query.filter_by(username=username).first():
        return jsonify({'error': 'Username exists'}), 400
    user = User(username=username, password_hash=bcrypt.generate_password_hash(password).decode('utf-8'))
    db.session.add(user)
    db.session.commit()
    return jsonify({'message': 'User created'}), 201

@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not request.is_json or not username or not password:
        return jsonify({'error': 'Invalid input'}), 400
    user = User.query.filter_by(username=username).first()
    if user and bcrypt.check_password_hash(user.password_hash, password):
        access_token = create_access_token(identity=user.id)
        return jsonify({'access_token': access_token})
    return jsonify({'error': 'Invalid credentials'}), 401

@app.route('/api/tasks', methods=['POST'])
@jwt_required()
def create_task():
    user_id = get_jwt_identity()
    data = request.get_json()
    title = data.get('title')
    if not request.is_json or not title:
        return jsonify({'error': 'Title required'}), 400
    task = Task(title=title, user_id=user_id)
    db.session.add(task)
    db.session.commit()
    return jsonify({'id': task.id, 'title': task.title, 'user_id': task.user_id}), 201

@app.route('/api/tasks', methods=['GET'])
@jwt_required()
def get_tasks():
    user_id = get_jwt_identity()
    tasks = Task.query.filter_by(user_id=user_id).all()
    return jsonify([{'id': t.id, 'title': t.title, 'user_id': t.user_id} for t in tasks])

with app.app_context():
    db.create_all()

if __name__ == '__main__':
    app.run(debug=True)

Output:

POST /api/register with {"username": "grace", "password": "secure123"}:
{"message": "User created"}

POST /api/login with {"username": "grace", "password": "secure123"}:
{"access_token": "eyJ..."}

POST /api/tasks with {"title": "Write report"} and Bearer token:
{"id": 1, "title": "Write report", "user_id": 1}

GET /api/tasks with Bearer token:
[{"id": 1, "title": "Write report", "user_id": 1}]

Explanation:

  • Ensures tasks are accessible only to their owners using get_jwt_identity.
  • Secures registration and login with JWT and Flask-Bcrypt.

Conclusion

Flask API authentication with JWT, integrated with Flask-RESTful, Flask-JWT-Extended, Flask-SQLAlchemy, Flask Handling JSON Data, and NumPy Array Operations, enables secure and scalable web applications. Key takeaways:

  • Use Flask-JWT-Extended for token generation, validation, and refresh tokens.
  • Implement role-based access control with JWT claims.
  • Integrate with Flask-SQLAlchemy and Flask-Bcrypt for secure user management.
  • Apply in e-commerce, task management, or other domains for secure APIs.

With these techniques, you can build Flask APIs that are secure, scalable, and user-friendly, meeting the demands of modern web development!

Comments