Comments (11)
As discussed, the cdn (CloudFront) and api need to be on the same domain. To achieve that I added the functionality that I suggested to the video plugin, where it allows users to set a custom domain for the CloudFront (#329) @wizage @nathanagez
Then you can utilise APIMapping to map the same domain to your api but the bigger issue is that the frontend server (origin) also needs to be on the same domain and for all of those to be on the same domain, it requires major changes and integration between video plugin and the main cli, otherwise CORS is inevitable. (Please note that CORS is required for subdomains)
To be able to issue a valid cookie on the server side, you need to have a domain that you own with a valid SSL anyway. So to get it working with the current situation, you can create a rest api using cli. Then add these custom resources to set a custom domain to the api.
"Parameters": {
"env": {
"Type": "String"
},
"certificateArn": {
"Type": "String",
"Default": "CertificateArn"
},
"hostedZoneId": {
"Type": "String",
"Default": "HostedZoneId"
},
"customDomain": {
"Type": "String",
"Default": "Custom Domain"
}
},
....
"ApiGWCustomDomain": {
"Type": "AWS::ApiGateway::DomainName",
"Properties": {
"DomainName": {
"Fn::Join": [
"",
[
{
"Ref": "env"
},
"-",
{
"Ref": "customDomain"
}
]
]
},
"CertificateArn": {
"Ref": "certificateArn"
},
"EndpointConfiguration": {
"Types": [ "EDGE" ]
},
"SecurityPolicy": "TLS_1_2"
}
},
"Route53RecordSetGroup": {
"Type": "AWS::Route53::RecordSet",
"Properties": {
"Name": {
"Fn::Join": [
"",
[
{
"Ref": "env"
},
"-",
{
"Ref": "customDomain"
}
]
]
},
"Type": "A",
"HostedZoneId": {
"Ref": "hostedZoneId"
},
"AliasTarget": {
"DNSName": {
"Fn::GetAtt": [ "ApiGWCustomDomain", "DistributionDomainName" ]
},
"EvaluateTargetHealth": false,
"HostedZoneId": {
"Fn::GetAtt": [ "ApiGWCustomDomain", "DistributionHostedZoneId" ]
}
}
}
},
Then add this mapping to your api CloudFormation template
"APIMapping": {
"Type": "AWS::ApiGateway::BasePathMapping",
"Properties": {
"BasePath": "<your path>",
"DomainName": {
"Fn::Join": [
"",
[
{
"Ref": "env"
},
"-",
{
"Ref": "customDomain"
}
]
]
},
"RestApiId": {
"Ref": "<your api id>"
},
"Stage": {
"Fn::If": [
"ShouldNotCreateEnvResources",
"Prod",
{
"Ref": "env"
}
]
}
}
}
and finally change the RootUrl output of the api cloudformation template. So when you call the api using amplify front-end library, it uses the custom domain not the default api gateway url.
"Outputs": {
"RootUrl": {
"Description": "Root URL of the API gateway",
"Value": {
"Fn::Join": [
"",
[
"https://",
{
"Ref": "env"
},
"-",
{
"Ref": "customDomain"
},
"/<your path>"
]
]
}
},
in the lambda function connected to the api, use almost the same code as the default CFTokenGenerator just change sigend url to signed cookies by using the following method
const signedCookie = signer.getSignedCookie(params);
Please note that to set a cookie with CORS you need to set the withCredentials
flag when making the request and the server needs to return the Access-Control-Allow-Credentials: true
header. You also need to change the Access-Control-Allow-Origin
header to a specific origin and can't use wildcards on a request that uses credentials.
// Enable CORS for all methods
app.use(function (request, res, next) {
const allowedOrigins = ['https://<your domain>', 'xxxx'];
const origin = request.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
res.header('Access-Control-Allow-Headers', '*');
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS,POST,PUT');
//intercept the OPTIONS call so we don't double up on calls to the integration
if ('OPTIONS' === request.method) {
res.send(200);
} else {
next();
}
});
Last but not least set the cookies in the response header
app.post('/<your path>', async (req, res) => {
// handle authorisation if the caller can get the cookies
const cookies = await signPath(req.body);
Object.keys(cookies).map((cookieName) => {
res.cookie(cookieName, cookies[cookieName], { httpOnly: true, path: "/", domain: ".<your domain>", sameSite: "None", secure: true });
})
...
res.json({ body })
});
Please make sure that you set withCredentials
flag when calling the api to store the cookies. Then call cloudfront with the same withCredentials
flag and cookies should be attached and hence you should get 200.
from amplify-video.
So using signed cookies is not currently supported. That being said it isn't that much a lift. The function that is used to create the urls is very similiar to the one you need for cookies.
As far as cookies/urls, the concept is the same. You can easily just add the /* to the end of a request to get a cookie and you now use it for any file that falls under that /. Since we sort videos by id it would be something like / and boom you now have all the hls files authed for that cookie/url.
Now the complicated thing where this gets to the hard part is talking about how cookies work vs urls. Urls are easy they work most everywhere and great for POCing. Cookies are better for production and big sites but take a trade off of you need a domain to work with. Cookies work by using a special header called Set-Cookie that is returned in the response. Set-Cookie needs to be called from the same domain as the request coming from url. I.E. example.com/getCookie and example.com/movie.id/master.hls.
This is why cookies will most likely see a long time before implementation via Amplify Video as it requires working w/ Route53 and other DNS products making the solution not as easy to be a one size fits all.
from amplify-video.
@wizage you're welcome. Happy to contribute. I believe we can even add the rest api creation to the video plugin, so the full solution is available to everyone via the cli. To do so we need to discuss it further, as I don't want to reimplement the functionalities that are already available in the main cli again and duplicate them here.
P.s. In this branch I have added the api gateway creation to video plugin. The only remaining part is updating amplify meta after resource create/remove. I looked at the CLI code and found the amplify helper but didn't want to duplicate them here. Lets have a quick chat. I'd appreciate your input.
from amplify-video.
@wizage @pedramp20 any idea when we can get this added to the core plugin?
from amplify-video.
@kylekirkby I created the pull request a while back but it seem like the team is busy with AWS reinvent. You can always pull the code and build it locally. Let me know if you need any help. The process of building the plugin locally is in the contribution guide.
from amplify-video.
Hi @pedramp20, Thank you for reporting this issue. It looks like it's related to video.js itself #131.
@wizage, is it a big effort to use signed cookies instead of signed urls? From what I understand, signed urls are useful for restricting access to a single file and signed cookies for restricting access to multiple files.
You want to provide access to multiple restricted files, for example, all of the files for a video in HLS format or all of the files in the subscribers' area of website.
from amplify-video.
I am developing with Flutter, and I am currently successfully playing protected videos using the flutter video players "headers" parameter instead of signed URLs as explained in my comment here. This seems to work for now. Hopefully it does not cause me issues in the future based on what @wizage is saying.
from amplify-video.
This does work but is considered a work around for the way cookies work.
Cookies are typically supposed to be set using the Set-Cookie and stick around during the entire duration of the session (or when set to expire). This is just modifying the sent headers with the Cookie.
from amplify-video.
This is awesome! I will read through this in more depth after a new feature release coming this month. If I see this all correct this would be a huge addition to our plugin! Thanks a ton and can't wait to review this :)
from amplify-video.
@pedramp20 the process was a bit more involved for us. I'll have to write up some details at some point but we've got signed cookies working now.
from amplify-video.
@kylekirkby appreciate if you could point out the differences and how you got the withCredentials
working using amplify http client?
from amplify-video.
Related Issues (20)
- Getting 403 Forbidden when trying to upload video to the input s3 bucket as an authenticated user HOT 9
- Output bucket not granting Public Read permission when filename contains spaces HOT 1
- Video player fails to play signed urls HOT 8
- Video object lost when VodAsset json is parsed into VodAsset object HOT 1
- Deployment Failed when Deploying from Admin UI After Adding Amplify Video to Schema HOT 4
- Surface Ivs Start/Stop channel events to a SNS queue
- Audio-Only Pipeline Guide in Wiki Fails to Output Audio HLS
- Cannot Add New Environment with Video Plugin
- Can not push to amplify when updating to v3.9.2 HOT 1
- Template error: instance of Fn::GetAtt references undefined resource videoResource HOT 2
- Provide Audio-On-Demand (AOD) option
- Failed compiling GraphQL schema: Your GraphQL Schema is using "@connection" directive from an older version of the GraphQL Transformer. HOT 3
- Adding amplify video with a Signed URL option fails because of permissions (even with an IAM user with Admin access)
- React video code for both Dash and HLS? HOT 1
- `AccessDeniedException` when invoking lambda function to convert video from input to output bucket HOT 1
- amplify video add command not found HOT 1
- Amplify will not Push after adding Video
- Generated GraphQL schema contains @connection HOT 1
- amplify video add (video on demand) no longer working with away amplify updated cli. HOT 11
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from amplify-video.