Skip to content

Commit

Permalink
frontend: support grab group info from OIDC provider
Browse files Browse the repository at this point in the history
Relates: #2836
  • Loading branch information
pkking authored and praiskup committed Aug 8, 2023
1 parent db6c730 commit 97b9fe4
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 26 deletions.
44 changes: 23 additions & 21 deletions frontend/coprs_frontend/coprs/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,37 +92,26 @@ class GroupAuth:
`app.config["FAS_LOGIN"]` and `app.config["KRB5_LOGIN"]` should be
encapsulated within this class.
"""

@classmethod
def update_user_groups(cls, user, oid_resp=None):
def update_user_groups(cls, user, groups=None):
"""
Upon a successful login, try to (a) load the list of groups from
authoritative source, and (b) (re)set the user.openid_groups.
"""

def _do_update(user, grouplist):
user.openid_groups = {
"fas_groups": grouplist,
}
if not groups:
groups = []

if oid_resp:
_do_update(user, OpenIDGroups.group_names(oid_resp))
return

# If we have a LDAP pre-configured, now is the right time to load the
# data, or fail.
keys = ["LDAP_URL", "LDAP_SEARCH_STRING"]
if all(app.config[k] for k in keys):
_do_update(user, LDAPGroups.group_names(user.username))
if not isinstance(groups, list):
app.logger.error("groups should be a list object")
return

# We only ever call update_user_groups() with oid_resp!= None with FAS
assert not app.config["FAS_LOGIN"]

app.logger.warning("Nowhere to get groups from")
# This copr doesn't support groups.
_do_update(user, [])

app.logger.info(f"groups add: {groups}")
_do_update(user, groups)
return

class FedoraAccounts:
"""
Expand Down Expand Up @@ -193,7 +182,7 @@ def user_from_response(cls, oid_resp):
# Update user attributes from FAS
user.mail = oid_resp.email
user.timezone = oid_resp.timezone
GroupAuth.update_user_groups(user, oid_resp)
GroupAuth.update_user_groups(user, OpenIDGroups.group_names(oid_resp))
return user


Expand Down Expand Up @@ -239,7 +228,9 @@ def user_from_username(username, load_metadata=False):
# Create a new user object
krb_config = app.config['KRB5_LOGIN']
user.mail = username + "@" + krb_config['email_domain']
GroupAuth.update_user_groups(user)
keys = ["LDAP_URL", "LDAP_SEARCH_STRING"]
if all(app.config[k] for k in keys):
GroupAuth.update_user_groups(user, LDAPGroups.group_names(user.username))
return user

@staticmethod
Expand Down Expand Up @@ -402,4 +393,15 @@ def user_from_userinfo(userinfo):
and userinfo['zoneinfo'] else None

user = UserAuth.get_or_create_user(userinfo['username'], userinfo['email'], zoneinfo)
GroupAuth.update_user_groups(user, OpenIDConnect.groups_from_userinfo(userinfo))
return user

@staticmethod
def groups_from_userinfo(userinfo):
"""
Create a `models.User` object from oidc user info
"""
if not userinfo:
return None

return userinfo.get("groups")
3 changes: 2 additions & 1 deletion frontend/coprs_frontend/coprs/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from coprs import app
from coprs.constants import BANNER_LOCATION
from coprs.helpers import current_url
from coprs.oidc import oidc_enabled


@app.context_processor
Expand Down Expand Up @@ -67,7 +68,7 @@ def login_menu():
'desc': 'sign up',
})

if config['OIDC_LOGIN'] and config['OIDC_PROVIDER_NAME']:
if oidc_enabled(config):
menu.append({
'link': flask.url_for("misc.oidc_login"),
'desc': '{} login'.format(app.config['OIDC_PROVIDER_NAME']),
Expand Down
9 changes: 7 additions & 2 deletions frontend/coprs_frontend/coprs/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@ def is_config_valid(config):
"""
If OpenID Connect is enabled
"""
return "OIDC_LOGIN" in config and config["OIDC_LOGIN"] is True
return "OIDC_LOGIN" in config and config["OIDC_LOGIN"] is True and \
"OIDC_PROVIDER_NAME" in config and config["OIDC_PROVIDER_NAME"]


def oidc_enabled(config):
"""
Check whether the config is valid
"""
if not is_config_valid(config):
logger.error("OIDC_LOGIN or OIDC_PROVIDER_NAME is empty")
return False

if not config.get("OIDC_CLIENT"):
logger.error("OIDC_CLIENT is empty")
return False
Expand Down Expand Up @@ -47,7 +52,7 @@ def init_oidc_app(app):
When configs check failed, a invalid client object is returned
"""
oidc = OAuth(app)
if oidc_enabled(app.config) and is_config_valid(app.config):
if oidc_enabled(app.config):
client_id = app.config.get("OIDC_CLIENT")
secret = app.config.get("OIDC_SECRET")
client_kwargs = {
Expand Down
4 changes: 2 additions & 2 deletions frontend/coprs_frontend/tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from unittest import mock
from tests.coprs_test_case import CoprsTestCase
from coprs import app
from coprs.auth import GroupAuth
from coprs.auth import GroupAuth, LDAPGroups


class TestGroupAuth(CoprsTestCase):
Expand All @@ -29,7 +29,7 @@ def test_group_names_ldap(self, get_user_groups):
b'cn=another-group-2,ou=foo,ou=bar,dc=company,dc=com'
]
user = mock.MagicMock()
GroupAuth.update_user_groups(user)
GroupAuth.update_user_groups(user, LDAPGroups.group_names(user.username))
assert user.openid_groups == {
"fas_groups": ["group1", "group2", "another-group",
"another-group-2"]}

0 comments on commit 97b9fe4

Please sign in to comment.