OIDC: scoped sub with client_credentials?

Simon Lundström simlu at su.se
Fri Nov 6 10:25:50 UTC 2026


Hey all,

We've been testing the waters with OIDC using both code flow and
client_credentials (for M2M). I've read Scotts stern warning[1] so I
don't wanna let this go before going to prod.

Our strategy is basically go with using subject-id (i.e.
eduPersonPrincipalName) and use the public subject type as the default.

I have setup an OIDC RP using mod_auth_openidc using the
authorization_code flow which gets sub scoped.

How ever when I setup an OAuth2 Resource Server (aka API) and tried to
authenticate a client using the client_credentials grant sub doesn't get
scoped.

I've used the provided examples and pasted in briefs below of what I
think is relevant:

RP with authorization_code grant which works:
      <oidcmd:OAuthRPExtensions
        grant_types="authorization_code"
        response_types="code"
        token_endpoint_auth_method="private_key_jwt"
        scopes="openid profile email"
        >
    <md:NameIDFormat>urn:mace:shibboleth:metadata:oidc:1.0:nameid-format:public</md:NameIDFormat>

Client which will talk to the OAuth2 Resource Server:
      <oidcmd:OAuthRPExtensions
        grant_types="client_credentials"
        response_types="code"
        token_endpoint_auth_method="client_secret_basic"
        scopes="openid profile email"
        >
    <md:NameIDFormat>urn:mace:shibboleth:metadata:oidc:1.0:nameid-format:public</md:NameIDFormat>

oidc-attribute-resolver.xml:
    <AttributeDefinition id="subjectPublic" xsi:type="Scoped" scope="%{idp.scope}"
        activationConditionRef="shibboleth.oidc.Conditions.PublicRequired">
        <InputDataConnector ref="suLDAP" attributeNames="uid"/>
        <AttributeEncoder xsi:type="oidc:OIDCScopedString" name="sub" />
    </AttributeDefinition>

oidc-attribute-filter.xml:
    <AttributeFilterPolicy id="OPENID_SCOPE">
        <PolicyRequirementRule xsi:type="oidc:OIDCScope" value="openid" />
        <AttributeRule attributeID="subjectPublic">
            <PermitValueRule xsi:type="ANY" />
        </AttributeRule>
    </AttributeFilterPolicy>

    <AttributeFilterPolicy id="OAUTH_SUBJECT">
        <PolicyRequirementRule xsi:type="AND">
            <Rule xsi:type="NOT">
                <Rule xsi:type="oidc:OIDCScope" value="openid" />
            </Rule>
        </PolicyRequirementRule>
        <AttributeRule attributeID="subjectPublic">
            <PermitValueRule xsi:type="ANY" />
        </AttributeRule>
    </AttributeFilterPolicy>


Using authorization_code works:
* Login to RP which shows scoped sub and via the access_token I can
  confirm it:
  $ curl -H "Authorization: Bearer $ACCESS_TOKEN" https://op.example.com/idp/profile/oidc/userinfo
{"sub":"simlu at su.se","email_verified":true,"name":"Simon Lundström","preferred_username":"simlu","given_name":"Simon","family_name":"Lundström","email":"simlu at su.se"}

Using client_credentials doesn't:
$ curl -s -u "test-user:$CLIENT_SECRET" -d "grant_type=client_credentials" -d scope=openid 'https://op.example.com/idp/profile/oidc/token' | jq -r .access_token | jwt decode -
[...]
Token claims
------------
[...]
  "scope": "openid",
  "sub": "test-user"
$ ACCESS_TOKEN=$(curl -s -u "test-user:$CLIENT_SECRET" -d "grant_type=client_credentials" -d scope=openid 'https://op.example.com/idp/profile/oidc/token' | jq -r .access_token)
$ curl -s -H "Authorization: Bearer $ACCESS_TOKEN" https://op.example.com/idp/profile/oidc/userinfo
{"sub":"test-user"}
$ curl -s -u "test-user:$CLIENT_SECRET" -d "grant_type=client_credentials" 'https://op.example.com/idp/profile/oidc/token' | jq -r .access_token | jwt decode -
[...]
Token claims
------------
[...]
  "sub": "test-user"

It feels like I'm missing something obvious.

1,
<https://shibboleth.atlassian.net/wiki/spaces/IDPPLUGINS/pages/1376879208/OPSubClaim>

Have a great weekend!

BR,
- Simon
____________________________________

Simon Lundström

IT Services
Stockholm University
SE-106 91 Stockholm, Sweden

www.su.se/it

https://www.su.se/english/about-this-website-1.517563


More information about the users mailing list