Help getting Channel to run as logged in user, rather than server admin

I’m running into an issue in getting my plugin to access the logged in user’s playlists, rather than the server admin regardless of who is logged in.

I initially was getting my token from os.environ['PLEXTOKEN'], and setting HTTP.Headers['X-Plex-Token'] to that. Understandably, this was always responding as the admin.

However, I then tried switching to user_token = Request.Headers.get('X-Plex-Token', ''). This does allow me to get the proper user’s token. I’ve verified that the token is proper by going to https://127.0.0.1:32400/playlists/?X-Plex-Token=xxx in a browser, and it returns the proper data.

So since I want to use that user_token, I was setting HTTP.Headers['X-Plex-Token'] = user_token, however I observed that the code in networking.py will override whatever you set X-Plex-Token to back to os.environ['PLEXTOKEN'] regardless of your settings (This is at lines 172-173 of networking.py).

To see if this was a bug, I hacked out that resetting, so the X-Plex-Token was still the user’s value, but when I do that, I get a HTTPError: HTTP Error 401: Unauthorized

To try to work around this, I rammed them all together:

HTTP.Headers['X-Plex-Token'] = os.environ['PLEXTOKEN']
all_playlists_xml = XML.ElementFromURL('http://127.0.0.1:32400/playlists?X-Plex-Token=xxx') # hardcoded USER token

and lo-and-behold, it worked.

Since I’ve been told that adding ?X-Plex-Token=xxx to your URLs is bad practice, I’ve been trying to figure out how else to accomplish this. But I couldn’t find any header field that would allow me to effectively pass a 2nd token to the server (The first to be authorized by the server, the second to be the user to act as).

I did, however, try to work around the networking code overriding your set token. I modified networking.py to not override your X-Plex-Token if you have manually set it (the last “and” is the new code):

        if 'PLEXTOKEN' in os.environ and len(os.environ['PLEXTOKEN']) > 0 and self._request_headers is not None and self._url.find('http://127.0.0.1') == 0 and 'X-Plex-Token' not in self._request_headers:
		  self._request_headers['X-Plex-Token'] = os.environ['PLEXTOKEN']

This works as well, without the ?X-Plex-Token=xxx, at least for all of the URLs that I need for my plugin (which are primarily '/Playlist', '/Video', '/library/metadata/###'), but it fails for at least one URL that I found, '/myplex/account', with an HTTPError that I assume is related to the 401 I get when just trying the raw URL in a browser.

So, those are my discoveries… Now the questions:

  • Is there any header key (or other method) where I can pass the two tokens to XML.ElementFromURL()?
  • Is it wrong to add the and 'X-Plex-Token' not in self._request_headers to networking.py as an official change? (Which I guess is asking if the error from ‘/myplex/account’ is a problem with ‘/myplex/account’ rather than my change…) It seems like the code should use the headers you’ve manually set and not override them.
  • Any other suggestion for how to solve this? Thanks!

Hard to tell, with only snips of the code, instead of a link to the sourcecode :frowning:

But when said, take a peak here:

So basically, instead of

playlists = XML.ElementFromURL(url)

unwrap that code and manually do

# Darn....Hard work ahead..We have to logon as another user here :-(
myHeader = {}
myHeader['X-Plex-Token'] = users[user]['accessToken']
# TODO Change to native framework call, when Plex allows token in header
request = urllib2.Request(self.getListsURL, headers=myHeader)
playlists = XML.ElementFromString(
urllib2.urlopen(request).read())

?

I guess that would probably work!

Works fine for WebTools :wink:

@dane22 said:
Works fine for WebTools :wink:

What “works fine for WebTools”??

Edit: Oh… Duh…

@edank said:
What “works fine for WebTools”??

To logon as a selected user, and grab his playlists

Awesome, that does work! Thanks for pointing me in the right direction.

def XMLFromURLforCurrentRequest(url):
	# TODO Change to native framework call, when Plex allows token in header...
	# Really, should just be "xml = XML.ElementFromURL(url, headers={'X-Plex-Token': Request.Headers.get('X-Plex-Token', '')})"
	# But PLEX library overrides X-Plex-Token and resets it to the Admin's token regardless.
	opener = urllib2.build_opener(urllib2.HTTPHandler)
	request = urllib2.Request(url)
	request.add_header('X-Plex-Token', Request.Headers.get('X-Plex-Token', ''))
	response = opener.open(request).read()
	xml = XML.ElementFromString(response)
	return xml