diff --git a/src/content/docs/products/ontrack/documentation/panopoto-integration/panopto-oauth2-intergration-plan.md b/src/content/docs/products/ontrack/documentation/panopoto-integration/panopto-oauth2-intergration-plan.md new file mode 100644 index 00000000..5b730332 --- /dev/null +++ b/src/content/docs/products/ontrack/documentation/panopoto-integration/panopto-oauth2-intergration-plan.md @@ -0,0 +1,118 @@ + +# Panopto OAuth2 Integration Guide (Updated) + +This guide provides a detailed, step-by-step process to integrate Panopto’s OAuth2-based authentication into your backend application (e.g., OnTrack or Doubtfire-API). It covers creating an API client on Panopto, configuring OAuth2 settings, obtaining authorization codes, exchanging them for access tokens, and integrating the process into your application’s workflow. Technical improvements, corrections, and additional recommendations based on best practices have been included. + +## OAuth2 Panopto API Client Setup +To upload videos to a user's personal Panopto instance, we need to authenticate using OAuth2. This involves creating an API client on Panopto, configuring redirect URIs and CORS, then performing the OAuth2 Authorization Code flow to retrieve the tokens required for API calls. + +## Step 1: Create an API Client on Panopto +1. Navigate to the Panopto website: + - Panopto Login: [https://deakin.au.panopto.com/Panopto/Pages/Home.aspx](https://deakin.au.panopto.com/Panopto/Pages/Home.aspx) + +2. Access User Settings: + - Click on the User Settings icon (usually in the top-right corner). + +3. Create a New API Client: + - Under the API Client section, click "Create New Client". + +4. Configure the API Client: + - Set a name for the client (e.g., "OnTrack Integration Client" or "Doubtfire Integration Client"). + - Choose "Server-side Application" as the client type since the integration is backend-based. + +5. Save Your Credentials: + - Note down your Client ID and Client Secret. These will be used to authenticate requests. + - Store them securely (e.g., environment variables). Do not commit these to version control. + +**Example:** +``` +CLIENT_ID=your_panopto_client_id +CLIENT_SECRET=your_panopto_client_secret +``` +Screenshot 2024-12-05 at 5 58 26 pm + +## Step 2: Configure Allowed URLs and Redirect URI +1. Set CORS (Cross-Origin Resource Sharing): + - In the Allowed URL section of the API Client configuration, set CORS to `https://localhost` for local development. + +2. Set Redirect URI: + - Set the Redirect URI to `http://localhost:9127/redirect`. + - The port number (9127) is arbitrary and used for local testing. It must match the `redirect_uri` parameter in your application’s OAuth flow exactly. + +## Step 3: Exchange the Code for an Access Token +Once the API client is set up, the next step is to perform the OAuth2 Authorization Code flow: + +### Obtain the Authorization Code +Replace `YOUR_CLIENT_ID` and `YOUR_PORT` as needed: + +``` +https://deakin.au.panopto.com/Panopto/oauth2/connect/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=http://localhost:9127/redirect&scope=openid%20api&nonce=12345 +``` + +1. Navigate to the above URL in a browser. +2. Log in and grant access when prompted. +3. After approval, Panopto redirects to: + ``` + http://localhost:9127/redirect?code=AUTHORIZATION_CODE + ``` + +### Exchange Authorization Code for Access Token +Use the code to request an access token. Note the correction in `grant_type` spelling (`authorization_code`): + +```bash +curl -X POST "https://deakin.au.panopto.com/Panopto/oauth2/connect/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=authorization_code" -d "code=YOUR_AUTHORIZATION_CODE" -d "redirect_uri=http://localhost:9127/redirect" -d "client_id=YOUR_CLIENT_ID" -d "client_secret=YOUR_CLIENT_SECRET" +``` + +**Example Response:** +```json +{ + "access_token": "eyJ...", + "expires_in": 3600, + "token_type": "Bearer", + "scope": "openid api", + "refresh_token": "optional_refresh_token_if_provided" +} +``` + +This `access_token` can be used to call Panopto’s API for video uploads. If a `refresh_token` is included, you can use it to obtain new access tokens without user re-authorization. + +## Step 4: Integrating with OnTrack (or Your Backend) +1. **Store Credentials Securely:** + - Create an `.env` file (for local development): + ```env + PANOPTO_CLIENT_ID=your_panopto_client_id + PANOPTO_CLIENT_SECRET=your_panopto_client_secret + PANOPTO_REDIRECT_URI=http://localhost:9127/redirect + ``` + - Load these environment variables in your backend application. + +2. **Authorization Flow Integration:** + - Your backend can present a link to the authorization URL. The user clicks it to start the process. + - After granting access, the backend receives the authorization code at the redirect URI. + - The backend exchanges the code for an access token automatically. + +3. **Video Upload:** + - With a valid access token, your backend can call Panopto’s upload APIs to programmatically upload videos to the user’s personal Panopto instance. + +## Recommendations and Updates +- **Security:** + - Use HTTPS in production for all communications. + - Do not log sensitive tokens (e.g., access tokens or refresh tokens). + - Store secrets securely using a tool like AWS Secrets Manager or HashiCorp Vault. +- **Scalability:** + - Use a shared token storage mechanism (e.g., a database) if running multiple instances of your backend behind a load balancer. +- **Error Handling:** + - Implement retry logic with exponential backoff for transient failures. + - Log errors but ensure no sensitive information (e.g., client secret) is exposed. +- **Version Control:** + - Ensure Panopto API versions are checked periodically for updates. + - Test all API changes in a staging environment before deploying them to production. + +## References +- Panopto Documentation: [https://support.panopto.com/s/docs](https://support.panopto.com/s/docs) +- OAuth2 Specification: [https://oauth.net/2/](https://oauth.net/2/) +- Secret Management: Consider [HashiCorp Vault](https://www.vaultproject.io/) or [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) for production. + +--- + +By following these steps and best practices, you can seamlessly integrate Panopto’s OAuth2 authentication flow into your backend (e.g., OnTrack or Doubtfire-API), ensuring a smooth and secure process for uploading videos to a user’s Panopto instance. diff --git a/src/content/docs/products/ontrack/documentation/panopoto-integration/panopto-upload-process.md b/src/content/docs/products/ontrack/documentation/panopoto-integration/panopto-upload-process.md new file mode 100644 index 00000000..a71517bf --- /dev/null +++ b/src/content/docs/products/ontrack/documentation/panopoto-integration/panopto-upload-process.md @@ -0,0 +1,199 @@ +# Panopto Video Upload Process + +## Overview +This document outlines key information about the process of uploading videos to Panopto using the Panopto REST API. While this isn't a comprehensive guide, it highlights the steps involved in creating a session, performing a multipart upload of the video file, creating the manifest, and finalising the upload. This serves as an informational resource for implementing the video upload functionality in the future. Additional research and context will be needed to fully integrate these steps. + +--- + +## Step 1: Create a Session for Video Upload + +Before uploading a video, a session must be created. The session provides the necessary details for the upload process, including the upload target and session ID. + +### Call the Session Creation API +The session creation process is triggered by sending a POST request to the `sessionUpload` endpoint. + +- **API Endpoint:** + ```ruby + POST https://{server}/Panopto/PublicAPI/REST/sessionUpload + ``` +- **Payload:** + ```http + { + "FolderId": "{folder_id}" + } + + ``` +- **Example Session Creation:** + ```ruby + response = RestClient.post( + "https://#{server}/Panopto/PublicAPI/REST/sessionUpload", + { "FolderId" => folder_id }.to_json, + { content_type: :json, accept: :json, authorization: "Bearer #{access_token}" } + ) + ``` + +- **Example Response:** + ```http + { + "ID": "session_id", + "UploadTarget": "upload_target_url", + "FolderId": "{folder_id}" + } + ``` +## Step 2: Upload Video via Multipart Upload +Panopto supports multipart uploads for large video files. This step uploads the video in parts to the ```upload target``` specified in the session creation response. + +#### 1. Initiate Multipart Upload: +- Get the Upload URL: After creating a session, extract the ```UploadTarget``` URL from the session creation response. This URL specifies where the video should be uploaded. + +- Use `Net::HTTP` and `URI` for Multipart Upload: Use Ruby's standard libraries to handle the multipart upload. The following example demonstrates how to upload a file in parts using `Net::HTTP:` + +```ruby + +# Extract the Upload Target URL from the session creation response +upload_target = "https://deakin.au.panopto.com/Panopto/Upload/..." + + +# Define the chunk size for multipart upload (5MB per part) +chunk_size = 5 * 1024 * 1024 + +# Initialise upload process +uri = URI(upload_target) +request = Net::HTTP::Post.new(uri) +request['Content-Type'] = 'multipart/form-data' + +# Read and upload the video file in chunks +while chunk = file.read(chunk_size) + form_data = [['file', chunk]] + request.set_form form_data, 'multipart/form-data' + + response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| + http.request(request) + end + + # Check the response (e.g., for successful upload) + puts response.body +end +``` +### 2. Upload Parts: +- Split the Video File: Split the video into parts, each no larger than 5MB. You can adjust the part size as needed. + +- Upload Each Part: Iterate over the parts and upload them using `Net::HTTP:` + +```ruby +# Read video file in 5MB chunks and upload each part +File.open('video_path.mp4', 'rb') do |file| + part_number = 1 + while (chunk = file.read(5 * 1024 * 1024)) # 5MB per part + form_data = [['file', chunk]] + request.set_form form_data, 'multipart/form-data' + + response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| + http.request(request) + end + + # Handle response + puts "Part #{part_number} uploaded: #{response.body}" + part_number += 1 + end +end +``` +### 3. Complete Multipart Upload: +- Finalise the Upload: Once all parts have been uploaded, call the ``complete_multipart_upload`` method to combine the parts into one video file in Panopto. + +```ruby +# Finalise the upload once all parts are uploaded +complete_upload_uri = URI("#{upload_target}/complete") +complete_request = Net::HTTP::Post.new(complete_upload_uri) +complete_request['Content-Type'] = 'application/json' + +# Send the finalisation request +response = Net::HTTP.start(complete_upload_uri.hostname, complete_upload_uri.port, use_ssl: true) do |http| + http.request(complete_request) +end +``` +## Step 3: Create and Upload the Manifest File +Once the video is uploaded, the next step is to create the manifest file. The manifest provides metadata for the video, including its title, description, and the file name. + +### 1. Create the Manifest File: +- The manifest file is an XML file that contains the following key elements: + +```xml +Copy code + + + {Video_Title} + {Video_Description} + {Current_Date} + + + + +``` +### 2. Upload the Manifest File: +- The manifest file is uploaded in the same way as the video parts, using `multipart upload`. + +```ruby +manifest_file = 'upload_manifest_generated.xml' +file = File.open(manifest_file, 'rb') + +# Prepare the POST request for multipart upload +request = Net::HTTP::Post.new(uri) +request['Content-Type'] = 'multipart/form-data' + +# Upload the manifest in chunks +while chunk = file.read(5 * 1024 * 1024) # 5MB per part + form_data = [['file', chunk]] + request.set_form form_data, 'multipart/form-data' + + # Send the request to upload the part + response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| + http.request(request) + end +``` +## Step 4: Finalise the Upload +After uploading the video and the manifest file, the final step is to finalise the session marking it as complete. + +### 1. Send the PUT Request to Finalise Session: +API Endpoint: + +```ruby +PUT https://{server}/Panopto/PublicAPI/REST/sessionUpload/{session_id} +``` +Payload: + +```ruby + +{ + "State": 1, # Mark as completed + "FolderId": "{folder_id}" +} +``` +Example Code: + +```ruby +RestClient.put( + "https://#{@server}/Panopto/PublicAPI/REST/sessionUpload/#{@session_id}", + { "State" => 1, "FolderId" => @folder_id }.to_json, + { content_type: :json, accept: :json, authorization: "Bearer #{@access_token}" } +) +``` +## 2. Monitor the Upload Status: +- Check for Processing: After finalising, periodically check the `session state` to ensure it is processed and completed. + +Polling Example: + +```ruby + +while true + sleep(5) # Wait a few seconds before checking status + session = RestClient.get("https://#{@server}/Panopto/PublicAPI/REST/sessionUpload/#{@session_id}") + if JSON.parse(session.body)["State"] == 4 # State 4 means processing complete + break + end +end +```