Securing a Python Flask REST API with Okta: A Complete Guide

In today's API-driven world, securing backend services is non-negotiable. Whether you're building a microservices architecture or exposing critical business logic via APIs, robust authentication and authorization mechanisms are essential.

Okta, a leading identity provider, offers seamless integration with OAuth 2.0 and OpenID Connect (OIDC), allowing developers to enforce secure access control with minimal effort.



Step 1: Set Up Okta for Authentication

1.1 Create an Okta Developer Account

1.2 Create an Okta Application

  • From the Okta Admin Dashboard, go to ApplicationsCreate App Integration.
  • Select OAuth 2.0/OpenID Connect (OIDC).
  • Choose Web as the application type.
  • Set Sign-in redirect URIs to:
    http://localhost:5000/login/callback
  • Set Sign-out redirect URIs to:
    http://localhost:5000/logout/callback
  • Assign users/groups to the application.

1.3 Get Client Credentials

  • After app creation, go to the application General Settings.
  • Note down:
    • Client ID
    • Client Secret
    • Issuer URL (e.g., https://your-okta-domain/oauth2/default)

Step 2: Set Up Flask and Required Dependencies

2.1 Install Flask and Okta Dependencies

pip install flask flask-cors flask-jwt-extended requests python-dotenv

Step 3: Create a Flask REST API

3.1 Project Structure

/flask-okta-auth │── app.py │── config.py │── .env │── requirements.txt

3.2 Configure Environment Variables

Create a .env file:

OKTA_ISSUER=https://your-okta-domain/oauth2/default
OKTA_CLIENT_ID=your-client-id
OKTA_CLIENT_SECRET=your-client-secret

Step 4: Implement Flask Authentication with Okta

4.1 Configure Flask App

Create config.py:

import os
from dotenv import load_dotenv

load_dotenv()

class Config:
    OKTA_ISSUER = os.getenv("OKTA_ISSUER")
    OKTA_CLIENT_ID = os.getenv("OKTA_CLIENT_ID")
    OKTA_CLIENT_SECRET = os.getenv("OKTA_CLIENT_SECRET")
    SECRET_KEY = "your-secret-key"  # Used for JWT signing

4.2 Implement Flask API with Okta Authentication

Create app.py:

from flask import Flask, request, jsonify
from flask_cors import CORS
import requests
import jwt
from config import Config

app = Flask(__name__)
CORS(app)

# Middleware: Validate JWT token
def verify_token(token):
    try:
        header = jwt.get_unverified_header(token)
        keys_url = f"{Config.OKTA_ISSUER}/v1/keys"
        keys = requests.get(keys_url).json()
        
        for key in keys["keys"]:
            public_key = jwt.algorithms.RSAAlgorithm.from_jwk(key)
            decoded_token = jwt.decode(token, public_key, algorithms=["RS256"], audience=Config.OKTA_CLIENT_ID)
            return decoded_token
    except Exception as e:
        return None

# Protected route
@app.route("/secure-data", methods=["GET"])
def secure_data():
    auth_header = request.headers.get("Authorization")
    if not auth_header:
        return jsonify({"error": "Missing token"}), 401

    token = auth_header.split("Bearer ")[-1]
    user_info = verify_token(token)
    if user_info:
        return jsonify({"message": "Secure data accessed!", "user": user_info}), 200
    else:
        return jsonify({"error": "Invalid token"}), 401

# Public route
@app.route("/", methods=["GET"])
def public_route():
    return jsonify({"message": "Public API endpoint"}), 200

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

Step 5: Test the Authentication

5.1 Start the Flask Server

python app.py

5.2 Obtain an Access Token from Okta

You can authenticate using Postman or a cURL request:

curl -X POST "https://your-okta-domain/oauth2/default/v1/token" \
-H "Accept: application/json" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=your-client-id&client_secret=your-client-secret&scope=openid"

You'll receive a response like:

{
  "access_token": "your-okta-jwt-token",
  "token_type": "Bearer",
  "expires_in": 3600
}

5.3 Use the Token to Access the Secure Route

curl -X GET "http://localhost:5000/secure-data" \
-H "Authorization: Bearer your-okta-jwt-token"

Expected response:

{
  "message": "Secure data accessed!",
  "user": {
    "sub": "your-user-id",
    "name": "John Doe",
    "email": "johndoe@example.com"
  }
}

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete