Closed pooshonbanerjee closed 3 years ago
Since no one is looking at this, I am constantly trying to figure out a work around. I have found one that works, but not without its quirks. After the SSO dialog is gone, which would indicate that the authentication was successful, and the video is presented, if I reload the IFRAME, by simply doing a myIframe.src = myIframe.src
, I can get the PlayerAPI initialize properly. All the events are properly bound, so they trigger correctly. The getProperty()
methods works, and they return correct values, also the callMethod()
functions start working correctly. The only place I am stuck is when to reload the IFRAME. To determine the right time and place I need to know if SSO dialog was presented or not, if it was, when was the authentication successful. I made a little progress in this direction too, but then got stuck again.
I got the contentWindow
object from the IFRAME. And I saw, when I printed the object on to the dev console, that once the auth is successful, this contentWindow
object contains a property named ustream
. But the irony is that I cannot read this ustream
property of contentWindow
because of cross-origin
restrictions.
If only the Apps and Integration
section of the Watson Media settings presented a CORS setting, I could have easily set my application domain as CORS enabled and would have easily read the properties. Everything would be set. But now it seems there is no way but to wait for WM team to find a solution at their end.
At one time I even thought if I call the getProperty('content')
method, and look for an error, I could reload the IFRAME, but this method does not return anything if the Player API is not properly initialized. I am unable to even capture the postMessage
error. So there is no way out.
Waiting for help to come. @jungdaniel
Hi @pooshonbanerjee, sorry for the late response. We are looking at this now, and I'll come back soon.
It seems to me, that this use-case wasn't covered in the past, but I think we should support it, if feasible. What I found so far is that we rely on the value of document.referrer
at some point, which doesn't seem to be a robust enough solution. I'll propose a fix and let you know if it can get into the to production player.
Sure thanks. I will be eagerly waiting since this is affecting a production application.
Hi @jungdaniel , is there any good new on this?
Hi @pooshonbanerjee, the fix is under testing. Hopefully this weak it can go into the production player.
Thanks
Hi @jungdaniel , Any update on this?
Hi @pooshonbanerjee, I know this is taking quite long. The fix went into production, but we introduced a small regression, so we rolled it back. The plan is to release it on next monday. (April 19)
Okay, looking forward to it. Thanks.
Hi @pooshonbanerjee.
We introduced a new parameter, which should be added to the video's src you are embedding. Now it is called The param's name is playerApiTargetUrl
but we'll probably rename it to api-target-origin
to better align with the params we have right now. The final name will go to the documentation.api-target-origin
and the its value should be the origin of the page from which the api is included.
For example, if I were to embed a video on github pages, with SSO configured, I would do it like this:
<iframe
src="https://video.ibm.com/internal/embed/<id>?api-target-origin=https://jungdaniel.github.io"
frameborder="0"
allowfullscreen=""
webkitallowfullscreen=""
></iframe>
It's worth mentioning that in some cases this param is not necessary. More specifically it should work out-of-the-box where location.ancestorOrigins is supported. (All major browsers except FF ...and IE) We removed this part. The param is necessary in every browser if someone wants to use the api with SSO.
Please test it and let us know your findings?
Sorry, but we had to roll back this release again. We found a use-cause which wasn't covered.
Okay, I will wait. Thanks.
Hi @jungdaniel , any update on this?
Hi @pooshonbanerjee,
Please try adding the api-target-origin
to the embed url.
Documentation: https://developers.video.ibm.com/player-api-usage#url-parameters
Hi @jungdaniel , I tried the solution mentioned in the documentation. Here are my observations:
Here is my IFRAME source code:
var apiTargetOrigin = encodeURIComponent(this.rootURL); // this.rootURL contains the URL of the currently running app, which is localhost.
this.iframeHTML = '<iframe id="playerWM" src="https://video.ibm.com/embed/recorded/'+asset_id+'?html5ui&showtitle=false&api-target-origin='+apiTargetOrigin+'" webkitallowfullscreen allowfullscreen frameborder="0" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation-by-user-activation" width="100%" height="100%" style="position:absolute; top:0; left: 0">Loading...</iframe>';
Here is the IFRAME code from the dev console (inspect element)
<iframe id="playerWM" src="https://video.ibm.com/embed/recorded/127341066?html5ui&showtitle=false&api-target-origin=%2F%2Flocalhost%2F" webkitallowfullscreen="" allowfullscreen="" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation-by-user-activation" style="position:absolute; top:0; left: 0" width="100%" height="100%" frameborder="0">Loading...</iframe>
Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘https://video.ibm.com’) does not match the recipient window’s origin (‘https://extauth.services.video.ibm.com’).
Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘https://extauth.services.video.ibm.com’) does not match the recipient window’s origin (‘https://localhost’).
The aforementioned error shows up 9 times, with the same parameters, and then stops occurring.
If I am doing anything wrong, please let know.
P.S: I am using the latest version 1.3.0.
Regards
Pooshon
Hi,
We checked the issue you mentioned above. The src is not looking right: https://video.ibm.com/embed/recorded/127341066?html5ui&showtitle=false&api-target-origin=%2F%2Flocalhost%2F
It looks like the query params are not separated correctly (there are &
characters instead of &
characters), so the player could not receive the api-target-origin
parameter.
Here is a simple example of adding an iframe dynamically. It was working for me with your video id (I used http-server
to serve the static files on localhost).
<!DOCTYPE html>
<html>
<head>
<title>Player API Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<main class="container">
<div class="player" id="playerContainer">
<div class="controls">
<button disabled class="play-pause">play</button>
</div>
</div>
</main>
<script src="./node_modules/ibm-video-streaming-web-player-api/dist/index.umd.min.js"></script>
<script>
var apiTargetOrigin = encodeURIComponent(window.location.origin);
var assetId = '127341066';
var iframeELement = document.createElement('iframe');
iframeELement.id = 'player';
iframeELement.setAttribute('allowfullscreen', '');
iframeELement.setAttribute('webkitallowfullscreen', '');
iframeELement.setAttribute('frameborder', '0');
iframeELement.width = '640';
iframeELement.height = '480';
iframeELement.src = 'https://video.ibm.com/embed/recorded/' + assetId + '?html5ui&showtitle=false&api-target-origin=' + apiTargetOrigin;
document.getElementById('playerContainer').appendChild(iframeELement);
var playing = false;
var playPauseButton = document.querySelector('.play-pause');
var api = PlayerAPI('player');
api.addListener('playing', function (event, value) {
playing = value;
playPauseButton.innerText = playing ? 'Pause' : 'Play';
});
api.addListener('contentAvailable', function () {
playPauseButton.disabled = false;
});
playPauseButton.addEventListener('click', () => {
api.callMethod(playing ? 'pause' : 'play');
});
</script>
</body>
</html>
Hi @annatomka ,
Thanks for your response. I re-checked my code and here are my observations:
&
in the SRC is from developer console -> inspect element. There all URLs are shown as encoded when copied from the console, that doesn't mean I am passing the parameters incorrectly.this.iframeHTML = '<iframe id="playerWM" src="https://video.ibm.com/embed/recorded/'+asset_id+'?api-target-origin='+apiTargetOrigin+'&html5ui&showtitle=true&allowfullscreen=false&volume=50" webkitallowfullscreen allowfullscreen frameborder="0" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation-by-user-activation" width="100%" height="100%" style="position:absolute; top:0; left: 0">Loading...</iframe>';
I also switched the place for api-target-origin
, it is the first one now, so there is no preceding &
. The other parameters tell the player to show the title, disable the fullscreen button and keep the volume at 50%. All these parameters are taking effect. Please have a look:
I did not copy it and instead took a capture because copying it encodes the URI and you will see &
instead of &
.
HTML:
<div fxFlex="1 0 100%" *ngIf="currentAsset.assetType==='video'" [innerHTML]="iframeHTML | safe: 'html'" style="padding-bottom:56.25%; position:relative; display:block; width: 100%; border:1px none red;" (keyup.escape)="closeAsset()">Loading ...</div>
Pipe:
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml, SafeStyle, SafeScript, SafeUrl, SafeResourceUrl } from '@angular/platform-browser';
@Pipe({
name: 'safe'
})
export class SafePipe implements PipeTransform {
constructor(protected sanitizer: DomSanitizer) {}
public transform(value: any, type: string): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl {
switch (type) {
case 'html': return this.sanitizer.bypassSecurityTrustHtml(value);
case 'style': return this.sanitizer.bypassSecurityTrustStyle(value);
case 'script': return this.sanitizer.bypassSecurityTrustScript(value);
case 'url': return this.sanitizer.bypassSecurityTrustUrl(value);
case 'resourceUrl': return this.sanitizer.bypassSecurityTrustResourceUrl(value);
default: throw new Error(`Invalid safe type specified: ${type}`);
}
}
}
I'd again like to say that I believe the player is receiving every parameter correctly otherwise the title, fullscreen, and the volume control also would not have taken effect.
Kindly consider my observations.
Please also have a look at the following:
It says 301: permanently moved
, then the next one ...
... says 302: Found
. The URL changes and internal
is inserted before embed
. I don't know how this affects, just sharing what I can, to help.
And the following are the errors:
To me it seems the target origin is getting overwritten by https://extauth.services.video.ibm.com
after being set to localhost
. I am no expert, just speaking my mind.
Finally I have a question. When you said it is working for you, did you go through the SSO login too? I am asking because when I authenticate once, everything works for me too, for the next one hour till the SSO auth token stays valid.
Requesting you again to please consider my observations.
Regards
Pooshon
Hi @pooshonbanerjee,
To be honest I don't know much about how sanitization work in Angular. I could be wrong but I wouldn't expect this issue to be Angular specific.
Just an idea: On your screenshot it seems you are passing api-target-origin=//localhost/
. Have you tried passing the protocol as well? For example.: api-target-origin=http://localhost
. Also is your local server running on port 80
? If not, I would try to add that too. For example.: api-target-origin=http://localhost:4200
. Let us know if any of this helped.
Hi @jungdaniel , Thanks a lot for constantly working on this with me.
Passing the protocol along with the URL finally worked. We can now close this ticket.
A big thanks to you and your entire engineering team.
Regards Pooshon
Hi @pooshonbanerjee,
Great, thank you for your feedback! Let us know if you have suggestions on improving the docs on: https://developers.video.ibm.com/player-api-usage
In my organization the channel I work with is set up with SSO authentication. After every 24 hours the SSO token expires and the viewer is required to authenticate again.
In my application that makes use of Watson Media, the video is displayed in an IFRAME. When the user is required to authenticate again, this IFRAME displays a "Sign In" button as shown below:
After the sign in is complete, the video plays fine, but this is where the Player API breaks. The events
contentAvailable
andplaying
never triggers, thecallMethod('play')
andcallMethod('seek')
doesn't work.When I check the dev console, I see an error thrown repeatedly:
Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘https://extauth.services.video.ibm.com’) does not match the recipient window’s origin (‘https://localhost’).
My application client is written in Angular, and I declare that I have correctly imported the package:
import PlayerAPI from 'ibm-video-streaming-web-player-api';
The PlayerAPI object is initialized correctly:
this.viewer = PlayerAPI('playerWM');
The listeners are set up correctly:
When I print the viewer object on dev console, this is what shows:
And I also declare that after the SSO sign in done and I refresh the page, all this would start working and keep working until the next time SSO sign in is required. Also the
‘postMessage’ on ‘DOMWindow’
error would not show up again.So in my opinion the PlayerAPI breaks if the SSO sign in dialog is presented. Can you suggest a work around if a solution is not possible?