-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Panopto-oauth2-integration documentation #120
Changes from 22 commits
94538bd
8a082e5
e72a2a0
bf626e2
a486d67
55db33c
76075a6
f08129e
4ae0df4
c9ff12d
fa29c8b
8965dc3
f9ee811
02db813
05ef8c4
7f647ee
4f5f03d
6f65e8e
809618b
6b841ee
e27f723
0ef138e
0e73811
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
``` | ||
<img width="400" alt="Screenshot 2024-12-05 at 5 58 26 pm" src="https://github.com/user-attachments/assets/26e91cd0-c986-4c32-88e4-c111283f4650"> | ||
|
||
## 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...<snip>", | ||
"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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
# 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. | ||
|
||
- Set Up AWS SDK : Even though Panopto doesn’t require AWS credentials, use AWS SDK to handle the multipart upload. Initialise the SDK with dummy credentials (to bypass authentication but still use the multipart upload logic). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use of standard library is preferred over introducing new wrapper libraries. Specially, when they are platform specific, like AWS S3, which can introduce breaking changes depending on the direction the platform takes. See the second answer in this post to see how a multipart file upload can be done with standard library in ruby. https://stackoverflow.com/a/46669328 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’ve read the comment and made the changes accordingly. I replaced the use of AWS SDK with Rubys standard library for the multipart file upload, as suggested. |
||
|
||
```ruby | ||
# Extract the Upload Target URL from the session creation response | ||
upload_target = "https://deakin.au.panopto.com/Panopto/Upload/..." | ||
|
||
# Set up AWS SDK for multipart upload | ||
s3 = Aws::S3::Client.new( | ||
endpoint: upload_target, | ||
region: 'us-east-1', | ||
access_key_id: 'dummy', | ||
secret_access_key: 'dummy' | ||
) | ||
|
||
# Initiate multipart upload | ||
mpu = s3.create_multipart_upload(Bucket: 'upload-bucket', Key: 'video-file.mp4') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the concept of bucket exist in Panopto or is this just a dummy too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Panopto uses S3-compatible object storage for uploading files. The concept of a bucket in Panopto is different from AWS S3. The S3 multipart upload method is how I chose to handle the file upload, but the actual storage is managed by Panopto, not AWS S3 |
||
upload_id = mpu['UploadId'] | ||
``` | ||
### 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 the AWS SDK. | ||
|
||
```ruby | ||
# Read the video file in 5MB chunks and upload parts | ||
File.open('video_path.mp4', 'rb') do |file| | ||
part_number = 1 | ||
while (chunk = file.read(5 * 1024 * 1024)) # 5MB per part | ||
s3.upload_part( | ||
bucket: 'upload-bucket', | ||
key: 'test-video.mp4', | ||
part_number: part_number, | ||
upload_id: upload_id, | ||
body: chunk | ||
) | ||
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 | ||
# After all parts have been uploaded, complete the upload | ||
s3.complete_multipart_upload( | ||
bucket: 'upload-bucket', | ||
key: 'video-file.mp4', | ||
upload_id: upload_id, | ||
multipart_upload: { parts: parts_metadata } # Metadata about each uploaded part | ||
) | ||
``` | ||
## 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 | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Session xmlns="http://tempuri.org/UniversalCaptureSpecification/v1"> | ||
<Title>{Video_Title}</Title> | ||
<Description>{Video_Description}</Description> | ||
<Date>{Current_Date}</Date> | ||
<Videos> | ||
<Video> | ||
<Start>PT0S</Start> | ||
<File>{Video_File_Name}</File> | ||
<Type>Primary</Type> | ||
</Video> | ||
</Videos> | ||
</Session> | ||
``` | ||
### 2. Upload the Manifest File: | ||
- The manifest file is uploaded in the same way as the video parts, using `multipart upload`. | ||
``` Example Upload (Using AWS SDK): | ||
ruby | ||
|
||
s3 = Aws::S3::Client.new( | ||
endpoint: upload_target, | ||
region: 'us-east-1', | ||
access_key_id: 'dummy', | ||
secret_access_key: 'dummy' | ||
) | ||
|
||
s3.put_object(bucket: bucket_name, key: manifest_key, body: File.read(manifest_file)) | ||
``` | ||
## 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 | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Panopto_OAuth2_Integration_Guide_version2.md
Consistency and Accuracy
File Section: OAuth2 Authorization URL
Suggestion: The authorization URL provided is accurate. However, it might be helpful to explicitly mention replacing both the
client_id
andredirect_uri
placeholders with actual values. Example:"Replace
YOUR_CLIENT_ID
with the actual client ID provided in Step 1 and ensure the redirect URI exactly matches the one configured in Panopto."Technical Details
File Section:
grant_type=authorisation_code
Suggestion: The grant type is currently spelled as
authorisation_code
(British English). According to OAuth2 standards and Panopto's documentation, the correct spelling isauthorization_code
(American English). Please update this to ensure compatibility with Panopto's API.CORS and Redirect Configuration
File Section: Redirect URI Configuration
Suggestion: Consider clarifying that the redirect URI should be registered exactly as defined, including the protocol (
http://
orhttps://
) and port number. For example:"Ensure the redirect URI configured in Panopto matches
http://localhost:9127/redirect
exactly, as mismatched URIs will cause authentication errors."Readability
File Section: Code Block for
curl
Token ExchangeSuggestion: The
curl
example for exchanging the authorization code for a token is clear. To improve readability, consider adding comments above each parameter to explain their purpose.Example:
Example:
Additional Feedback
File Section: Step 1 (Creating the API Client)
Comment: The instructions for creating the API client are clear and detailed. Providing an example of a client name (e.g., "OnTrack Integration Client") helps the user understand what’s expected. Great job!
File Section: Step 3 (Authorization Code Flow)
Comment: The explanation of the authorization code flow is thorough and well-structured. Including the redirect example URL (
http://localhost:9127/redirect?code=AUTHORIZATION_CODE
) makes the process easy to follow.File Section: Handling Refresh Tokens
Comment: It might be beneficial to include a brief explanation of how refresh tokens can improve user experience by reducing the need for re-authorization. For example:
"Refresh tokens allow the application to request new access tokens without prompting the user, thereby streamlining the experience for recurring video uploads."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, thank you so much for the review, additionally thank you greatly as well for the improvements. Its very informative having a different set of eyes to look at the documentation which I probably assumed a lot of prior knowledge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@epineto Just added you changes. Thanks again for the comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @washyking,
Thank you for your quick and thoughtful response to the feedback, as well as for incorporating the suggested changes. It’s been a pleasure reviewing your work, and I appreciate the effort you’ve put into improving the documentation. The updated version looks fantastic and addresses all the points raised, making it much clearer and more user-friendly.
Your openness to feedback and prompt actions truly reflect great collaboration skills. Keep up the amazing work!