By: Craig Neuwirt user 16 May 2018 at 11:16 a.m. CDT

26 Responses
Craig Neuwirt gravatar
I am trying to have a C# Console Application use Client Credential Flow to access an ASP.NET Core Web Api. I was able to call the Gluu Token Endpoint to obtain the AccessToken, but it is returning it as an UUID and not a JWT. I want the JWT so the API (C# Web Api) will not need to communicate back to Gluu to obtain the claims. Is there a configuration that can achieve this? Do you have an examples on how the use this AccessToken on the API (C# Web Api) side to validate it and obtain the detailed claims that can be used by the application.

By Aliaksandr Samuseu staff 16 May 2018 at 11:25 a.m. CDT

Aliaksandr Samuseu gravatar
Hi, Craig. > I was able to call the Gluu Token Endpoint to obtain the AccessToken, but it is returning it as an UUID and not a JWT. I'm not quite following, sorry. Could you provide an example, and also an example of a value you expect? >Do you have an examples on how the use this AccessToken on the API (C# Web Api) side to validate it and obtain the detailed claims that can be used by the application. If you are not that much familiar with the protocol, I would suggest to use our [oxd server](https://gluu.org/docs/oxd/3.1.3/) RP implementation. It comes with [C# libraries](https://gluu.org/docs/oxd/3.1.3/libraries/languages/csharp/) as well.

By Craig Neuwirt user 16 May 2018 at 12:10 p.m. CDT

Craig Neuwirt gravatar
When I call the Gluu Token Endpoint (https://qaid.sixflags.com/oxauth/restv1/token in my case), I receive a response with the access_token field set to 3662bf9f-4202-4bd7-8b7a-6cda231f9cd7. When interacting with other oauth/openid servers I get an encoded JWT token of the form eyJhbGciOiJSUzI1NiIsImtpZCI6ImI0MjYyMzljMDQxNWU1YTU3MTA5Mjk3NjdlMTFjOWUwIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MjY0OTAzNzUsImV4cCI6MTUyNjQ5Mzk3NSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJhcGkxIl0sImNsaWVudF9pZCI6ImNsaWVudCIsInNjb3BlIjpbImFwaTEiXX0.qeFl89X_PJAA8R0G3nlpZvW-kQiPZbMz_4aCLvcAhUgWsgsrK_NW9rkYJ069I-I2glETsj36NZwDLp1FMgxrji74nQY49p1obqFEbYDz6TQMAAJEpLCYqBGrHJ1OcAQHTjhlbJWeq7pHsNZbEPJZbu6lH57b7PPeCfF2tRFy2DD538rf59YVPXCYkhx4Ji45cjBVibPgA84RfSXjcFxRLOlhZvmd2GxN7L0XT-Fv9W23embtEYrmdhtWyrKZNr2q35D61JhA609tE29M8iLJoLCb3utilwQ3ocWGfiU8I2XZRgboaLeD8Nha-dPQRFKU4aw4RusvAYdecSUWM507pw which decodes to { "alg": "RS256", "kid": "b426239c0415e5a5710929767e11c9e0", "typ": "JWT" } { "nbf": 1526490375, "exp": 1526493975, "iss": "http://localhost:5000", "aud": [ "http://localhost:5000/resources", "api1" ], "client_id": "client", "scope": [ "api1" ] } I there a parameter I am missing to obtain JWT Access Tokens that I can set as bearer authentication header and call my backend API? I will also look at the c# libraries again. I didn't see any that integrated directly with C# Web Api, but I could have missed something

By Aliaksandr Samuseu staff 16 May 2018 at 12:34 p.m. CDT

Aliaksandr Samuseu gravatar
Access token is an opaque string and spec doesn't make it mandatory for it to be a JSON object or have any specific format. Most likely you are referring to `id_token`. The latter still must be returned from token endpoint as well, in addition to access token. Not sure why you are not getting it. For us to understand what's going on, please create and share a HAR file with a capture of the whole failing flow. You can use steps listed [here](https://www.inflectra.com/support/knowledgebase/kb254.aspx) - please use Firefox for that, Chrome's HARs are flawed. Also don't forget to set "Persist log" and "Disable cache" checkboxes in the console to save everything, not just the recently loaded page. I'll also ask you yo also provide dump of the corresponding client's settings: 1. Open the client's properties in Gluu's web UI and copy its "Inum" value 2. Move into Gluu's container 3. Put your LDAP password in `/tmp/.dpw` (it's the same as default admin's password was right after installation) 4. Dump the client's properties: `# /opt/opendj/bin/ldapsearch -h 127.0.0.1 -p 1636 -s sub -T -Z -X -D 'cn=directory manager' -j /tmp/.dpw -b 'o=gluu' -z 3 '&(objectclass=oxauthclient)(inum=YOUR_INUM)'` 5. Share it here. You may decide to remove client's secret from output

By Aliaksandr Samuseu staff 16 May 2018 at 12:36 p.m. CDT

Aliaksandr Samuseu gravatar
Please also provide the actual request you send to token endpoint, and the exact response you get from it.

By Craig Neuwirt user 17 May 2018 at 8:05 a.m. CDT

Craig Neuwirt gravatar
I was looking at the logs exposed by the Gluu Portal and noticed NullPointerExceptions when creating the id_token. Can this be the cause of the missing required id_token in the token response. This is a blocking situation so any advice would be much appreciated. thanks, craig

By Aliaksandr Samuseu staff 17 May 2018 at 11:59 a.m. CDT

Aliaksandr Samuseu gravatar
Hi, Craig. Please provide the requested items so we would be able to understand the situation. One last thing I can suggest before looking at those is for you to double-check your client's registration entry at Gluu. Make sure you provided `redirect_uri` property as well. Even if it's client credentials flow where it's not being used, it must be provided for `id_token` to be issued. You can use some bogus uri if you want.

By Craig Neuwirt user 17 May 2018 at 1:58 p.m. CDT

Craig Neuwirt gravatar
Well, your suggestion to add a redirect_uri did result in an id_token being generated :-) { "kid": "65e6b0bd-1879-4aa3-bf95-d040c7f99c5b", "typ": "JWT", "alg": "RS256" } { "iss": "https://qaid.sixflags.com", "aud": "@!5FEF.D0FA.ECA9.C3DD!0001!8902.F58C!0008!5293.D840.F466.837B", "exp": 1526584271, "iat": 1526580671, "oxOpenIDConnectVersion": "openidconnect-1.0", "sub": "0Nc-ufBSRJKeRaFZn42NQludeoBMtkt115EPtb3PBrA" } I would have expected the "aud" claim to be the resource I am trying to protect and not the id of the sending client. In addition, I would expect a scope claim which would be used by the resource server to perform authentication. In the absence, how is the resource server supposed to know that the calling client has the desired scope to perform the operation? thanks again for your continued help. We are getting close

By Aliaksandr Samuseu staff 17 May 2018 at 5:10 p.m. CDT

Aliaksandr Samuseu gravatar
>I would have expected the "aud" claim to be the resource I am trying to protect and not the id of the sending client It must be client's id, according to [the spec](http://openid.net/specs/openid-connect-core-1_0.html#IDToken). In case of any doubts feel free to consult the document, Gluu tries to follow the specs as close as possible. >I would expect a scope claim which would be used by the resource server to perform authentication. Not sure I got the idea, but if you expect to find user's claims in `id_token`, Gluu doesn't inlcude them there by default. Client should get user claims from [userinfo endpoint](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo). The only claim that identifies the user in it is "sub", and by default its value is an opaque string called [pairwise identifier](http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes). Its type can be changed client-wise; if "public" is set, "uid" attribute will be used as source of "sub" instead, what may be closer to what you are talking about. It's also possible to push claims to `id_token` by enabling its legacy generating mode, but it's not recommended generally.

By Aliaksandr Samuseu staff 17 May 2018 at 5:28 p.m. CDT

Aliaksandr Samuseu gravatar
>In the absence, how is the resource server supposed to know that the calling client has the desired scope to perform the operation? Strictly speaking, "Resource server" here will be Gluu's oxAuth component, as well as Authorization server. Resource server is an entity that consumes access token and allows access to some protected data (user's personal attributes in case of OIDC). A more appropriate term here would be "Relying party", I believe. So the main idea of OIDC is that RP asks for user's permission to acquire a token allowing it out-of-band/back-channel access to their personal data at OIDC OP. RP uses that access token to access userinfo endpoint and request those attributes (with approved scopes serving as filters/constraints). You can say OIDC is very specialized profile of oAuth2.0 tailored for securely share personal data with 3rd parties. Answering your question, the client needs to get user's attributes from userinfo and then run them through authorization rules. As you are using client's credentials flow at the moment, it doesn't make much sense in this context, though, as this won't produce an access token you can access user's data with. If you insist on using a simplified flow like this, it should be resource owner's credentials flow at least (neither of them are described in OIDC core spec, btw, they are more like oAuth2.0 legacy).

By Aliaksandr Samuseu staff 17 May 2018 at 5:34 p.m. CDT

Aliaksandr Samuseu gravatar
For resource owner's creds grant, request will look like this: ``` POST /oxauth/restv1/token HTTP/1.1 Host: idp.host.loc Content-Type: application/x-www-form-urlencoded Authorization: Basic BASE64_ENCODED_CLEINT_CREDS Cache-Control: no-cache Content-Length: 104 grant_type=password&username=admin&password=1q2w3e4r&scope=openid+profile+email+uma_protection+user_name ```

By Craig Neuwirt user 18 May 2018 at 9:58 a.m. CDT

Craig Neuwirt gravatar
Aliaksandr, Thank you very much for this invaluable information. I think the best next step would be a quick phone support call to help shore up any confusions I still have. I have schedule one for Monday @ 9:30a. I hope you can attend since you are the most familiar with my issue. craig

By Aliaksandr Samuseu staff 18 May 2018 at 10:28 a.m. CDT

Aliaksandr Samuseu gravatar
Hi, Craig. I don't mind be there in a call, but I must admit I can't say I understand the issue completely yet. It started with your request on how to use client credentials flow (which is not that often being used at all) to get a specific data item, so I tried to help with just that, assuming you may know your setup better asking for a specific use case. But after you started to mention authorization checks and user's id, i.e. things that don't belong together with that flow, I think it would be better if you would provide a more detailed explanation of your setup and goals. That may save us time during the call as well.

By Craig Neuwirt user 18 May 2018 at 10:35 a.m. CDT

Craig Neuwirt gravatar
Sorry for any confusion. My goal is to simply ensure that a standalone client application (not web app) can access a rest API (web app) with credentials (claims) that protect the resource (api). That is why I am using client credentials grant. The api does not need user information, just scopes (and claims) that identity the calling clients access to the operations. i.e. the Api can only update the database if the calling client has a particular scope (with claims). We have been successful implementing the more complex, user oriented flows (openidconnect) but have struggled with the most simplest of oauth2 flows.

By Craig Neuwirt user 18 May 2018 at 10:43 a.m. CDT

Craig Neuwirt gravatar
I saw the Gluu UMA support but was hoping I didn't need this complexity to authorize a client to access and api. Is this something I need in the client credentials flow?

By Aliaksandr Samuseu staff 18 May 2018 at 10:47 a.m. CDT

Aliaksandr Samuseu gravatar
I see. So, it should look like this: 1. Standalone/native app uses client creds grant to acquire access token and id_token 2. It then makes some call to that API, including one of them (or both) Then I suppose you still need somehow to verify that those items are valid. That's why you need a signed JWT, I suppose? You expect it to contain enough information to make an authorization decision?

By Aliaksandr Samuseu staff 18 May 2018 at 10:50 a.m. CDT

Aliaksandr Samuseu gravatar
>I saw the Gluu UMA support but was hoping I didn't need this complexity to authorize a client to access and api. Is this something I need in the client credentials flow? UMA is very well tuned for protecting APIs, indeed, but for your very niche use case it may indeed be an overkill.

By Craig Neuwirt user 18 May 2018 at 10:52 a.m. CDT

Craig Neuwirt gravatar
Absolutely correct - That is why my initial question was on how to obtain the id_token. Adding openid scope and redirect_uri to client enabled that - However, the id_token didn't include the scope (or claims associated with scope) which makes it not very useful at the resource server. How do I get that information from the token? Introspection endpoint? Basically, I don't know how to get enough information from the token endpoint that I can pass to the resource server (api) and make the access decision. I prefer not to have to call Gluu every time an api call is made to obtain scopes and claims Any ideas? :-)

By Craig Neuwirt user 18 May 2018 at 2:26 p.m. CDT

Craig Neuwirt gravatar
Is there any way to get the requested scopes included in the identity_token?

By Aliaksandr Samuseu staff 18 May 2018 at 2:44 p.m. CDT

Aliaksandr Samuseu gravatar
>Any ideas? :-) The first that comes to mind is to program your API to use `/introspection` endpoint to validate access token it receives from the native app. Request to it would look like this: ``` POST /oxauth/restv1/introspection HTTP/1.1 Authorization: Bearer 104789cb-4a85-403e-823a-f42f24b39ff7 Content-Type: application/x-www-form-urlencoded; charset=utf-8 Host: mytrue.host.loc Connection: close User-Agent: Paw/3.1.5 (Macintosh; OS X/10.12.6) GCDHTTPRequest Content-Length: 71 token=104789cb-4a85-403e-823a-f42f24b39ff7&token_type_hint=access_token ``` Its response contains scopes in it: ``` {"active":true,"scopes":["openid","profile","uma_protection","email"],"client_id":"@!84B1.7441.57C3.98B0!0001!76A2.0919!0008!8BE3.A330.6FFC.6446","username":null,"token_type":"bearer","exp":1526604503,"iat":1526604203,"sub":"","aud":"@!84B1.7441.57C3.98B0!0001!76A2.0919!0008!8BE3.A330.6FFC.6446","iss":"https://mytrue.host.loc","jti":null,"acr_values":null} ``` >Is there any way to get the requested scopes included in the identity_token? Spec doesn't mention a standard claim like this at all, unfortunately. Still, in case of Gluu, there is a way (or sort of a hack) which allows you to push a custom claim with any contents to `id_token`, even for client credentials flow. We did something similar in the past for a customer, the idea is that you write [a dynamic scope script](https://gluu.org/docs/ce/3.1.3/admin-guide/custom-script/#dynamic-scopes) which does it, and then enable a legacy mode of `id_token` generation which includes all possible claims in the JWT. But as it's rather non-standard configuration and involves scripting tasks, it's a bit out of scope of Community Support, I'm afraid. If you'll chose to follow this lead, you'll be mostly on your own, unless you are ready to sign a support contract with Gluu.

By Aliaksandr Samuseu staff 18 May 2018 at 3 p.m. CDT

Aliaksandr Samuseu gravatar
You are also free to open an "Enhancement" issue at [this Github repo](https://github.com/GluuFederation/oxAuth), asking for providing such feature OOTB, explaining how it may make the project better (what are possible use cases and benefits, etc), but no ETA can be guaranteed for such cases (unless it comes from a customer)

By Craig Neuwirt user 18 May 2018 at 3:05 p.m. CDT

Craig Neuwirt gravatar
Thanks Aliaksandr, I did figure out how to get the introspection endpoint working, but that seems to require an access_token and requires a call to the Gluu Server for every api call and we will be having a high frequency of those calls. That's why I was hoping for a way to stash the scopes in the id_token and have it already available on api (resource server). The scripting change definitely sounds out of scope for what I want.

By Craig Neuwirt user 18 May 2018 at 3:10 p.m. CDT

Craig Neuwirt gravatar
Out of curiosity, if I create my scope as OpenId and add claims to it, will they come back from the introspection endpoint?

By Aliaksandr Samuseu staff 18 May 2018 at 3:16 p.m. CDT

Aliaksandr Samuseu gravatar
>Out of curiosity, if I create my scope as OpenId and add claims to it, will they come back from the introspection endpoint? If you'll include your new scope to initial request for access token and then will try to introspect it, endpoint's response should contain that scope in "scopes" property, yes. But list of claims and their values won't be included, as you see. JSON object's composition in the response is also governed by a spec, no properties can be added there.

By Michael Schwartz Account Admin 20 May 2018 at 6:33 a.m. CDT

Michael Schwartz gravatar
A few comments: 1. We do not support JWT access tokens. You only need to introspect once--after introspection you can cache the access token until it expires. IMHO, JWT access tokens only make sense if you're Auth0, and you would get millions of introspection requests, and you want to save money on network and compute. 2. An id_token is only available via the implicit or code flow--i.e. if a person (i.e. the user or subject) authorizes it. It's not possible to get an id_token via the client credential grant. 3. User claims are not available at the introspection endpoint. The OpenID userinfo endpoint interprets scopes, and maps them to available claims. You need to present your access token at the userinfo endpoint to get the userinfo JWT. 4. You are correct that you need an access token to call the introspection endpoint. We wouldn't want allow anonymous introspection of access tokens. You can control who gets client creds--i.e. dynamic client registration is enabled by default, but you can disable it.

By Aliaksandr Samuseu staff 31 May 2018 at 10:18 a.m. CDT

Aliaksandr Samuseu gravatar
Hi, Craig. What other questions do you still have? Can we close the ticket?

By Craig Neuwirt user 31 May 2018 at 12:41 p.m. CDT

Craig Neuwirt gravatar
Yes, we can close this ticket. thanks for responses