OIDC Provider Scope Templating

Hello! I’ve used the Vault OIDC provider for a couple of applications now, Waypoint and Grafana. With Grafana though, one of the required identifiers for a user is their email address. Currently with my Vault’s auth methods, I don’t have a user’s email address set in their metadata (seeing if I can achieve this with my LDAP provider now, also as an alternative I’m evaluating if I want the “username” of the LDAP entity alias metadata to actually be the user’s email address instead of their LDAP username).

However in the meantime, my scope looks something like this:

{
    "Name": {{identity.entity.aliases.auth_ldap_abcd1234.name}},
    "Email": "email@company.com",
    "groups": {{identity.entity.groups.names}}
}

This was nothing more than a hacky workaround to give Grafana what it wanted (an email address), and give my Vault users the ability to login. When doing so, their username is set to their LDAP username, and their email is set to “email@company.com”. Obviously not ideal, but the problem is that the next person who accesses Grafana is logged in as the last-logged-in-user from OIDC, whether or not it is them, possibly resulting in privilege escalation to admin (see OpenID unique user identifier · Issue #17635 · grafana/grafana · GitHub).

So at this point, I’m trying to do something like this with my scope, so that the email is unique to each user:

{
    "Name": {{identity.entity.aliases. auth_ldap_abcd1234.name}},
    "Email": "{{identity.entity.aliases. auth_ldap_abcd1234.name}}@company.com",
    "groups": {{identity.entity.groups.names}}
}

When attempting to update the scope, though, Vault is unhappy:

✗ vault write identity/oidc/scope/user template="$(echo $TEMPLATE | base64 -)"
Error writing data to identity/oidc/scope/user: Error making API request.

URL: PUT https://vault.service.dc1.consul:8200/v1/identity/oidc/scope/user
Code: 400. Errors:

* error parsing template JSON: invalid character '"' after object key:value pair

I’ve tried this with and without quotes around the value for “Email”, escape characters, etc., to no avail so far. So my question is - is it currently possible with Vault OIDC provider scopes to “concatenate” a dynamically templated value alongside a static string in a scope?

Your question has helped me realise why this code exists in Vault:

Unfortunately for your use-case, it looks like the template expansions are hard-coded to return complete JSON objects, be they strings, lists or maps, so there is no way to do what you’re trying to do here.

In my experience working with OAuth/OIDC, there are enough hard interoperability problems bridging between different systems expectations, that you really need the ability to write arbitrary code in your IdP to process claims - in this case you need an IdP capable of going back to your LDAP server to retrieve additional attributes and turn them into OIDC claims. Vault’s IdP doesn’t have this flexibility (and is a tech preview not intended for production, according to OIDC Identity Provider | Vault by HashiCorp), so it may be worth looking at other available options.

If you really have to do this in Vault, you might be able to manage with a cronjob that periodically synchronises email addresses from your LDAP directory into Vault Identity entity or entity-alias metadata. With this solution, you’d have to live with the issue that a new user wouldn’t be able to log in until the next periodic sync has picked up their account.

1 Like

Can’t you just do something like

“Email”: “{{identity.entity.aliases. auth_ldap_abcd1234.name + ‘@company.com’}}”

?

You’re assuming Vault supports arbitrary expressions here - it does not. Only a single dot-separated reference path is supported inside each {{ }} construct.

1 Like