Napster / napster.js

Napster Javascript SDK
MIT License
56 stars 44 forks source link

VIDEOJS: ERROR: TypeError: Cannot read property 'attributes' of undefined #17

Closed kerem-signifai closed 5 years ago

kerem-signifai commented 5 years ago

Able to play tracks (albeit intermittently, but seems to be different issue) on my local machine but always fails when I deploy to a test virtual machine (different network). I am using the password grant authentication scheme.

The error I get is:

streaming-player.js?_=1555903584712:27 VIDEOJS: ERROR: TypeError: Cannot read property 'attributes' of undefined
    at e (streaming-player.js?_=1555903584712:34)
    at r.<anonymous> (streaming-player.js?_=1555903584712:34)
    at r.n.dispatcher (streaming-player.js?_=1555903584712:27)
    at ye (streaming-player.js?_=1555903584712:27)
    at r.Oe.trigger (streaming-player.js?_=1555903584712:27)
    at streaming-player.js?_=1555903584712:34

I assume I am making an error with authentication because when I invoke Napster.member.set with a bogus accessToken I get the same errors.

Help is appreciated.

kerem-signifai commented 5 years ago

I am also getting:

GET https://api.napster.com/v2.2/sessions/1555904647191:me@keremc.com:40134:ip_web_napi_eb2306ce-7f29-43f0-94e2-2cc6db9c65cd?context=UNKNOWN&trackId=tra.30867601 403 (Forbidden)

upon every time I call Napster.player.play on my local machine (the one that works). However, although the first time I invoke that method, I get the error and nothing plays, the second time I invoke, I get the same error but the song plays.

kerem-signifai commented 5 years ago

This is my authentication flow:

$(document).ready(function () {
    var API_KEY = <>;
    var API_SECRET = <>;
    var pass = <>;
    var user = <>;
    Napster.init({
        consumerKey: API_KEY,
        isHTML5Compatible: true
    });

    Napster.player.on('ready', function (e) {
        var headers = {
            'Authorization': 'Basic ' + btoa(API_KEY + ':' + API_SECRET)
        };
        $.ajax({
            type: "POST",
            url: "https://api.napster.com/oauth/token",
            data: {
                username: user,
                password: pass,
                grant_type: 'password'
            },
            headers: headers,
            success: function (result) {
                Napster.member.set({
                    accessToken: result.access_token,
                    refreshToken: result.refresh_token
                });
            },
            dataType: 'json'
        });
    });

    Napster.player.on('error', console.log);
}
eltmon commented 5 years ago

Are you using a different API key for the test virtual machine? I assume it's a different hostname?

On Sun, Apr 21, 2019 at 8:56 PM kerem notifications@github.com wrote:

This is my authentication flow:

$(document).ready(function () { var API_KEY = <>; var API_SECRET = <>; var pass = <>; var user = <>; Napster.init({ consumerKey: API_KEY, isHTML5Compatible: true });

Napster.player.on('ready', function (e) { var headers = { 'Authorization': 'Basic ' + btoa(API_KEY + ':' + API_SECRET) }; $.ajax({ type: "POST", url: "https://api.napster.com/oauth/token", data: { username: user, password: pass, grant_type: 'password' }, headers: headers, success: function (result) { Napster.member.set({ accessToken: result.access_token, refreshToken: result.refresh_token }); }, dataType: 'json' }); });

Napster.player.on('error', console.log); }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/Napster/napster.js/issues/17#issuecomment-485317436, or mute the thread https://github.com/notifications/unsubscribe-auth/AAFFWP32RXLM27IYONGYVZTPRUZN3ANCNFSM4HHNFC3Q .

kerem-signifai commented 5 years ago

@eltmon I tried with a new API key for the test virtual machine which is actually probably just better referred to as a DigitalOcean server. The new API credentials and old worked on my local machine but neither did on the server. Yes the hostnames would be different because locally I am just using localhost.

If I dispatch request for access token from my server and use the received access token on my local machine it works. However, even after doing that, the same access token still won't work on the server.

eltmon commented 5 years ago

If you are accessing your app using "localhost" instead of a hostname that may be the issue. You should use a real hostname, although you can spoof that host name by modifying your /etc/hosts file or using something like ngrok.io

Also, not sure why, but in my player I call Napster.player.auth() in my 'ready' event callback, and I also call Napster.member.set() after calling Napster.init

On Sun, Apr 21, 2019 at 9:03 PM kerem notifications@github.com wrote:

@eltmon https://github.com/eltmon I tried with a new API key for the test virtual machine which is actually probably just better referred to as a DigitalOcean server. The new API credentials and old worked on my local machine but neither did on the server. Yes the hostnames would be different because locally I am just using localhost.

If I dispatch request for access token from my server and use the received access token on my local machine it works. However, even after doing that, the same access token still won't work on the server.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Napster/napster.js/issues/17#issuecomment-485318371, or mute the thread https://github.com/notifications/unsubscribe-auth/AAFFWPZDADSGXGLFHFSV35TPRU2KVANCNFSM4HHNFC3Q .

kerem-signifai commented 5 years ago

@eltmon Yup, same problem when using ngrok.io. Interesting, how are hostnames relevant here?

And when I called Napster.player.auth() after calling Napter.member.set() I got a warning along the lines of ... already initialised

kerem-signifai commented 5 years ago

Deployed a fresh clone of the repository onto the server and ran the example app. Still the same failure, even though I am authenticating using the recommended implicit authentication.

kerem-signifai commented 5 years ago

not sure how much of a help this is, but when I tried to go through streaming-player.js and log a few objects/stack traces and I see that when I run on the server or I run through ngrok, the client will dispatch a XMLHttpRequest but I don't see that same request if I connect directly to localhost.

eltmon commented 5 years ago

Does it work if you use the curl command? I wonder if it's an issue with how you re setting your header?

curl -v -X POST -u "{api_key}:{api_secret}" -d "username=user@domain.com&password=secret&grant_type=password" "https://api.napster.com/oauth/token"

On Mon, Apr 22, 2019 at 12:00 AM kerem notifications@github.com wrote:

not sure how much of a help this is, but when I tried to go through streaming-player.js and log a few objects/stack traces and I see that when I run on the server or I run through ngrok, the client will dispatch a XMLHttpRequest but I don't see that same request if I connect directly to localhost.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Napster/napster.js/issues/17#issuecomment-485345014, or mute the thread https://github.com/notifications/unsubscribe-auth/AAFFWPYBUOJY7IKWN27FX3LPRVPAFANCNFSM4HHNFC3Q .

kerem-signifai commented 5 years ago

@eltmon Same issue. BTW, on the deployment that does not work, I see that the method trigger("loadedmetadata") is called but not on the localhost deployment, in which case I see `trigger("enabledchange") called, and not on server.

kerem-signifai commented 5 years ago

When e.prototype.setSource is called, it appears that e.selectSourceHandler(t, this.options_) is returning different source handlers on each environment. On localhost:

{canHandleSource: ƒ, handleSource: ƒ, canPlayType: ƒ}
canHandleSource: ƒ e(t)
arguments: (...)
caller: (...)
length: 1
name: "e"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: streaming-player.js?…1555949969808:18144
[[Scopes]]: Scopes[2]
canPlayType: ƒ e(t)
arguments: (...)
caller: (...)
length: 1
name: "e"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: streaming-player.js?…1555949969808:18159
[[Scopes]]: Scopes[2]
handleSource: ƒ e(t, r, n)
arguments: (...)
caller: (...)
length: 3
name: "e"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: streaming-player.js?…1555949969808:18156
[[Scopes]]: Scopes[2]
__proto__: Object

On the server:

{name: "videojs-http-streaming", VERSION: "1.5.1", canHandleSource: ƒ, handleSource: ƒ, canPlayType: ƒ}
VERSION: "1.5.1"
canHandleSource: ƒ e(t)
arguments: null
caller: null
length: 1
name: "e"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: VM83:75002
[[Scopes]]: Scopes[3]
canPlayType: ƒ e(t)
arguments: null
caller: null
length: 1
name: "e"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: VM83:75015
[[Scopes]]: Scopes[3]
handleSource: ƒ e(t, r)
arguments: null
caller: null
length: 2
name: "e"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: VM83:75007
[[Scopes]]: Scopes[3]
name: "videojs-http-streaming"
__proto__: Object

Formatting is off but I think the difference is clear.

kerem-signifai commented 5 years ago

Looks like u.a.navigator.requestMediaKeySystemAccess was undefined. This happens in insecure contexts and localhost is apparently considered a secured context. Setting up HTTPS on my server fixed it.

Now, shouldn't this have triggered:

                r.trigger(n.KEY_SYSTEM_ACCESS_COMPLETE, {
                    error: "Insecure origins are not allowed"
                });

?

eltmon commented 5 years ago

Thanks for sharing your resolution. I had known https (ssl) was required, but didn't know it would cause that issue.

Congrats, good luck on whatever you are building!

On Mon, Apr 22, 2019 at 10:38 AM kerem notifications@github.com wrote:

Looks like u.a.navigator.requestMediaKeySystemAccess was undefined. This happens in insecure contexts and localhost is apparently considered a secured context. Setting up HTTPS on my server fixed it.

Now, shouldn't this have triggered:

            r.trigger(n.KEY_SYSTEM_ACCESS_COMPLETE, {
                error: "Insecure origins are not allowed"
            });


—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/Napster/napster.js/issues/17#issuecomment-485488251>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAFFWP75ZIVUP3XOPI4CCYTPRXZYPANCNFSM4HHNFC3Q>
.
cleio commented 5 years ago

Hi @kerem-signifai! You are correct, some browsers are refusing videojs player without SSL - and in production environment SSL should always be enabled, but if you prefer to develop or test on http, you can use Firefox browser (it allows playback without https). :) Thank you for reporting this issue, and finding the solution!