Shared item federation uses a simple token

merge-requests/30/head
Bob Mottram 2021-07-26 10:08:36 +01:00
parent cf9bffbed7
commit 4c8b96efc1
2 changed files with 38 additions and 40 deletions

56
auth.py
View File

@ -179,37 +179,34 @@ def generateSharedItemFederationTokens(sharedItemsFederatedDomains: [],
fp.write(line + '\n') fp.write(line + '\n')
def authorizeDFC(sharedItemsFederatedDomains: [], def authorizeSharedItems(sharedItemsFederatedDomains: [],
baseDir: str, baseDir: str,
callingDomain: str, callingDomain: str,
authHeader: str, authHeader: str,
debug: bool) -> bool: debug: bool) -> bool:
"""HTTP basic auth for shared item federation """HTTP simple token check for shared item federation
""" """
if not sharedItemsFederatedDomains:
# no shared item federation
return False
if callingDomain not in sharedItemsFederatedDomains: if callingDomain not in sharedItemsFederatedDomains:
if debug: if debug:
print(callingDomain + print(callingDomain +
' is not in the shared items federation list') ' is not in the shared items federation list')
return False return False
if 'Basic ' not in authHeader: if 'Basic ' in authHeader:
if debug: if debug:
print('DEBUG: DFC basic auth - Authorisation header does not ' + print('DEBUG: shared item federation should not use basic auth')
'contain a space character')
return False return False
base64Str = \ providedToken = authHeader.replace('\n', '').replace('\r', '').strip()
authHeader.split(' ')[1].replace('\n', '').replace('\r', '') if not providedToken:
plain = base64.b64decode(base64Str).decode('utf-8')
if ':' not in plain:
if debug: if debug:
print('DEBUG: DFC basic auth header does not contain a ":" ' + print('DEBUG: shared item federation token is empty')
'separator for username:password')
return False return False
basicAuthDomain = plain.split(':')[0] if len(providedToken) < 60:
if basicAuthDomain != callingDomain:
if debug: if debug:
print('DEBUG: DFC calling domain does not match ' + print('DEBUG: shared item federation token is too small ' +
'the one in the Authorization header (' + providedToken)
basicAuthDomain + ')')
return False return False
tokensFile = baseDir + '/accounts/sharedItemsFederationTokens' tokensFile = baseDir + '/accounts/sharedItemsFederationTokens'
if not os.path.isfile(tokensFile): if not os.path.isfile(tokensFile):
@ -217,21 +214,22 @@ def authorizeDFC(sharedItemsFederatedDomains: [],
print('DEBUG: shared item federation tokens file missing ' + print('DEBUG: shared item federation tokens file missing ' +
tokensFile) tokensFile)
return False return False
providedToken = plain.split(':')[1] # check the tokens file
with open(tokensFile, 'r') as tokfile: with open(tokensFile, 'r') as tokfile:
for line in tokfile: for line in tokfile:
if not line.startswith(basicAuthDomain + ':'): if not line.startswith(callingDomain + ':'):
continue continue
storedToken = \ storedToken = \
line.split(':')[1].replace('\n', '').replace('\r', '') line.split(':')[1].replace('\n', '').replace('\r', '')
success = _verifyPassword(storedToken, providedToken) if constantTimeStringCheck(storedToken, providedToken):
if not success: return True
else:
if debug: if debug:
print('DEBUG: DFC token check failed for ' + print('DEBUG: shared item federation token ' +
basicAuthDomain) 'check failed for ' + callingDomain)
return success return False
print('DEBUG: DFC did not find token for ' + basicAuthDomain + print('DEBUG: shared item federation token for ' + callingDomain +
' in ' + tokensFile) ' not found in ' + tokensFile)
return False return False

View File

@ -106,7 +106,7 @@ from skills import setActorSkillLevel
from auth import generateSharedItemFederationTokens from auth import generateSharedItemFederationTokens
from auth import recordLoginFailure from auth import recordLoginFailure
from auth import authorize from auth import authorize
from auth import authorizeDFC from auth import authorizeSharedItems
from auth import createPassword from auth import createPassword
from auth import createBasicAuthHeader from auth import createBasicAuthHeader
from auth import authorizeBasic from auth import authorizeBasic
@ -10669,19 +10669,19 @@ class PubServer(BaseHTTPRequestHandler):
'show logout', 'isAuthorized') 'show logout', 'isAuthorized')
if self.path.startswith('/dfc-catalog'): if self.path.startswith('/dfc-catalog'):
catalogAuthorized = False catalogAuthorized = authorized
if authorized: if not catalogAuthorized:
catalogAuthorized = True
else:
# basic auth access to shared items catalog # basic auth access to shared items catalog
if self.headers.get('Authorization'): if self.headers.get('Authorization'):
if authorizeDFC(self.server.sharedItemsFederatedDomains, permittedDomains = \
self.server.baseDir, self.server.sharedItemsFederatedDomains
callingDomain, if authorizeSharedItems(permittedDomains,
self.headers['Authorization'], self.server.baseDir,
self.server.debug): callingDomain,
self.headers['Authorization'],
self.server.debug):
catalogAuthorized = True catalogAuthorized = True
# show shared items DFC catalog # show shared items catalog for federation
if self._hasAccept(callingDomain) and catalogAuthorized: if self._hasAccept(callingDomain) and catalogAuthorized:
catalogType = 'html' catalogType = 'html'
if self.path.endswith('.csv') or self._requestCSV(): if self.path.endswith('.csv') or self._requestCSV():