'Populate roles basing on provided groups and project/domain.
Used for federated users with dynamically assigned groups.
This method does not return anything, yet it modifies token_data in
place.
:param token_data: a dictionary used for building token response
:param group_ids: list of group IDs a user is a member of
:param project_id: project ID to scope to
:param domain_id: domain ID to scope to
:param user_id: user ID
:raises keystone.exception.Unauthorized: when no roles were found'

def populate_roles_for_federated_user(self, token_data, group_ids, project_id=None, domain_id=None, user_id=None):

    def check_roles(roles, user_id, project_id, domain_id):
        if roles:
            return
        if project_id:
            msg = (_('User    %(user_id)s    has    no    access    to    project    %(project_id)s') % {'user_id': user_id, 'project_id': project_id})
        elif domain_id:
            msg = (_('User    %(user_id)s    has    no    access    to    domain    %(domain_id)s') % {'user_id': user_id, 'domain_id': domain_id})
        raise exception.Unauthorized(msg)
    roles = self.assignment_api.get_roles_for_groups(group_ids, project_id, domain_id)
    roles = (roles + self._get_roles_for_user(user_id, domain_id, project_id))
    roles = [dict(t) for t in set([tuple(d.items()) for d in roles])]
    check_roles(roles, user_id, project_id, domain_id)
    token_data['roles'] = roles
