├── .gitignore ├── .vscode └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cognito_MANUAL.md ├── LICENSE ├── NOTICE ├── README.md ├── THIRD-PARTY-LICENSES.txt ├── amplify ├── .config │ └── project-config.json ├── README.md ├── backend │ ├── amplify.state │ ├── auth │ │ └── playerjwtcognito5d5d2eb2 │ │ │ └── cli-inputs.json │ ├── backend-config.json │ ├── function-parameters.json │ ├── function │ │ └── jwtauth │ │ │ ├── amplify.state │ │ │ ├── function-parameters.json │ │ │ ├── jwtauth-cloudformation-template.json │ │ │ └── src │ │ │ ├── config.js │ │ │ ├── event.json │ │ │ ├── index.js │ │ │ ├── package.json │ │ │ └── yarn.lock │ ├── tags.json │ └── types │ │ └── amplify-dependent-resources-ref.d.ts ├── cli.json └── hooks │ ├── README.md │ └── post-push.js ├── doc ├── Auth01.png ├── DeploytoEDGE.png ├── DeploytoEDGE02.png ├── SimplePlayer.png ├── architecture.png └── cloudfrontARN.png ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── aws-video-exports.js ├── components ├── App.css ├── App.js ├── Home.css ├── Home.js └── playerjs │ ├── Player.js │ └── index.js └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | .vscode/* 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | 27 | #docs 28 | docs/ 29 | 30 | #.gitignore 31 | package-lock.json 32 | 33 | #amplify-do-not-edit-begin 34 | amplify/\#current-cloud-backend 35 | amplify/.config/local-* 36 | amplify/logs 37 | amplify/mock-data 38 | amplify/backend/amplify-meta.json 39 | amplify/backend/.temp 40 | build/ 41 | dist/ 42 | node_modules/ 43 | aws-exports.js 44 | awsconfiguration.json 45 | amplifyconfiguration.json 46 | amplifyconfiguration.dart 47 | amplify-build-config.json 48 | amplify-gradle-config.json 49 | amplifytools.xcconfig 50 | .secret-* 51 | **.sample 52 | #amplify-do-not-edit-end 53 | amplify/team-provider-info.json 54 | amplify/backend/function/jwtauth/src/org.config.js.org 55 | amplify/backend/src/org.config.js.org 56 | amplify/backend/function/jwtauth/src/config.js -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "amplify/.config": true, 4 | "amplify/**/*-parameters.json": true, 5 | "amplify/**/amplify.state": true, 6 | "amplify/**/transform.conf.json": true, 7 | "amplify/#current-cloud-backend": true, 8 | "amplify/backend/amplify-meta.json": true, 9 | "amplify/backend/awscloudformation": true 10 | } 11 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. -------------------------------------------------------------------------------- /Cognito_MANUAL.md: -------------------------------------------------------------------------------- 1 | # Configure the function congnito params manually 2 | This step has been astracted by Amaplify Hooks, by creating a before push script. 3 | If you need to configure manually, please follow the steps below: 4 | **a. Edit the index.js function file and add your Cognito User Pool attributes** 5 | 6 | Open the config.js file, located in 7 | 8 | ``` 9 | cd amplify/backend/function/jwtauth/src/ 10 | amplify/backend/function/jwtauth/src/config.js 11 | ``` 12 | 13 | List the auth resources created and copy the User Pool id. 14 | 15 | ``` 16 | amplify auth console 17 | Using service: Cognito, provided by: awscloudformation 18 | ? Which console User Pool 19 | User Pool console: 20 | https://us-east-1.console.aws.amazon.com/cognito/users/?region=us-east-1#/pool/us-east-SomeID/details 21 | Current Environment: dev 22 | ``` 23 | 24 | The user pool id can be located in the URL returned by running *amplify auth console* 25 | https://us-east-1.console.aws.amazon.com/cognito/users/?region=us-east-1#/pool/us-east-SomeID/details 26 | 27 | **b. Add the Region of the deployment (Cognito region) to the var** 28 | 29 | ```javascript 30 | config.REGION = 'us-east-1' 31 | ``` 32 | 33 | **c. Copy the *Pool Id *information and replace in the var USERPOOLID** 34 | 35 | ```javascript 36 | config.USERPOOLID = 'us-east-1_SomeID'; 37 | ``` 38 | 39 | **d. Download and store the corresponding public JSON Web Key (JWK) for your user pool. It is available as part of a JSON.** 40 | * *Web Key Set (JWKS). You can locate it at: 41 | https://cognito-idp.us-east-1.amazonaws.com/*us-east-SomeID*/.well-known/jwks.json 42 | 43 | For more information on JWK and JWK sets, see Cognito Verifying a JSON Web Token documentation (https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html) and JSON Web Key (JWK) (https://tools.ietf.org/html/rfc7517). 44 | 45 | You can see the sample jwks.json in JSON Web Token documentation (https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html). 46 | Now replace the JWKS with the credentials of your Cognito User Pool. 47 | 48 | ```javascript 49 | config.JWKS = '{"keys":[{"alg":"RS256","e":"AQAB","kid":"1234exemple=","kty"::"RSA"....}]} 50 | ``` 51 | 52 | Now deploy your lambda function by simply executing amplify push in the home app folder. 53 | 54 | ``` 55 | amplify push 56 | ``` 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: MIT-0 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this 6 | * software and associated documentation files (the "Software"), to deal in the Software 7 | * without restriction, including without limitation the rights to use, copy, modify, 8 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 12 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 13 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 14 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 15 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 16 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Secure your Media Workloads with JWT Token with Lambda@Edge 2 | 3 | Video streaming is no longer exclusively done by media companies. Schools, ecommerce retailers, tech companies, and banks are creating media content to distribute directly to their consumers. Video streaming, both live and on-demand, has become the prevailing communication tool to reach the target audiences. As the value and number of media assets grow, creating a secure distribution workflow to ensure that only the intended audiences have access. 4 | 5 | ## Architecture overview 6 | 7 | Architecture 8 | 9 | ## Solution components 10 | In this post, we walk through the implementation of the component in the web APP (GitHub repository). We also go through the cloud components for authentication, token validation, and CDN caching. 11 | 12 | The frontend and backend AWS resources are built using [AWS Amplify](https://docs.amplify.aws/), an end-to-end solution that enables mobile and front-end web developers to build and deploy secure, scalable full-stack applications. With Amplify, you can configure app backends in minutes, connect them to your app in just a few lines of code, and deploy static web apps in three steps. 13 | 14 | The web app is built in React and uses Video.JS as the video player. 15 | 16 | After successful authentication, [Amazon Cognito](https://aws.amazon.com/cognito/) returns user pool tokens to your application. Then, you can use the token to grant access to the backend resources. In the proposed architecture, the token is used for signing the requests for media stream content, Lambda@Edge function decode and validate the token attributes, authenticating the spectator to watch the content. 17 | 18 | 19 | ## Deployment Steps: 20 | 21 | ### 1. Project Dependencies 22 | 23 | For building the integration with AWS components and host our web application we will be using AWS Amplify. 24 | For more complete steps of installing and configure AWS Amplify please visit the documentation (Amplify Documentation (https://docs.amplify.aws/start/getting-started/installation/q/integration/react#option-2-follow-the-instructions) for React). 25 | 26 | ```sh 27 | npm install -g @aws-amplify/cli 28 | amplify configure 29 | ``` 30 | 31 | *[Optional]* If you are using [AWS Cloud9](https://aws.amazon.com/cloud9/), you need to copy the cretential for the amplify config 32 | 33 | ```sh 34 | cp ~/.aws/credentials ~/.aws/config 35 | ``` 36 | 37 | ### 2. Clone the repository 38 | We will clone using the amplify init app. AWS Amplify will create a sample implementation on your local environment and provision the AWS backend resources: (API and Authentication). 39 | 40 | ```sh 41 | git clone https://github.com/aws-samples/cloudfront-secure-media.git 42 | cd cloudfront-secure-media/ 43 | ``` 44 | 45 | Now install the dependencies and start your backend environment with AWS Amplify. 46 | 47 | ```sh 48 | npm install 49 | ``` 50 | ```sh 51 | amplify init 52 | ? Enter a name for the environment dev 53 | ? Choose your default editor: Visual Studio Code 54 | Using default provider awscloudformation 55 | ? Select the authentication method you want to use: AWS profile 56 | ? Please choose the profile you want to use default 57 | ``` 58 | *Please make sure to select correct aws profile created with amplify configure* 59 | 60 | ### 3. Create your cloud environment for authentication 61 | 62 | ```sh 63 | amplify status 64 | ``` 65 | 66 | It should list the following resources: 67 | 68 | ``` 69 | Current Environment: dev 70 | 71 | ┌──────────┬──────────────────────────┬───────────┬───────────────────┐ 72 | │ Category │ Resource name │ Operation │ Provider plugin │ 73 | ├──────────┼──────────────────────────┼───────────┼───────────────────┤ 74 | │ Auth │ playerjwtcognito5d5d2eb2 │ Create │ awscloudformation │ 75 | ├──────────┼──────────────────────────┼───────────┼───────────────────┤ 76 | │ Function │ jwtauth │ Create │ awscloudformation │ 77 | └──────────┴──────────────────────────┴───────────┴───────────────────┘ 78 | ``` 79 | 80 | To create the Amazon Cognito user pool for authenticate our users, and provide the JWT token to protect your media resources, we need to push the local resources to the AWS cloud. 81 | 82 | ```sh 83 | amplify push 84 | ``` 85 | 86 | As we have a post-push script to retrieve the Amazon Cognito configuration, so to minimize the deployment steps, you need to push changes again in order to properly set the Lambda params. 87 | 88 | ```sh 89 | amplify push 90 | ``` 91 | 92 | ## 4. Start your local environment 93 | 94 | Now you can start testig your application 95 | 96 | ```sh 97 | npm start 98 | ``` 99 | It should load the authentication page. Now you can create your first user account and sign in. 100 | Click in *Create Account* 101 | 102 | Create your Account 103 | 104 | *After the login, it should load the following local website:* 105 | Simple Player Demo 106 | 107 | ### 5. Setup the video workflow: **[ Optional ]** 108 | *Note: You can jump this step if you already have a video, HLS content in a S3 bucket* 109 | 110 | We will be using Amplify Video (https://github.com/awslabs/amplify-video) for creating some test VOD content, Amplify Video is an open-source plugin for the Amplify CLI, that makes it easy to incorporate video streaming to your web or mobile applications. Powered by AWS Amplify (https://aws-amplify.github.io/) and AWS Media Services (https://aws.amazon.com/media-services/). 111 | Amplify video also supports live workflows. For more options and sample implementations, please visit amplify-video (https://github.com/awslabs/amplify-video) GitHub. 112 | 113 | ```sh 114 | npm i amplify-category-video -g 115 | 116 | amplify add video 117 | ? Please select from one of the below mentioned services: Video-On-Demand 118 | ? Provide a friendly name for your resource to be used as a label for this category in the project: vod-wf-jwt 119 | ? Select a system-provided encoding template, specify an already-created template name: Default HLS Adaptive Bitrate 120 | ? Is this a production enviroment? Yes 121 | ? Do you want to protect your content with signed urls? No 122 | ? Do you want Amplify to create a new GraphQL API to manage your videos? (Beta) No 123 | ✔ All resources built. 124 | ``` 125 | ```sh 126 | amplify push 127 | ``` 128 | 129 | Amplify Video will create the S3 bucket to store the source content, the transcoded content, it will also deploy the CloudFront distribution. Please see the sample result of amplify push. 130 | 131 | ``` 132 | Video on Demand: 133 | 134 | Input Storage bucket: 135 | vodcfjwt-dev-input-SOMEID 136 | 137 | Output URL for content: 138 | https://someid.cloudfront.net (https://someid.cloudfront.net/) 139 | ``` 140 | 141 | 142 | *Note:* Amplify Video also offers the option to protect the content with a signed URL, you can find more information on how to use signed url using amplify video at Getting Started with VOD (https://github.com/awslabs/amplify-video/wiki/Getting-Started-with-VOD). 143 | 144 | **Test Transcoding** 145 | 146 | Navigate to the S3 console. Amplify Video has deployed a few buckets into your environment. Select the input bucket and upload a .mp4 file you have stored locally on your computer. 147 | Once the file has been successfully uploaded, navigate the MediaConvert Console to see your transcode job kicked off. This job takes the input file, transcodes it into the Apple HTTP Live Streaming Protocol (HLS), and outputs the segment files to the S3 bucket labeled output. 148 | 149 | **Testing Media Playback** 150 | 151 | After the MediaConvert job has reached a completed state, navigate back to the S3 Console, and locate the output bucket. When you step into the bucket you will see a folder with the name of the file you uploaded. Step into the folder and you will see the output files created by MediaConvert. Locate the HLS Manifest, the file with the .m3u8 extension, then replace the S3 domain with the Output URL of the content. 152 | 153 | The format of the playable URL will be the Output URL for content + /name of the asset/ + name of the asset.m3u8 154 | Example: https://someid.cloudfront.net/BigBuckBunny/BigBuckBunny.m3u8 155 | 156 | ### 6. Add JWT token authentication to your Amazon CloudFront distribution. 157 | 158 | This step has been astracted by Amaplify Hooks, by creating a before push script. 159 | If you need to configure manually [follow this guide](/Cognito_MANUAL.md) 160 | 161 | ### 7. *Deploy to Lambda@Edge* 162 | 163 | Now that we have pushed the function to check the JWT Token to the cloud, you have to deploy it to your distribution, which has been created at step 5. 164 | 165 | *a. Go to the* *CloudFront console* (https://console.aws.amazon.com/cloudfront/)*, and get the distribution ARN created at step 5* 166 | cloudfront arn 167 | 168 | 169 | *b. Go to Lambda console (https://console.aws.amazon.com/lambda), and Deploy the function to Lambda@Edge* 170 | cloudfront arn 171 | 172 | Then, select **Viewer Request** 173 | cloudfront arn 174 | 175 | 176 | ### 8. End-to-End Tests 177 | 178 | Now open your web application and play some test content. 179 | In the video URL field, add the full CloudFront URL of your output asset created at step 5. 180 | Simple Player Demo 181 | 182 | ### 9. Cleanup, removing the provisioned AWS resources. **[ Optional ]** 183 | If you need to remove the resources deployed by this sample, you can use the command below: 184 | 185 | ```sh 186 | amplify delete 187 | ``` 188 | 189 | ### License Summary 190 | This sample code is made available under a modified MIT-0 [LICENSE](LICENSE) -------------------------------------------------------------------------------- /THIRD-PARTY-LICENSES.txt: -------------------------------------------------------------------------------- 1 | ** React; version 17.0.1 -- https://github.com/facebook/react 2 | 3 | MIT License 4 | 5 | Copyright (c) Facebook, Inc. and its affiliates. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /amplify/.config/project-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "playerJWTcognito", 3 | "version": "3.1", 4 | "frontend": "javascript", 5 | "javascript": { 6 | "framework": "react", 7 | "config": { 8 | "SourceDir": "src", 9 | "DistributionDir": "build", 10 | "BuildCommand": "npm run-script build", 11 | "StartCommand": "npm run-script start" 12 | } 13 | }, 14 | "providers": [ 15 | "awscloudformation" 16 | ] 17 | } -------------------------------------------------------------------------------- /amplify/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Amplify CLI 2 | This directory was generated by [Amplify CLI](https://docs.amplify.aws/cli). 3 | 4 | Helpful resources: 5 | - Amplify documentation: https://docs.amplify.aws 6 | - Amplify CLI documentation: https://docs.amplify.aws/cli 7 | - More details on this folder & generated files: https://docs.amplify.aws/cli/reference/files 8 | - Join Amplify's community: https://amplify.aws/community/ 9 | -------------------------------------------------------------------------------- /amplify/backend/amplify.state: -------------------------------------------------------------------------------- 1 | { 2 | "pluginId": "amplify-nodejs-function-runtime-provider", 3 | "functionRuntime": "nodejs", 4 | "useLegacyBuild": true, 5 | "defaultEditorFile": "src/index.js" 6 | } -------------------------------------------------------------------------------- /amplify/backend/auth/playerjwtcognito5d5d2eb2/cli-inputs.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1", 3 | "cognitoConfig": { 4 | "identityPoolName": "playerjwtcognito5d5d2eb2_identitypool_5d5d2eb2", 5 | "allowUnauthenticatedIdentities": false, 6 | "resourceNameTruncated": "player5d5d2eb2", 7 | "userPoolName": "playerjwtcognito5d5d2eb2_userpool_5d5d2eb2", 8 | "autoVerifiedAttributes": [ 9 | "email" 10 | ], 11 | "mfaConfiguration": "OFF", 12 | "mfaTypes": [ 13 | "SMS Text Message" 14 | ], 15 | "smsAuthenticationMessage": "Your authentication code is {####}", 16 | "smsVerificationMessage": "Your verification code is {####}", 17 | "emailVerificationSubject": "Your verification code", 18 | "emailVerificationMessage": "Your verification code is {####}", 19 | "defaultPasswordPolicy": false, 20 | "passwordPolicyMinLength": 8, 21 | "passwordPolicyCharacters": [], 22 | "requiredAttributes": [ 23 | "email" 24 | ], 25 | "aliasAttributes": [], 26 | "userpoolClientGenerateSecret": false, 27 | "userpoolClientRefreshTokenValidity": 30, 28 | "userpoolClientWriteAttributes": [ 29 | "email" 30 | ], 31 | "userpoolClientReadAttributes": [ 32 | "email" 33 | ], 34 | "userpoolClientLambdaRole": "player5d5d2eb2_userpoolclient_lambda_role", 35 | "userpoolClientSetAttributes": false, 36 | "sharedId": "5d5d2eb2", 37 | "resourceName": "playerjwtcognito5d5d2eb2", 38 | "authSelections": "identityPoolAndUserPool", 39 | "useDefault": "default", 40 | "usernameAttributes": [ 41 | "email" 42 | ], 43 | "userPoolGroupList": [], 44 | "serviceName": "Cognito", 45 | "usernameCaseSensitive": false, 46 | "useEnabledMfas": true 47 | } 48 | } -------------------------------------------------------------------------------- /amplify/backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": { 3 | "playerjwtcognito5d5d2eb2": { 4 | "service": "Cognito", 5 | "providerPlugin": "awscloudformation", 6 | "dependsOn": [], 7 | "customAuth": false, 8 | "frontendAuthConfig": { 9 | "socialProviders": [], 10 | "usernameAttributes": [ 11 | "EMAIL" 12 | ], 13 | "signupAttributes": [ 14 | "EMAIL" 15 | ], 16 | "passwordProtectionSettings": { 17 | "passwordPolicyMinLength": 8, 18 | "passwordPolicyCharacters": [] 19 | }, 20 | "mfaConfiguration": "OFF", 21 | "mfaTypes": [ 22 | "SMS" 23 | ], 24 | "verificationMechanisms": [ 25 | "EMAIL" 26 | ] 27 | } 28 | } 29 | }, 30 | "function": { 31 | "jwtauth": { 32 | "build": true, 33 | "providerPlugin": "awscloudformation", 34 | "service": "Lambda" 35 | } 36 | }, 37 | "api": {}, 38 | "video": {} 39 | } -------------------------------------------------------------------------------- /amplify/backend/function-parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "lambdaLayers": [] 3 | } -------------------------------------------------------------------------------- /amplify/backend/function/jwtauth/amplify.state: -------------------------------------------------------------------------------- 1 | { 2 | "pluginId": "amplify-nodejs-function-runtime-provider", 3 | "functionRuntime": "nodejs", 4 | "useLegacyBuild": true, 5 | "defaultEditorFile": "src/index.js" 6 | } -------------------------------------------------------------------------------- /amplify/backend/function/jwtauth/function-parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "lambdaLayers": [] 3 | } -------------------------------------------------------------------------------- /amplify/backend/function/jwtauth/jwtauth-cloudformation-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"8.0.2\",\"stackType\":\"function-Lambda\",\"metadata\":{}}", 4 | "Parameters": { 5 | "CloudWatchRule": { 6 | "Type": "String", 7 | "Default": "NONE", 8 | "Description": " Schedule Expression" 9 | }, 10 | "env": { 11 | "Type": "String" 12 | }, 13 | "deploymentBucketName": { 14 | "Type": "String" 15 | }, 16 | "s3Key": { 17 | "Type": "String" 18 | } 19 | }, 20 | "Conditions": { 21 | "ShouldNotCreateEnvResources": { 22 | "Fn::Equals": [ 23 | { 24 | "Ref": "env" 25 | }, 26 | "NONE" 27 | ] 28 | } 29 | }, 30 | "Resources": { 31 | "LambdaFunction": { 32 | "Type": "AWS::Lambda::Function", 33 | "Metadata": { 34 | "aws:asset:path": "./src", 35 | "aws:asset:property": "Code" 36 | }, 37 | "Properties": { 38 | "Handler": "index.handler", 39 | "FunctionName": { 40 | "Fn::If": [ 41 | "ShouldNotCreateEnvResources", 42 | "jwtauth", 43 | { 44 | "Fn::Join": [ 45 | "", 46 | [ 47 | "jwtauth", 48 | "-", 49 | { 50 | "Ref": "env" 51 | } 52 | ] 53 | ] 54 | } 55 | ] 56 | }, 57 | "Environment": { 58 | "Variables": {} 59 | }, 60 | "Role": { 61 | "Fn::GetAtt": [ 62 | "LambdaExecutionRole", 63 | "Arn" 64 | ] 65 | }, 66 | "Runtime": "nodejs14.x", 67 | "Layers": [], 68 | "Timeout": "1", 69 | "Code": { 70 | "S3Bucket": { 71 | "Ref": "deploymentBucketName" 72 | }, 73 | "S3Key": { 74 | "Ref": "s3Key" 75 | } 76 | } 77 | } 78 | }, 79 | "LambdaExecutionRole": { 80 | "Type": "AWS::IAM::Role", 81 | "Properties": { 82 | "RoleName": { 83 | "Fn::If": [ 84 | "ShouldNotCreateEnvResources", 85 | "cfjwauthLambdaRole4baf72dd", 86 | { 87 | "Fn::Join": [ 88 | "", 89 | [ 90 | "cfjwauthLambdaRole4baf72dd", 91 | "-", 92 | { 93 | "Ref": "env" 94 | } 95 | ] 96 | ] 97 | } 98 | ] 99 | }, 100 | "AssumeRolePolicyDocument": { 101 | "Version": "2012-10-17", 102 | "Statement": [ 103 | { 104 | "Effect": "Allow", 105 | "Principal": { 106 | "Service": [ 107 | "lambda.amazonaws.com", 108 | "edgelambda.amazonaws.com" 109 | ] 110 | }, 111 | "Action": [ 112 | "sts:AssumeRole" 113 | ] 114 | } 115 | ] 116 | } 117 | } 118 | }, 119 | "lambdaexecutionpolicy": { 120 | "DependsOn": [ 121 | "LambdaExecutionRole" 122 | ], 123 | "Type": "AWS::IAM::Policy", 124 | "Properties": { 125 | "PolicyName": "lambda-execution-policy", 126 | "Roles": [ 127 | { 128 | "Ref": "LambdaExecutionRole" 129 | } 130 | ], 131 | "PolicyDocument": { 132 | "Version": "2012-10-17", 133 | "Statement": [ 134 | { 135 | "Effect": "Allow", 136 | "Action": [ 137 | "logs:CreateLogGroup", 138 | "logs:CreateLogStream", 139 | "logs:PutLogEvents" 140 | ], 141 | "Resource": { 142 | "Fn::Sub": [ 143 | "arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*", 144 | { 145 | "region": { 146 | "Ref": "AWS::Region" 147 | }, 148 | "account": { 149 | "Ref": "AWS::AccountId" 150 | }, 151 | "lambda": { 152 | "Ref": "LambdaFunction" 153 | } 154 | } 155 | ] 156 | } 157 | } 158 | ] 159 | } 160 | } 161 | } 162 | }, 163 | "Outputs": { 164 | "Name": { 165 | "Value": { 166 | "Ref": "LambdaFunction" 167 | } 168 | }, 169 | "Arn": { 170 | "Value": { 171 | "Fn::GetAtt": [ 172 | "LambdaFunction", 173 | "Arn" 174 | ] 175 | } 176 | }, 177 | "Region": { 178 | "Value": { 179 | "Ref": "AWS::Region" 180 | } 181 | }, 182 | "LambdaExecutionRole": { 183 | "Value": { 184 | "Ref": "LambdaExecutionRole" 185 | } 186 | } 187 | } 188 | } -------------------------------------------------------------------------------- /amplify/backend/function/jwtauth/src/config.js: -------------------------------------------------------------------------------- 1 | var config = {}; 2 | 3 | config.REGION = 'us-east-1'; // please replace with the cognito region id. region of the deployment, e.i us-east-1 4 | config.USERPOOLID = ''; // please add your cognito user pool id, you can run amplify auth console and select 'User Pool option' 5 | config.JWKS = ''; // please add the cognito well-known JWKS, please read step 5 6 | module.exports = config; 7 | 8 | /// version 0.1.7 9 | -------------------------------------------------------------------------------- /amplify/backend/function/jwtauth/src/event.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "cf": { 5 | "config": { 6 | "distributionId": "EXAMPLE" 7 | }, 8 | "request": { 9 | "uri": "/output/HLS/video.m3u8?eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJhd3M6Y2hhbm5lbC1hcm4iOiJhcm46YXdzOml2czp1cy1lYXN0LTE6MDk4NDM1NDE1NzQyOmNoYW5uZWwvakdhcm1IVkh5M0txIiwiYXdzOmFjY2Vzcy1jb250cm9sLWFsbG93LW9yaWdpbiI6IioiLCJpYXQiOjE2MDM0MDg4MDMsImV4cCI6MTYwMzU4MTYwM30.GigzRJzSpSIk8PuOKNt73I-IHdi2otItotGxSBoheiesmd3f7hIF5IzFthjj52gOSKV8Xck2v7C0W-qblCTP-l_LXOau8vgBP0pXOeE2kcWcr8JKAsnZPEl04Yt9qWq4", 10 | "method": "GET", 11 | "clientIp": "2001:cdba::3257:9652", 12 | "querystring": "token=eyJraWQiOiJYN2JacnFuV0Z4dEZLRHRJbHFwaGxibG1NdHJDQ25UQ1ZTcVo1QkZGbExNPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiIyYjFjNjZkNy0wMzg4LTRiMTktOWQzOC0zYmU1MGJkYTEzYzAiLCJldmVudF9pZCI6IjA0NWVlMWMyLWNmMDMtNGRkMC05YzNiLWVmMWQ1OGVhNGJiYSIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE2MTAwNjgxNTUsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX0RSQm9WY0VEaiIsImV4cCI6MTYxMDA3MTc1NSwiaWF0IjoxNjEwMDY4MTU1LCJqdGkiOiIxNTk2NTQwOC1hZjJkLTQ3OGItOWE3Ni0wY2ZkNTFhMTA3NTAiLCJjbGllbnRfaWQiOiIzdjBjaWNkdDB1YW44ZGxqYnJwdjZsdGVhdSIsInVzZXJuYW1lIjoib3NtYXJiQGFtYXpvbi5jb20ifQ.nyEA6_MjDWtFSGGa0cL-H-Qu4GFZZWQRLernizGXfwlN4RwZAFjHDdRuRyr_BySeAetyeWTOPKCe3-3s03DRrWszWBYVB6Uhde8P_iFee5XDTNRzKaknU9OiRUn0yGnZb3tFzAUI8blnTcwHJZK9PweL3qx3zgz5ymCkFujSTKDIDmN2JHm2Q0okUc-xiGz_BjGcjQrWw3TbubyFDVg8IU20UkyRlLk1rzmRHUC9kGby3BlMoNbr7oZuRaTSDDmoocUFcY9S-ghettFpsHW6C-x1fNanOppEj4IpxQjCosOIas2D_dquWIUfBu2XdcztoVhtfFWWFUP47bxMtMkcsw", 13 | "headers": { 14 | "user-agent": [ 15 | { 16 | "key": "User-Agent", 17 | "value": "test-agent" 18 | } 19 | ], 20 | "host": [ 21 | { 22 | "key": "Host", 23 | "value": "3.82.27.154" 24 | } 25 | ] 26 | } 27 | } 28 | } 29 | } 30 | ] 31 | } -------------------------------------------------------------------------------- /amplify/backend/function/jwtauth/src/index.js: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: MIT-0 3 | 4 | "use strict"; 5 | var jwt = require("jsonwebtoken"); 6 | var jwkToPem = require("jwk-to-pem"); 7 | var config = require("./config"); 8 | 9 | var JWKS = config.JWKS; // please configure the file config.js 10 | var iss = 11 | "https://cognito-idp." + 12 | config.REGION + 13 | ".amazonaws.com/" + 14 | config.USERPOOLID; 15 | var pems; 16 | 17 | pems = {}; 18 | var keys = JSON.parse(JWKS).keys; 19 | for (var i = 0; i < keys.length; i++) { 20 | var key_id = keys[i].kid; 21 | var modulus = keys[i].n; 22 | var exponent = keys[i].e; 23 | var key_type = keys[i].kty; 24 | var jwk = { kty: key_type, n: modulus, e: exponent }; 25 | var pem = jwkToPem(jwk); 26 | pems[key_id] = pem; 27 | } 28 | 29 | const response401 = { 30 | status: "401", 31 | statusDescription: "Unauthorized", 32 | }; 33 | 34 | exports.handler = (event, context, callback) => { 35 | const cfrequest = event.Records[0].cf.request; 36 | const headers = cfrequest.headers; 37 | console.log("getting started"); 38 | console.log("pems=" + pems); 39 | console.log("cfrequest=" + cfrequest); 40 | console.log("!!!", config, iss, JWKS); 41 | 42 | const srcQuerystring = cfrequest.querystring; 43 | console.log("qurey pam=", srcQuerystring); 44 | 45 | //strip out "Bearer " to extract JWT token only 46 | var jwtToken = srcQuerystring.slice(6); 47 | console.log("jwtToken=" + jwtToken); 48 | 49 | //Fail if the token is not jwt 50 | var decodedJwt = jwt.decode(jwtToken, { complete: true }); 51 | console.log("Decoded Token", decodedJwt); 52 | if (!decodedJwt) { 53 | console.log("Not a valid JWT token"); 54 | 55 | callback(null, response401); 56 | return false; 57 | } 58 | 59 | // UserPool check 60 | if (decodedJwt.payload.iss != iss) { 61 | console.log("invalid issuer, check config.js"); 62 | callback(null, response401); 63 | return false; 64 | } 65 | 66 | //Reject the jwt if it's not an 'Access Token' 67 | if (decodedJwt.payload.token_use != "access") { 68 | console.log("Not an access token"); 69 | callback(null, response401); 70 | return false; 71 | } 72 | 73 | //Get the kid from the token and retrieve corresponding PEM 74 | var kid = decodedJwt.header.kid; 75 | var pem = pems[kid]; 76 | if (!pem) { 77 | console.log("Invalid access token"); 78 | callback(null, response401); 79 | return false; 80 | } 81 | 82 | //Verify the signature of the JWT token to ensure it's really coming from your User Pool 83 | jwt.verify(jwtToken, pem, { issuer: iss }, function (err, payload) { 84 | if (err) { 85 | console.log("Token failed verification", err); 86 | callback(null, response401); 87 | return false; 88 | } else { 89 | //Valid token. 90 | console.log("Successful verification"); 91 | //remove authorization header 92 | delete cfrequest.headers.authorization; 93 | //CloudFront can proceed to fetch the content from origin 94 | callback(null, cfrequest); 95 | return true; 96 | } 97 | }); 98 | }; 99 | -------------------------------------------------------------------------------- /amplify/backend/function/jwtauth/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jwtauth", 3 | "version": "2.0.0", 4 | "description": "Lambda function generated by Amplify", 5 | "main": "index.js", 6 | "license": "Apache-2.0", 7 | "dependencies": { 8 | "jsonwebtoken": "^8.5.1", 9 | "jwk-to-pem": "^2.0.4" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /amplify/backend/function/jwtauth/src/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | asn1.js@^5.3.0: 6 | version "5.4.1" 7 | resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" 8 | integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== 9 | dependencies: 10 | bn.js "^4.0.0" 11 | inherits "^2.0.1" 12 | minimalistic-assert "^1.0.0" 13 | safer-buffer "^2.1.0" 14 | 15 | bn.js@^4.0.0, bn.js@^4.11.9: 16 | version "4.12.0" 17 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" 18 | integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== 19 | 20 | brorand@^1.1.0: 21 | version "1.1.0" 22 | resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" 23 | integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= 24 | 25 | buffer-equal-constant-time@1.0.1: 26 | version "1.0.1" 27 | resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" 28 | integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= 29 | 30 | ecdsa-sig-formatter@1.0.11: 31 | version "1.0.11" 32 | resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" 33 | integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== 34 | dependencies: 35 | safe-buffer "^5.0.1" 36 | 37 | elliptic@^6.5.4: 38 | version "6.5.4" 39 | resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" 40 | integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== 41 | dependencies: 42 | bn.js "^4.11.9" 43 | brorand "^1.1.0" 44 | hash.js "^1.0.0" 45 | hmac-drbg "^1.0.1" 46 | inherits "^2.0.4" 47 | minimalistic-assert "^1.0.1" 48 | minimalistic-crypto-utils "^1.0.1" 49 | 50 | hash.js@^1.0.0, hash.js@^1.0.3: 51 | version "1.1.7" 52 | resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" 53 | integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== 54 | dependencies: 55 | inherits "^2.0.3" 56 | minimalistic-assert "^1.0.1" 57 | 58 | hmac-drbg@^1.0.1: 59 | version "1.0.1" 60 | resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" 61 | integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= 62 | dependencies: 63 | hash.js "^1.0.3" 64 | minimalistic-assert "^1.0.0" 65 | minimalistic-crypto-utils "^1.0.1" 66 | 67 | inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: 68 | version "2.0.4" 69 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 70 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 71 | 72 | jsonwebtoken@^8.5.1: 73 | version "8.5.1" 74 | resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" 75 | integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== 76 | dependencies: 77 | jws "^3.2.2" 78 | lodash.includes "^4.3.0" 79 | lodash.isboolean "^3.0.3" 80 | lodash.isinteger "^4.0.4" 81 | lodash.isnumber "^3.0.3" 82 | lodash.isplainobject "^4.0.6" 83 | lodash.isstring "^4.0.1" 84 | lodash.once "^4.0.0" 85 | ms "^2.1.1" 86 | semver "^5.6.0" 87 | 88 | jwa@^1.4.1: 89 | version "1.4.1" 90 | resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" 91 | integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== 92 | dependencies: 93 | buffer-equal-constant-time "1.0.1" 94 | ecdsa-sig-formatter "1.0.11" 95 | safe-buffer "^5.0.1" 96 | 97 | jwk-to-pem@^2.0.4: 98 | version "2.0.5" 99 | resolved "https://registry.yarnpkg.com/jwk-to-pem/-/jwk-to-pem-2.0.5.tgz#151310bcfbcf731adc5ad9f379cbc8b395742906" 100 | integrity sha512-L90jwellhO8jRKYwbssU9ifaMVqajzj3fpRjDKcsDzrslU9syRbFqfkXtT4B89HYAap+xsxNcxgBSB09ig+a7A== 101 | dependencies: 102 | asn1.js "^5.3.0" 103 | elliptic "^6.5.4" 104 | safe-buffer "^5.0.1" 105 | 106 | jws@^3.2.2: 107 | version "3.2.2" 108 | resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" 109 | integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== 110 | dependencies: 111 | jwa "^1.4.1" 112 | safe-buffer "^5.0.1" 113 | 114 | lodash.includes@^4.3.0: 115 | version "4.3.0" 116 | resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" 117 | integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= 118 | 119 | lodash.isboolean@^3.0.3: 120 | version "3.0.3" 121 | resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" 122 | integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= 123 | 124 | lodash.isinteger@^4.0.4: 125 | version "4.0.4" 126 | resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" 127 | integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= 128 | 129 | lodash.isnumber@^3.0.3: 130 | version "3.0.3" 131 | resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" 132 | integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= 133 | 134 | lodash.isplainobject@^4.0.6: 135 | version "4.0.6" 136 | resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" 137 | integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= 138 | 139 | lodash.isstring@^4.0.1: 140 | version "4.0.1" 141 | resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" 142 | integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= 143 | 144 | lodash.once@^4.0.0: 145 | version "4.1.1" 146 | resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" 147 | integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= 148 | 149 | minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: 150 | version "1.0.1" 151 | resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" 152 | integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== 153 | 154 | minimalistic-crypto-utils@^1.0.1: 155 | version "1.0.1" 156 | resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" 157 | integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= 158 | 159 | ms@^2.1.1: 160 | version "2.1.3" 161 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 162 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 163 | 164 | safe-buffer@^5.0.1: 165 | version "5.2.1" 166 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 167 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 168 | 169 | safer-buffer@^2.1.0: 170 | version "2.1.2" 171 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 172 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 173 | 174 | semver@^5.6.0: 175 | version "5.7.1" 176 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 177 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 178 | -------------------------------------------------------------------------------- /amplify/backend/tags.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Key": "user:Stack", 4 | "Value": "{project-env}" 5 | }, 6 | { 7 | "Key": "user:Application", 8 | "Value": "{project-name}" 9 | } 10 | ] -------------------------------------------------------------------------------- /amplify/backend/types/amplify-dependent-resources-ref.d.ts: -------------------------------------------------------------------------------- 1 | export type AmplifyDependentResourcesAttributes = { 2 | "auth": { 3 | "playerjwtcognito5d5d2eb2": { 4 | "IdentityPoolId": "string", 5 | "IdentityPoolName": "string", 6 | "UserPoolId": "string", 7 | "UserPoolArn": "string", 8 | "UserPoolName": "string", 9 | "AppClientIDWeb": "string", 10 | "AppClientID": "string" 11 | } 12 | }, 13 | "function": { 14 | "jwtauth": { 15 | "Name": "string", 16 | "Arn": "string", 17 | "Region": "string", 18 | "LambdaExecutionRole": "string" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /amplify/cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "features": { 3 | "graphqltransformer": { 4 | "addmissingownerfields": true, 5 | "improvepluralization": false, 6 | "validatetypenamereservedwords": true, 7 | "useexperimentalpipelinedtransformer": true, 8 | "enableiterativegsiupdates": true, 9 | "secondarykeyasgsi": true, 10 | "skipoverridemutationinputtypes": true, 11 | "transformerversion": 2, 12 | "suppressschemamigrationprompt": true, 13 | "securityenhancementnotification": false, 14 | "showfieldauthnotification": false 15 | }, 16 | "frontend-ios": { 17 | "enablexcodeintegration": true 18 | }, 19 | "auth": { 20 | "enablecaseinsensitivity": true, 21 | "useinclusiveterminology": true, 22 | "breakcirculardependency": true, 23 | "forcealiasattributes": false, 24 | "useenabledmfas": true 25 | }, 26 | "codegen": { 27 | "useappsyncmodelgenplugin": true, 28 | "usedocsgeneratorplugin": true, 29 | "usetypesgeneratorplugin": true, 30 | "cleangeneratedmodelsdirectory": true, 31 | "retaincasestyle": true, 32 | "addtimestampfields": true, 33 | "handlelistnullabilitytransparently": true, 34 | "emitauthprovider": true, 35 | "generateindexrules": true, 36 | "enabledartnullsafety": true 37 | }, 38 | "appsync": { 39 | "generategraphqlpermissions": true 40 | }, 41 | "latestregionsupport": { 42 | "pinpoint": 1, 43 | "translate": 1, 44 | "transcribe": 1, 45 | "rekognition": 1, 46 | "textract": 1, 47 | "comprehend": 1 48 | }, 49 | "project": { 50 | "overrides": true 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /amplify/hooks/README.md: -------------------------------------------------------------------------------- 1 | # Command Hooks 2 | 3 | Command hooks can be used to run custom scripts upon Amplify CLI lifecycle events like pre-push, post-add-function, etc. 4 | 5 | To get started, add your script files based on the expected naming convention in this directory. 6 | 7 | Learn more about the script file naming convention, hook parameters, third party dependencies, and advanced configurations at https://docs.amplify.aws/cli/usage/command-hooks 8 | -------------------------------------------------------------------------------- /amplify/hooks/post-push.js: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: MIT-0 3 | // Author Osmar Bento @osmarb 4 | 5 | "use strict"; 6 | 7 | const axios = require("axios").default; 8 | const fs = require("fs"); 9 | const path = require("path"); 10 | 11 | const filePath = path.join(__dirname, "..", "..", "/src/aws-exports.js"); 12 | readBlock(filePath); 13 | 14 | function readBlock(file_path) { 15 | fs.readFile(file_path, "utf8", function (err, data) { 16 | if (err) console.log(err); 17 | else { 18 | let splitArray = data.split("\n"); 19 | let newArr = []; 20 | newArr.push(searchParams("aws_cognito_region", splitArray)); 21 | newArr.push( 22 | searchParams("aws_user_pools_id", splitArray).replace(/,/g, "") 23 | ); 24 | newArr.unshift("{"); 25 | newArr.push("}"); 26 | let awsmobile = newArr.join("\n"); 27 | getJWKS(awsmobile); 28 | } 29 | }); 30 | } 31 | 32 | function searchParams(element, arr) { 33 | for (var i = 0; i < arr.length; i++) { 34 | if (arr[i].match(element)) { 35 | return arr[i]; 36 | } 37 | } 38 | } 39 | 40 | async function getJWKS(awsmobile) { 41 | var awsConfig = JSON.parse(awsmobile); 42 | var config = {}; 43 | config.REGION = awsConfig.aws_cognito_region; 44 | config.USERPOOLID = awsConfig.aws_user_pools_id; 45 | 46 | var congnitoJWKSurl = `https://cognito-idp.${config.REGION}.amazonaws.com/${config.USERPOOLID}/.well-known/jwks.json`; 47 | 48 | await getJWKSinfo(congnitoJWKSurl); 49 | 50 | async function getJWKSinfo(url) { 51 | await axios 52 | .get(url) 53 | .then(function (response) { 54 | config.JWKS = response.data; 55 | writeConfig(config); 56 | }) 57 | .catch(function (error) { 58 | console.log(error); 59 | }); 60 | } 61 | } 62 | 63 | async function writeConfig(config) { 64 | let params = ` 65 | var config = {}; 66 | config.REGION = '${config.REGION}' 67 | config.USERPOOLID = '${config.USERPOOLID}' 68 | config.JWKS = '${JSON.stringify(config.JWKS)}' 69 | module.exports = config;`; 70 | 71 | fs.writeFile( 72 | __dirname + "/../backend/function/jwtauth/src/config.js", 73 | params, 74 | (error) => { 75 | if (error) console.log(error); 76 | else { 77 | console.log("File written successfully\n"); 78 | console.log("The written has the following contents:"); 79 | console.log( 80 | fs.readFileSync( 81 | __dirname + "/../backend/function/jwtauth/src/config.js", 82 | "utf8" 83 | ) 84 | ); 85 | } 86 | } 87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /doc/Auth01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/cloudfront-secure-media/b5278bd473bda032b181d444b1110cc7bce1390c/doc/Auth01.png -------------------------------------------------------------------------------- /doc/DeploytoEDGE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/cloudfront-secure-media/b5278bd473bda032b181d444b1110cc7bce1390c/doc/DeploytoEDGE.png -------------------------------------------------------------------------------- /doc/DeploytoEDGE02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/cloudfront-secure-media/b5278bd473bda032b181d444b1110cc7bce1390c/doc/DeploytoEDGE02.png -------------------------------------------------------------------------------- /doc/SimplePlayer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/cloudfront-secure-media/b5278bd473bda032b181d444b1110cc7bce1390c/doc/SimplePlayer.png -------------------------------------------------------------------------------- /doc/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/cloudfront-secure-media/b5278bd473bda032b181d444b1110cc7bce1390c/doc/architecture.png -------------------------------------------------------------------------------- /doc/cloudfrontARN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/cloudfront-secure-media/b5278bd473bda032b181d444b1110cc7bce1390c/doc/cloudfrontARN.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cf-jw-auth", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@aws-amplify/auth": "^4.5.2", 7 | "@aws-amplify/core": "^4.5.2", 8 | "@aws-amplify/ui-react": "^2.15.5", 9 | "config": "^3.3.7", 10 | "react": "^18.1.0", 11 | "react-bootstrap": "^2.3.0", 12 | "react-dom": "^18.1.0", 13 | "react-router-dom": "^6.3.0", 14 | "react-scripts": "5.0.1" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "eject": "react-scripts eject" 20 | }, 21 | "browserslist": { 22 | "production": [ 23 | ">0.2%", 24 | "not dead", 25 | "not op_mini all" 26 | ], 27 | "development": [ 28 | "last 1 chrome version", 29 | "last 1 firefox version", 30 | "last 1 safari version" 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/cloudfront-secure-media/b5278bd473bda032b181d444b1110cc7bce1390c/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 24 | 25 | 31 | 32 | 35 | 36 | 39 | 40 | AWS - Simple JWT Token 41 | 42 | 43 | 44 |
45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/cloudfront-secure-media/b5278bd473bda032b181d444b1110cc7bce1390c/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/cloudfront-secure-media/b5278bd473bda032b181d444b1110cc7bce1390c/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/aws-video-exports.js: -------------------------------------------------------------------------------- 1 | // WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten. 2 | 3 | const awsvideoconfig = { 4 | "awsInputVideo": "vodcfjwt-dev-input-0yq1aexg", 5 | "awsOutputVideo": "d3kevoas2d6vi1.cloudfront.net" 6 | }; 7 | 8 | export default awsvideoconfig; -------------------------------------------------------------------------------- /src/components/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-header { 6 | background-color: #282c34; 7 | min-height: 100vh; 8 | display: flex; 9 | flex-direction: column; 10 | align-items: center; 11 | justify-content: center; 12 | font-size: calc(10px + 2vmin); 13 | color: white; 14 | } 15 | 16 | .App-link { 17 | color: #61dafb; 18 | } 19 | 20 | .player-wrapper 21 | { 22 | display: flex; 23 | justify-content: center; 24 | align-items: top; 25 | margin: 0 0 20px; 26 | } 27 | 28 | .headerPlayer{ 29 | text-align: center; 30 | line-height: 0px; 31 | color: rgb(220, 224, 228); 32 | font-size: 24px; 33 | margin: 5px; 34 | bottom: 100000000px; 35 | } 36 | 37 | .form-URL{ 38 | display: flex; 39 | justify-content: left; 40 | align-items: top; 41 | width: 100%; 42 | padding: 6px 100px; 43 | margin: 18px 0; 44 | box-sizing: border-box; 45 | } 46 | 47 | .formURL{ 48 | width: 400px; 49 | height: 38px; 50 | margin: 10px; 51 | } 52 | 53 | .formBot{ 54 | background-color: #FF9900; 55 | width: 50px; 56 | height: 36px; 57 | color: white; 58 | margin: 10px; 59 | border: none; 60 | } 61 | 62 | .formLabel{ 63 | text-align: center; 64 | line-height: 0px; 65 | color: rgb(220, 224, 228); 66 | font-size: 20px; 67 | } 68 | 69 | 70 | .DebugBOXger{ 71 | line-height: 0px; 72 | color: rgb(220, 224, 228); 73 | margin: 0px; 74 | padding: 6px 200px; 75 | 76 | 77 | } 78 | 79 | .DebugBOXtitle{ 80 | text-align: left; 81 | line-height: 0px; 82 | color: rgb(220, 224, 228); 83 | font-size: 16px; 84 | margin: 0 0 15px; 85 | } 86 | 87 | .DebugBOX{ 88 | margin: 0; 89 | background-color: #282c34; 90 | line-height: 0px; 91 | text-align: left; 92 | color: #26262626; 93 | overflow: auto; 94 | scrollbar-width: none; 95 | 96 | 97 | } 98 | 99 | .DebugTable{ 100 | table-layout: flex; 101 | word-wrap: break-all; 102 | white-space: nowrap; 103 | width: 100%; 104 | } 105 | 106 | @keyframes App-logo-spin { 107 | from { 108 | transform: rotate(0deg); 109 | } 110 | to { 111 | transform: rotate(360deg); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/components/App.js: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: MIT-0 3 | 4 | import React, { useEffect, useState } from "react"; 5 | import "./App.css"; 6 | import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom"; 7 | import Nav from "react-bootstrap/Nav"; 8 | import Navbar from "react-bootstrap/Navbar"; 9 | import Container from "react-bootstrap/Container"; 10 | import Home from "./Home"; 11 | import Amplify from "@aws-amplify/core"; 12 | import Auth from "@aws-amplify/auth"; 13 | import { withAuthenticator } from "@aws-amplify/ui-react"; 14 | import awsmobile from "../aws-exports"; 15 | import "@aws-amplify/ui-react/styles.css"; 16 | 17 | Amplify.configure(awsmobile); 18 | 19 | function App(props) { 20 | const [username, setUsername] = useState(); 21 | const [token, setToken] = useState(); 22 | 23 | useEffect(() => { 24 | (async function () { 25 | try { 26 | await Auth.currentSession({ bypassCache: false }).then((session) => { 27 | console.log( 28 | "User name", 29 | session.accessToken.payload.username 30 | //session.accessToken.jwtToken // for Debug 31 | ); 32 | setUsername(session.accessToken.payload.username); 33 | setToken(session.accessToken.jwtToken); 34 | }); 35 | } catch (e) { 36 | console.error("Error, no logeeed user ", e); 37 | } 38 | })(); 39 | console.log("Simple Player JWT Mounted"); 40 | }, [username, token]); 41 | 42 | const signOut = async () => { 43 | try { 44 | await Auth.signOut(); 45 | window.location.reload(); 46 | } catch (err) { 47 | console.log("error signing out: ", err); 48 | } 49 | }; 50 | 51 | return username ? ( 52 | 53 |
54 | 55 | 56 | Simple Player 57 | 64 | 65 | 66 | 67 | } 70 | /> 71 | 72 |
73 |
74 | ) : ( 75 |
Loading...
76 | ); 77 | } 78 | export default withAuthenticator(App); 79 | -------------------------------------------------------------------------------- /src/components/Home.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | background-color: #1b1a1ae1; 4 | } 5 | 6 | .form-custom { 7 | display: inline-block; 8 | max-width: 500px; 9 | align-items: center; 10 | margin: 10px; 11 | } 12 | 13 | .title { 14 | margin-top: 10px; 15 | color: white; 16 | margin-bottom: 10px; 17 | } 18 | 19 | .videoborder { 20 | position: relative; 21 | padding: 10px; 22 | max-width: 896px; 23 | height: 504px; 24 | margin: auto; 25 | align-items: center; 26 | margin-bottom: 10px; 27 | } 28 | 29 | .video { 30 | width: 100%; 31 | height: 100%; 32 | position: absolute; 33 | top: 0; 34 | left: 0; 35 | z-index: 0; 36 | } 37 | 38 | .DebugBOXger{ 39 | line-height: 0px; 40 | color: rgb(220, 224, 228); 41 | margin: 0px; 42 | padding: 6px 200px; 43 | } 44 | 45 | .DebugBOXtitle{ 46 | text-align: left; 47 | line-height: 0px; 48 | color: rgb(220, 224, 228); 49 | font-size: 16px; 50 | margin: 0 0 15px; 51 | } 52 | 53 | .DebugBOX{ 54 | margin: 0; 55 | background-color: #282c34; 56 | line-height: 0px; 57 | text-align: left; 58 | color: #26262626; 59 | overflow: auto; 60 | scrollbar-width: none; 61 | 62 | 63 | } 64 | .DebugTable{ 65 | table-layout: flex; 66 | word-wrap: break-all; 67 | white-space: nowrap; 68 | width: 100%; 69 | } -------------------------------------------------------------------------------- /src/components/Home.js: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: MIT-0 3 | 4 | import React, { useState, useRef } from "react"; 5 | import "./Home.css"; 6 | import VideoPlayer from "./playerjs/"; 7 | import Table from "react-bootstrap/Table"; 8 | import Form from "react-bootstrap/Form"; 9 | import Button from "react-bootstrap/Button"; 10 | 11 | export default function Home(props) { 12 | console.log("HOME", props); 13 | 14 | console.log("HOME Toke", props.token); 15 | 16 | const username = props.username; 17 | const token = props.token; 18 | const playerRef = useRef(null); 19 | 20 | const [videoURL, setvideoURL] = useState( 21 | "http://d2qohgpffhaffh.cloudfront.net/HLS/vanlife/withad/sdr_uncage_vanlife_admarker_60sec.m3u8" 22 | ); 23 | 24 | const videoJsOptions = { 25 | autoplay: "muted", //mute audio when page loads, but auto play video 26 | controls: true, 27 | responsive: true, 28 | fluid: true, 29 | width: 896, 30 | height: 504, 31 | token: token, 32 | sources: [ 33 | { 34 | src: videoURL, 35 | type: "application/x-mpegURL", 36 | }, 37 | ], 38 | }; 39 | 40 | const handlePlayerReady = (player) => { 41 | player.on("waiting", () => { 42 | console.log("player is waiting"); 43 | }); 44 | 45 | player.on("dispose", () => { 46 | console.log("player will dispose"); 47 | }); 48 | 49 | player.on("playing", () => { 50 | console.log("player playing"); 51 | }); 52 | 53 | playerRef.current = player; 54 | }; 55 | 56 | const handlePlay = (e) => { 57 | e.preventDefault(); 58 | console.log("New URL is", videoURL); 59 | playerRef.current.src(videoURL); 60 | }; 61 | 62 | return username && token ? ( 63 |
64 |

Simple Player JWT Token

65 | 66 |
67 | 68 | setvideoURL(e.target.value)} 73 | /> 74 | 81 | 82 | 83 | This need to be a HTTP video type, such as HLS, otherwise change the 84 | videoJsOptions 85 | 86 |
87 | 88 |
89 | 94 |
95 | 96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 |
URL:{videoURL}
Playing:True
Token:{token}
113 |
114 |
115 | ) : ( 116 |
No username, or token
117 | ); 118 | } 119 | -------------------------------------------------------------------------------- /src/components/playerjs/Player.js: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: MIT-0 3 | 4 | import React from "react"; 5 | 6 | function VideoJS(props) { 7 | const videoRef = React.useRef(null); 8 | const playerRef = React.useRef(null); 9 | const { options, onReady } = props; 10 | 11 | React.useEffect(() => { 12 | videojs.Vhs.xhr.beforeRequest = function (options) { 13 | options.uri = `${options.uri}?token=${ 14 | videojs.getAllPlayers()[0].options().token 15 | }`; 16 | return options; 17 | }; 18 | 19 | if (!playerRef.current) { 20 | const videoElement = videoRef.current; 21 | if (!videoElement) return; 22 | // ini video js 23 | const player = (playerRef.current = videojs(videoElement, options, () => { 24 | console.log("player is ready"); 25 | console.log("video Element", videoElement); 26 | onReady && onReady(player); 27 | })); 28 | } else { 29 | const player = playerRef.current; 30 | } 31 | }, [options]); 32 | 33 | // Dispose the Video.js player when the functional component unmounts 34 | React.useEffect(() => { 35 | return () => { 36 | if (playerRef.current) { 37 | playerRef.current.dispose(); 38 | playerRef.current = null; 39 | } 40 | }; 41 | }, []); 42 | 43 | return ( 44 |
45 |
51 | ); 52 | } 53 | 54 | export default VideoJS; 55 | -------------------------------------------------------------------------------- /src/components/playerjs/index.js: -------------------------------------------------------------------------------- 1 | export { default } from "./Player"; 2 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: MIT-0 3 | import React from "react"; 4 | import ReactDOM from "react-dom"; 5 | import App from "./components/App"; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById("root") 12 | ); 13 | --------------------------------------------------------------------------------