mirror of
https://github.com/hrfee/jellyfin-accounts.git
synced 2024-12-23 01:20:12 +00:00
Added ability to log in with jellyfin credentials
The new jellyfin_login and admin_only allow anyone use their username and password from jellyfin to login to the admin page, and restrict this to jellyfin admins only, respectively.
This commit is contained in:
parent
9b8204eb12
commit
b9cefcc111
@ -46,7 +46,7 @@ Usually as simple as:
|
|||||||
```
|
```
|
||||||
git clone https://github.com/hrfee/jellyfin-accounts.git
|
git clone https://github.com/hrfee/jellyfin-accounts.git
|
||||||
cd jellyfin-accounts
|
cd jellyfin-accounts
|
||||||
pip3 install -r requirements.txt
|
pip3 install pyOpenSSL
|
||||||
python3 setup.py install
|
python3 setup.py install
|
||||||
```
|
```
|
||||||
If not, or if you want to use docker, see [install](https://github.com/hrfee/jellyfin-accounts/wiki/Install).
|
If not, or if you want to use docker, see [install](https://github.com/hrfee/jellyfin-accounts/wiki/Install).
|
||||||
@ -102,8 +102,15 @@ device_id = jf-accounts-0.1
|
|||||||
; Set 0.0.0.0 to run localhost
|
; Set 0.0.0.0 to run localhost
|
||||||
host = 0.0.0.0
|
host = 0.0.0.0
|
||||||
port = 8056
|
port = 8056
|
||||||
|
; Enable this to use Jellyfin users instead of the below username and pw.
|
||||||
|
jellyfin_login = true
|
||||||
|
; Allows only admin users on Jellyfin to access admin page.
|
||||||
|
admin_only = true
|
||||||
|
; Username to use on admin page... (leave blank if using jellyfin_login)
|
||||||
username = your username
|
username = your username
|
||||||
|
; ..and its corresponding password (leave blank if using jellyfin_login)
|
||||||
password = your password
|
password = your password
|
||||||
|
|
||||||
debug = false
|
debug = false
|
||||||
|
|
||||||
; Displayed at the bottom of all pages except admin
|
; Displayed at the bottom of all pages except admin
|
||||||
|
@ -13,8 +13,15 @@ device_id = jf-accounts-0.1
|
|||||||
; Set 0.0.0.0 to run localhost
|
; Set 0.0.0.0 to run localhost
|
||||||
host = 0.0.0.0
|
host = 0.0.0.0
|
||||||
port = 8056
|
port = 8056
|
||||||
|
; Enable this to use Jellyfin users instead of the below username and pw.
|
||||||
|
jellyfin_login = true
|
||||||
|
; Allows only admin users on Jellyfin to access admin page.
|
||||||
|
admin_only = true
|
||||||
|
; Username to use on admin page... (leave blank if using jellyfin_login)
|
||||||
username = your username
|
username = your username
|
||||||
|
; ..and its corresponding password (leave blank if using jellyfin_login)
|
||||||
password = your password
|
password = your password
|
||||||
|
|
||||||
debug = false
|
debug = false
|
||||||
|
|
||||||
; Displayed at the bottom of all pages except admin
|
; Displayed at the bottom of all pages except admin
|
||||||
|
@ -8,21 +8,46 @@ from passlib.apps import custom_app_context as pwd_context
|
|||||||
import uuid
|
import uuid
|
||||||
from __main__ import config, app, g
|
from __main__ import config, app, g
|
||||||
from __main__ import auth_log as log
|
from __main__ import auth_log as log
|
||||||
|
from jellyfin_accounts.jf_api import Jellyfin
|
||||||
|
from jellyfin_accounts.web_api import jf
|
||||||
|
|
||||||
|
|
||||||
|
def tempJF():
|
||||||
|
return Jellyfin(config['jellyfin']['server'],
|
||||||
|
config['jellyfin']['client'],
|
||||||
|
config['jellyfin']['version'],
|
||||||
|
config['jellyfin']['device'] + '_temp',
|
||||||
|
config['jellyfin']['device_id'] + '_temp')
|
||||||
|
|
||||||
class Account():
|
class Account():
|
||||||
def __init__(self, username, password):
|
def __init__(self, username=None, password=None):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password_hash = pwd_context.hash(password)
|
if password is not None:
|
||||||
self.id = str(uuid.uuid4())
|
self.password_hash = pwd_context.hash(password)
|
||||||
|
self.id = str(uuid.uuid4())
|
||||||
|
self.jf = False
|
||||||
|
elif username is not None:
|
||||||
|
jf.authenticate(config['jellyfin']['username'],
|
||||||
|
config['jellyfin']['password'])
|
||||||
|
self.id = jf.getUsers(self.username, public=False)['Id']
|
||||||
|
self.jf = True
|
||||||
def verify_password(self, password):
|
def verify_password(self, password):
|
||||||
return pwd_context.verify(password, self.password_hash)
|
if not self.jf:
|
||||||
|
return pwd_context.verify(password, self.password_hash)
|
||||||
|
else:
|
||||||
|
temp_jf = tempJF()
|
||||||
|
try:
|
||||||
|
return temp_jf.authenticate(self.username, password)
|
||||||
|
except Jellyfin.AuthenticationError:
|
||||||
|
return False
|
||||||
def generate_token(self, expiration=1200):
|
def generate_token(self, expiration=1200):
|
||||||
s = Serializer(app.config['SECRET_KEY'], expires_in=expiration)
|
s = Serializer(app.config['SECRET_KEY'], expires_in=expiration)
|
||||||
|
log.debug(self.id)
|
||||||
return s.dumps({ 'id': self.id })
|
return s.dumps({ 'id': self.id })
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def verify_token(token, account):
|
def verify_token(token, accounts):
|
||||||
|
log.debug(f'verifying token {token}')
|
||||||
s = Serializer(app.config['SECRET_KEY'])
|
s = Serializer(app.config['SECRET_KEY'])
|
||||||
try:
|
try:
|
||||||
data = s.loads(token)
|
data = s.loads(token)
|
||||||
@ -30,27 +55,65 @@ class Account():
|
|||||||
return None
|
return None
|
||||||
except BadSignature:
|
except BadSignature:
|
||||||
return None
|
return None
|
||||||
if data['id'] == account.id:
|
if config.getboolean('ui', 'jellyfin_login'):
|
||||||
return account
|
for account in accounts:
|
||||||
|
if data['id'] == accounts[account].id:
|
||||||
|
return account
|
||||||
|
else:
|
||||||
|
return accounts['adminAccount']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
auth = HTTPBasicAuth()
|
auth = HTTPBasicAuth()
|
||||||
|
|
||||||
|
accounts = {}
|
||||||
|
|
||||||
adminAccount = Account(config['ui']['username'], config['ui']['password'])
|
if not config.getboolean('ui', 'jellyfin_login'):
|
||||||
|
accounts['adminAccount'] = Account(config['ui']['username'],
|
||||||
|
config['ui']['password'])
|
||||||
|
|
||||||
|
|
||||||
@auth.verify_password
|
@auth.verify_password
|
||||||
def verify_password(username, password):
|
def verify_password(username, password):
|
||||||
user = adminAccount.verify_token(username, adminAccount)
|
user = None
|
||||||
if not user:
|
verified = False
|
||||||
if username == adminAccount.username and adminAccount.verify_password(password):
|
log.debug('Verifying auth')
|
||||||
g.user = adminAccount
|
if config.getboolean('ui', 'jellyfin_login'):
|
||||||
|
try:
|
||||||
|
jf_user = jf.getUsers(username, public=False)
|
||||||
|
id = jf_user['Id']
|
||||||
|
user = accounts[id]
|
||||||
|
except KeyError:
|
||||||
|
if config.getboolean('ui', 'admin_only'):
|
||||||
|
if jf_user['Policy']['IsAdministrator']:
|
||||||
|
user = Account(username)
|
||||||
|
accounts[id] = user
|
||||||
|
else:
|
||||||
|
log.debug(f'User {username} not admin.')
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
user = Account(username)
|
||||||
|
accounts[id] = user
|
||||||
|
except Jellyfin.UserNotFoundError:
|
||||||
|
user = Account().verify_token(username, accounts)
|
||||||
|
if user:
|
||||||
|
verified = True
|
||||||
|
if not user:
|
||||||
|
log.debug(f'User {username} not found on Jellyfin')
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
user = accounts['adminAccount']
|
||||||
|
verified = Account().verify_token(username, accounts)
|
||||||
|
|
||||||
|
if not verified:
|
||||||
|
if username == user.username and user.verify_password(password):
|
||||||
|
g.user = user
|
||||||
log.debug("HTTPAuth Allowed")
|
log.debug("HTTPAuth Allowed")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
log.debug("HTTPAuth Denied")
|
log.debug("HTTPAuth Denied")
|
||||||
return False
|
return False
|
||||||
g.user = adminAccount
|
g.user = user
|
||||||
log.debug("HTTPAuth Allowed")
|
log.debug("HTTPAuth Allowed")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import secrets
|
|||||||
import time
|
import time
|
||||||
from __main__ import config, config_path, app, g
|
from __main__ import config, config_path, app, g
|
||||||
from __main__ import web_log as log
|
from __main__ import web_log as log
|
||||||
from jellyfin_accounts.login import auth
|
|
||||||
from jellyfin_accounts.validate_password import PasswordValidator
|
from jellyfin_accounts.validate_password import PasswordValidator
|
||||||
|
|
||||||
def resp(success=True, code=500):
|
def resp(success=True, code=500):
|
||||||
@ -51,6 +50,8 @@ jf = Jellyfin(config['jellyfin']['server'],
|
|||||||
config['jellyfin']['device'],
|
config['jellyfin']['device'],
|
||||||
config['jellyfin']['device_id'])
|
config['jellyfin']['device_id'])
|
||||||
|
|
||||||
|
from jellyfin_accounts.login import auth
|
||||||
|
|
||||||
attempts = 0
|
attempts = 0
|
||||||
success = False
|
success = False
|
||||||
while attempts != 3:
|
while attempts != 3:
|
||||||
@ -262,7 +263,6 @@ def deleteInvite():
|
|||||||
@auth.login_required
|
@auth.login_required
|
||||||
def get_token():
|
def get_token():
|
||||||
token = g.user.generate_token()
|
token = g.user.generate_token()
|
||||||
log.debug('Token generated')
|
|
||||||
return jsonify({'token': token.decode('ascii')})
|
return jsonify({'token': token.decode('ascii')})
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user