def METHOD_NAME(user, roles: Tuple[str] = None):
    """
    Add users to groups based on roles from single sign-on identity provider
    Business role for registries:
      adjudicator: e.g. Groundwater Data Specialist
        Enters applications for new or existing registrants.
          read/write access to: Person, Organization, Application, Registration
      authority: e.g. Deputy Comptroller
        Approves changes to application or registration status
          read/write access to: Person, Organization, Application, Registration,
            ApplicationStatus, RegistrationStatus
      viewer: e.g. Groundwater Protection Officer
          read only access to: Person, Organization, Application, Registration
    Business roles for aquifers:
        TBD
    Business roles for wells and submissions:
        TBD
    """
    if user is None:
        raise exceptions.AuthenticationFailed(
            'Failed to retrieve user to apply roles to')
    user_group_names = [group.name for group in user.groups.all()]
    role_change = False
    for role in roles:
        # if user is not in their role group, add them
        if role not in user_group_names and role not in EXCLUDE:
            # When a role/group is newly assigned, there may be many parallel processes that try to add
            # a create a group, and add a user to a group.
            # We don't want to lock - that can slow everything down. If there's an integrity error,
            # we don't really care either, it just means someone beat us to it, so we don't allow the
            # exception to bubble up, we just log it.
            # This is an unfortunate side effect of how we've decided to handle sso->django integration.
            group = Group.objects.filter(name=role).first()
            if not group:
                # From time to time, a new role will be added to keycloak, and this role will not yet
                # exist in the django database as a group. When this happens, we create it.
                logger.info('Group "{}" does not exist. Creating it....'.format(role))
                group = Group(name=role)
                try:
                    group.save()
                except IntegrityError as e:
                    logger.info(e)
                    # In the time we tried to create this group, someone may have beat us to it! Try to
                    # reload it again.
                    group = Group.objects.filter(name=role).first()
                    if not group:
                        # Uh oh - can't create it, can't load it - out of ideas!
                        raise
            try:
                group.user_set.add(user)
            except IntegrityError as e:
                logger.info(e)
            role_change = True
    # check if user has been removed from their SSO (Keycloak) group
    for group in user_group_names:
        if group not in roles:
            user.groups.get(name=group).user_set.remove(user)
            role_change = True
    if role_change:
        user.refresh_from_db()