The code starting at https://github.com/openstack/django_openstack_auth/blob/master/openstack_auth/policy.py#L130 sets four keys on the policy check target equal to the user's domain id (e.g the domain in which the user was created). Line 144 then reassigns the 'domain_id' key with the domain to which the user has a scoped token *if* they have such a token.
This creates a double meaning for domain_id. When keystone uses 'domain_id' in policy checks, the meaning is 'the domain to which a token is scoped', so a check for 'is a domain admin' might be 'role:admin and domain_id:%(domain_id)s'. Under Horizon this doesn't work, since the domain_id part essentially always passes, and thus a project admin is indistinguishable from a domain admin.
My proposal is to set domain_id only if there is a domain scoped token. If a policy check actually requires the user's domain, it can use attributes on the token (token.user.domain.id).
One example problem case is where you are the admin of a project; the admin_and_ matching_ domain_ id rule is defined as "rule:admin_ required and domain_ id:%(domain_ id)s". Since in the existing code the domain_ id:%(domain_ id)s is equivalent to user_domain_ id==user_ domain_ id it always passes and thus you are a domain admin.
openstack_ dashboard/ api/keystone uses this rule for 'is_domain_admin', which then tries to make API calls against keystone that will fail depending how keystone's policy file is set up (and logically should fail).