Skip to content

Commit dce4220

Browse files
authored
Merge pull request #5889 from TaykYoku/8.0_fixOAuth
[8.0][OAuth 2] fix bugs in TokenManager, AuthServer
2 parents 6f47700 + 26be3d7 commit dce4220

File tree

5 files changed

+24
-27
lines changed

5 files changed

+24
-27
lines changed

src/DIRAC/FrameworkSystem/API/AuthHandler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ def get_redirect(self, state, error=None, error_description="", chooseScope=[]):
382382

383383
# RESPONSE to basic DIRAC client request
384384
resp = self.server.create_authorization_response(response, grant_user)
385-
if not resp.payload.startswith("<!DOCTYPE html>"):
385+
if isinstance(resp.payload, str) and not resp.payload.startswith("<!DOCTYPE html>"):
386386
resp.payload = getHTML("authorization response", state=resp.status_code, body=resp.payload)
387387
return resp
388388

src/DIRAC/FrameworkSystem/Client/TokenManagerClient.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from DIRAC.Core.Utilities.DictCache import DictCache
77
from DIRAC.Core.Base.Client import Client, createClient
88
from DIRAC.ConfigurationSystem.Client.Helpers import Registry
9+
from DIRAC.Resources.IdProvider.IdProviderFactory import IdProviderFactory
910

1011
gTokensSync = ThreadSafe.Synchronizer()
1112

@@ -20,6 +21,7 @@ def __init__(self, **kwargs):
2021
super(TokenManagerClient, self).__init__(**kwargs)
2122
self.setServer("Framework/TokenManager")
2223
self.__tokensCache = DictCache()
24+
self.idps = IdProviderFactory()
2325

2426
@gTokensSync
2527
def getToken(
@@ -53,9 +55,9 @@ def getToken(
5355
return result
5456
idpObj = result["Value"]
5557

56-
if userGroup and (groupScope := idpObj.getGroupScopes(userGroup)):
58+
if userGroup and (result := idpObj.getGroupScopes(userGroup))["OK"]:
5759
# What scope correspond to the requested group?
58-
scope = list(set((scope or []) + groupScope))
60+
scope = list(set((scope or []) + result["Value"]))
5961

6062
# Set the scope
6163
idpObj.scope = " ".join(scope)

src/DIRAC/FrameworkSystem/Service/TokenManagerHandler.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646

4747
class TokenManagerHandler(TornadoService):
4848

49-
DEFAULT_AUTHENTICATION = ["authenticated"]
49+
DEFAULT_AUTHORIZATION = ["authenticated"]
5050
DEFAULT_RT_EXPIRATION_TIME = 24 * 3600
5151

5252
@classmethod
@@ -211,9 +211,9 @@ def export_getToken(
211211
return result
212212
idpObj = result["Value"]
213213

214-
if userGroup and (groupScope := idpObj.getGroupScopes(userGroup)):
214+
if userGroup and (result := idpObj.getGroupScopes(userGroup))["OK"]:
215215
# What scope correspond to the requested group?
216-
scope = list(set((scope or []) + groupScope))
216+
scope = list(set((scope or []) + result["Value"]))
217217

218218
# Set the scope
219219
idpObj.scope = " ".join(scope)

src/DIRAC/FrameworkSystem/private/authorization/AuthServer.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
""" This class provides authorization server activity. """
22
import re
3-
import six
43
import json
54
import pprint
65
from dominate import tags as dom
@@ -343,11 +342,15 @@ def handle_response(self, status_code=None, payload=None, headers=None, newSessi
343342
344343
:return: TornadoResponse()
345344
"""
346-
sLog.debug(
347-
f"Handle authorization response with {status_code} status code:",
348-
"HTML page" if isinstance(payload, str) and payload.startswith("<!DOCTYPE html>") else payload,
349-
)
350345
resp = TornadoResponse(payload, status_code)
346+
if not isinstance(payload, dict):
347+
sLog.debug(
348+
f"Handle authorization response with {status_code} status code:",
349+
"HTML page" if payload.startswith("<!DOCTYPE html>") else payload,
350+
)
351+
elif "error" in payload:
352+
resp.clear_cookie("auth_session") # pylint: disable=no-member
353+
sLog.error(f"{payload['error']}: {payload.get('error_description', 'unknown')}")
351354
if headers:
352355
sLog.debug("Headers:", headers)
353356
for key, value in headers:
@@ -356,7 +359,7 @@ def handle_response(self, status_code=None, payload=None, headers=None, newSessi
356359
sLog.debug("Initialize new session:", newSession)
357360
# pylint: disable=no-member
358361
resp.set_secure_cookie("auth_session", json.dumps(newSession), secure=True, httponly=True)
359-
if delSession or isinstance(payload, dict) and "error" in payload:
362+
if delSession:
360363
resp.clear_cookie("auth_session") # pylint: disable=no-member
361364
return resp
362365

@@ -386,18 +389,13 @@ def validate_consent_request(self, request, provider=None):
386389
387390
:return: response generated by `handle_response` or S_ERROR or html
388391
"""
389-
if request.method != "GET":
390-
return self.handle_response(
391-
payload=getHTML("use GET method", theme="error", info="Use GET method to access this endpoint."),
392-
delSession=True,
393-
)
394392
try:
395393
request = self.create_oauth2_request(request)
396394
# Check Identity Provider
397395
req = self.validateIdentityProvider(request, provider)
398396

399-
# If return IdP selector
400-
if isinstance(req, six.string_types):
397+
# If return HTML page with IdP selector
398+
if isinstance(req, str):
401399
return req
402400

403401
sLog.info("Validate consent request for ", req.state)

src/DIRAC/Resources/IdProvider/OAuth2IdProvider.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from authlib.oidc.discovery.well_known import get_well_known_url
1515
from authlib.oauth2.rfc7636 import create_s256_code_challenge
1616

17-
from DIRAC.FrameworkSystem.private.authorization.utils.Requests import createOAuth2Request
1817

1918
from DIRAC import S_OK, S_ERROR
2019
from DIRAC.Core.Utilities import ThreadSafe
@@ -27,6 +26,7 @@
2726
getVOs,
2827
)
2928
from DIRAC.FrameworkSystem.private.authorization.utils.Tokens import OAuth2Token
29+
from DIRAC.FrameworkSystem.private.authorization.utils.Requests import createOAuth2Request
3030

3131
DEFAULT_HEADERS = {"Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"}
3232

@@ -407,9 +407,9 @@ def deviceAuthorization(self, group=None):
407407

408408
# Notify user to go to authorization endpoint
409409
if response.get("verification_uri_complete"):
410-
showURL = "Use next link to continue\n%s" % response["verification_uri_complete"]
410+
showURL = "Use the following link to continue\n%s" % response["verification_uri_complete"]
411411
else:
412-
showURL = 'Use next link to continue, your user code is "%s"\n%s' % (
412+
showURL = 'Use the following link to continue, your user code is "%s"\n%s' % (
413413
response["user_code"],
414414
response["verification_uri"],
415415
)
@@ -543,13 +543,10 @@ def getGroupScopes(self, group: str) -> list:
543543
return scope_to_list(idPScope) if idPScope else []
544544

545545
def getScopeGroups(self, scope: str) -> list:
546-
"""Get DIRAC groups related to scope
547-
548-
:param scope: scope
549-
"""
546+
"""Get DIRAC groups related to scope"""
550547
groups = []
551548
for group in getAllGroups():
552-
if g_scope := self.getGroupScopes(group) and set(g_scope).issubset(scope_to_list(scope)):
549+
if (g_scope := self.getGroupScopes(group)) and set(g_scope).issubset(scope_to_list(scope)):
553550
groups.append(group)
554551
return groups
555552

0 commit comments

Comments
 (0)