By: Eckhard Lehmann user 26 Apr 2019 at 9:42 a.m. CDT

11 Responses
Eckhard Lehmann gravatar
Hello, I know that managing claims for users is easy by setting them into scopes (via attributes). They can be retrieved from the userInfo endpoint. We are successfully doing that. Now we want to have separate OIDC Clients with the grant_type *client_credentials* and the purpose to enable server applications to login to our system and access particular (REST) resources. Each server application should be configured with its own clientId and clientSecret, and they use it with basic auth at the token endpoint to retrieve an access token. So far so good, that works as expected. But how can we specify which resources they are able to access? For users we can manage and retrieve claims, e.g. group memberships, and associate permissions that way. For clients I haven't found a way to do the same. Looking at the LDAP object for a client, I see an empty field *associatedPerson* and it sounds like that could enable us to assign a client to a user, which in turn could enable to have groups, roles etc. for a client by having them for the associated user. But apparently there is no way to fill this field via the register API or in oxTrust, so I wasn't able to try it out and its pure speculation. So, is there any way to do it? A workaround would be to have users instead of clients, and configure the server applications so that they login with the *passwort* grant_type. But we would prefer the *client_credentials* flow as this seems to be the more official way to do such things. Thanks in advance.

By Aliaksandr Samuseu staff 06 May 2019 at 1:37 p.m. CDT

Aliaksandr Samuseu gravatar
Hi, Eckhard. The client and user credentials grants flows are special cases in Gluu Server, as they are technically not OIDC flows (OIDC spec doesn't define such flows). They are sort of legacy from oAuth2.0 we decide to implement for special niche tasks. I'm not sure I fully understand your use-case, may be you could expand on this part, providing detailed step-by-step of the flow and/or diagram of it: >But how can we specify which resources they are able to access? For users we can manage and retrieve claims, e.g. group memberships, and associate permissions that way. For clients I haven't found a way to do the same If you need some way to know what scopes were allowed for a certain client, you may try to query the introspection endpoint, for one. Here is example of such query: ``` POST /oxauth/restv1/introspection HTTP/1.1 Authorization: Bearer 6ed2a554-baa5-4868-b02b-05a33c90c634 Content-Type: application/x-www-form-urlencoded; charset=utf-8 Host: host.example.com Connection: close User-Agent: Paw/3.1.5 (Macintosh; OS X/10.12.6) GCDHTTPRequest Content-Length: 71 token=6ed2a554-baa5-4868-b02b-05a33c90c634&token_type_hint=access_token ``` The `token` is access token you get from `/token` endpoint for this client initially. You use it in `Authorization: Bearer` as well in this request. The response will look like this: ``` {"active":true,"scopes":["openid","email"],"client_id":"@!38F1.D485.87AD.048A!0001!E6C9.DA08!0008!AD2D.0336.3C79.6955","username":null,"token_type":"bearer","exp":1557167846,"iat":1557167546,"sub":"","aud":"@!38F1.D485.87AD.048A!0001!E6C9.DA08!0008!AD2D.0336.3C79.6955","iss":"https:\/\/host.example.com","jti":null,"acr_values":null,"scope":["openid","email"],"key_from_script":"value_from_script"} ``` So it will contain the list of scopes OP allowed this client to have access to. Hope this helps. You assumption about interconnection between client and user was a miss, though. There is no way (at least supported and intended) to tie both together. Overall, such in-depth modifications involving changing attributes on entries directly in LDAP are not usually covered by Community Support and we can't hold responsibility for any disaster that may come from it. Please refrain from it unless there is no other way.

By Eckhard Lehmann user 07 May 2019 at 2:53 a.m. CDT

Eckhard Lehmann gravatar
Hi Aliaksandr, > The client and user credentials grants flows are special cases in Gluu Server, as they are technically not OIDC flows Ok I see... > I'm not sure I fully understand your use-case, may be you could expand on this part Basically I would like to threat an OIDC client like a user and get authentication information for it as for a user. For example, I would like to make the client member of particular groups in oxtrust, then create a "group-membership" scope in the scopes section in oxtrust and then, when a client presents a token, have its group membership reflected at the userinfo, resp. the clientinfo endpoint. But yes I remember from what I've read, the client authentication flow is Oauth2 rather than OIDC, so what I am looking for is not the standard way of doing things. Meanwhile we decided to have system users with authentication information and to use the password flow with these system users. It would be helpful though, to have a 1:1 mapping of an OIDC client to a system user and be able to restrict the OIDC client such that only this one user can log in via one OIDC client. Is it possible in general to specify which users are able to log in via particular OIDC clients?

By Michael Schwartz Account Admin 08 May 2019 at 6:59 a.m. CDT

Michael Schwartz gravatar
To convey group membership info, you can use the `memberOf` ldap attribute. I believe you can use a dynamic attribute in OpenDJ to keep this in sync automatically. The Resource Owner Password (ROPW) Credential grant is the anti-pattern. The whole point of federated identity is to make sure the RP does not see the user's password. If you are not using passwords (for example using the flow to trigger an OOB notification, ROPW can be interesting, and that's why we created an interception script for it. ``` a 1:1 mapping of an OIDC client to a system user and be able to restrict the OIDC client such that only this one user can log in via one OIDC client. ``` It's possible if you use an interception script. But in general, I think this is not a very scalable solution. Why even bother with client creds if you are validating user credentials?

By Eckhard Lehmann user 08 May 2019 at 8 a.m. CDT

Eckhard Lehmann gravatar
> To convey group membership info, you can use the memberOf ldap attribute. I believe you can use a dynamic attribute in OpenDJ to keep this in sync automatically. Yes, I've done that already for users. The purpose of dynamic attributes is still somewhat obscure to me, as is the creation of interception scripts, but hopefully I am getting there sooner ot later. > It's possible if you use an interception script. But in general, I think this is not a very scalable solution. Why even bother with client creds if you are validating user credentials? We have two scenarios: Normal user login (which we do via the authentication code flow and spring security) and "service login", where services login to our API with a predefined/configured set of credentials. For the latter we'd prefer the client_credentials flow (or anything that suits better than the ROPW antipattern), but apparently it is not possible to get claims with authentication information for that one, as we get for users in the id_token or /userinfo endpoint. So we are basically forced to use the ROPW antipattern in order to get additional claims for a service login, unless there is another way (maybe with interception scripts). Still we want to separate the services logins from the "normal" user login and the intention is to use one OIDC client for the normal users and additional OIDC clients for every service login. Ideally it must not be possible to login with a service user (the ROPW antipattern user) at the "normal user OIDC client" and vice versa. BTW, this is an additional requirement we will have later: enable the login for particular sets of users only at particular OIDC clients.

By Michael Schwartz Account Admin 08 May 2019 at 8:06 a.m. CDT

Michael Schwartz gravatar
Dynamic claims script might be a good way to tranform the DN of the group to a more meaningful string. Be careful of performance though. ``` but apparently it is not possible [for client credential grant] to get user claims ``` If the client is a mobile or web application, acting on behalf of a person, shouldn't the client should already have an `id_token`? Why can't the client push the `id_token` to the API?

By Eckhard Lehmann user 08 May 2019 at 12:15 p.m. CDT

Eckhard Lehmann gravatar
> If the client is a mobile or web application, acting on behalf of a person, shouldn't the client should already have an id_token? Why can't the client push the id_token to the API? The client is a server, most of the time. We try to achieve "external server"->"our API" authentication... and the server should be threated more or less as a user who has permissions according to what we have provided it with. For the client_credentials flow that would mean, the OIDC client *is* essentially the user we try to authenticate and we want to use Gluu to manage its permissions in the same way as we do for ordinary users.

By Aliaksandr Samuseu staff 14 May 2019 at 3:45 p.m. CDT

Aliaksandr Samuseu gravatar
Hi, Eckhard. What other questions do you still have? Do you think this ticket can be closed now?

By Eckhard Lehmann user 15 May 2019 at 10:01 a.m. CDT

Eckhard Lehmann gravatar
Hi Aliaksandr, I think the ticket can be closed, thanks. Best Regards

By Sean Kelly user 25 Aug 2020 at 5:03 a.m. CDT

Sean Kelly gravatar
I'm trying to exactly this. Did you have any luck? It seems like it should be so simple.

By Michael Schwartz Account Admin 25 Aug 2020 at 9:19 a.m. CDT

Michael Schwartz gravatar
"Clients" are software. If you are using the client credential grant, this is an OAuth flow, not an OpenID Connect flow. This makes sense because OpenID Connect is a "[is a simple identity layer](https://openid.net/connect/)"--see the first sentence. Thus no person... no "identity". However, a client can have client claims. Think of an ldap--each client has an ldap entry. That entry has attributes. If you are using client credentail grant, you can share information about the client If a client is acting on behalf of a person, there must be some kind of contextual link. For example, if a client obtains an access token as part of the OpenID Connect code flow, it will be associated with a person. At this point, I am closing this ticket. It is all over the place. If you have further questions, please open a new issue. I cannot follow the thread here. I also suggest you [read my book](https://gluu.co/book).

By Eckhard Lehmann user 25 Aug 2020 at 2:39 p.m. CDT

Eckhard Lehmann gravatar
Hello Sean, > I'm trying to exactly this. Did you have any luck? It seems like it should be so simple. We ended up storing the necessary context in our database. And implemented a way to extract the information from the token, whether it is from a real "in-person" user or from a client (in spring-security you can provide an AuthenticationConverter Bean for that). Then we can act accordingly. It turned out that fine granular user permissions do require a user login anyway and thus do always have an "in-person" token. For client logins, which we only use to access a service by another service, we only need abstract permissions and we use scopes for that. Best Regards