Skip to content

Conversation

@magajh
Copy link
Contributor

@magajh magajh commented Mar 4, 2025

Summary

This PR adds a custom authentication class (JWTsignedOauthAppAuthentication) that allows authentication using a signed JWT token for the OauthApplicationAPIView.

Your explanation is clear but a bit wordy and could be structured more logically for better readability. Here's a more concise and natural version:

Motivation for this addition

When a new subscription is registered from Control Center, we need to call this eox-core endpoint to create the tenant OAuth client for the instance. However, at this stage, Control Center does not yet have the OAuth client credentials needed to generate a JWT token for authentication.

This authentication mechanism allows the request to be securely made using a signed JWT token, eliminating the need for pre-existing credentials.

Once the tenant OAuth client is created, its credentials are stored in Control Center, enabling future authenticated API requests to the Open edX instance.

Key Changes

  • Implements JWTsignedOauthAppAuthentication, which:
    • Extracts the JWT token from the Authorization header.
    • Verifies the token signature without raising exceptions if authentication fails, allowing fallback to other authentication methods.
    • Returns AnonymousUser() upon successful authentication.
  • Enables secure authentication for service-to-service communication between Control Center and the Open edX instances.

How to Test

  1. Generate RSA Key Pair (Private & Public Keys)

    • Run the following commands to generate the keys:
      openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
      openssl rsa -in private_key.pem -pubout -out public_key.pem
    • Use the public key in Open edX (settings.EOX_CORE_JWT_SIGNED_OAUTH_APP_PUBLIC_KEY).
    • Keep the private key in a secure location for signing JWTs.
  2. Generate a Signed JWT

    • Use the private key to generate a JWT token:
      import jwt
      import time
      import uuid
      
      private_key_path = "private_key.pem"
      
      with open(private_key_path, "r") as f:
          private_key = f.read()
      
      payload = {
          "iat": int(time.time()),
          "exp": int(time.time()) + 300,  # Token expires in 5 minutes
          "nonce": str(uuid.uuid4()),  # Prevents replay attacks
      }
      
      token = jwt.encode(payload, private_key, algorithm="RS256")
      print(f"Generated JWT Token: {token}")
  3. Make a Request to the API

    • Use the generated JWT in the Authorization header:
      curl -X POST "<domain>/eox-core/support-api/v1/oauth-application/" \
           -H "Authorization: Bearer YOUR_GENERATED_JWT" \
           -H "Content-Type: application/json" \
           -d '{
                     {
                         "user": {
                             "fullname": "John Doe",
                             "email": "[email protected]",
                             "username": "johndoe",
                             "permissions": ["can_call_eox_core", "can_call_eox_tenant"]
                         },
                         "redirect_uris": "http://testing-site.io/ http://testing-site.io",
                         "client_type":"confidential",
                         "authorization_grant_type":"client-credentials",
                         "name": "test-application",
                         "skip_authorization": true
                     }
           }'
    • Ensure the request returns a successful response.

@magajh magajh requested a review from a team as a code owner March 4, 2025 13:18
@magajh magajh force-pushed the maga/oauth-app-endpoint-permissions branch from ed3a652 to 6588d41 Compare March 4, 2025 20:25
luisfelipec95
luisfelipec95 previously approved these changes Mar 4, 2025
@magajh
Copy link
Contributor Author

magajh commented Mar 6, 2025

Hey @luisfelipec95! could you check my latest commit? 77f7e8a

I’ve updated the EoxCoreSupportAPIPermission to only allow AnonymousUsers authenticated via JWTsignedOauthAppAuthentication

For other authentication methods, the existing is_staff check remains without changes. This ensures that only signed JWT-authenticated users and staff members can access the API while maintaining security.

Copy link
Contributor

@jignaciopm jignaciopm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@magajh magajh merged commit 0cdbd4e into master Mar 7, 2025
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants