Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map Userinfo and id_token claims to HTTP headers #373

Closed
nynymike opened this issue Oct 25, 2019 · 9 comments
Closed

Map Userinfo and id_token claims to HTTP headers #373

nynymike opened this issue Oct 25, 2019 · 9 comments
Assignees
Labels
enhancement HIGH PRIORITY Need to address asap
Milestone

Comments

@nynymike
Copy link
Contributor

nynymike commented Oct 25, 2019

GG admins should be able to map distinct HTTP headers to claims in the id_token and Userinfo JWT. The admin should be able to set the name of the HTTP header. The value of the header should be string if it's single value, and a JSON array if it's multi-value. If no claim is present in the token, omit the header.

This feature is needed to maintain behavior with legacy WAM platforms.

@nynymike nynymike added this to the 4.1 milestone Oct 25, 2019
@nynymike nynymike added the HIGH PRIORITY Need to address asap label Oct 25, 2019
@altexy
Copy link
Contributor

altexy commented Oct 30, 2019

Here is original Mike's wireframe:
https://raw.githubusercontent.com/GluuFederation/gluu-gateway/master/kong-openid-rp/doc/konga-openid-wireframe.png

@nynymike
Should we map EVERY claims in a token (id_token, userinfo) to a distinct header?
Or customer should be able to specify claim(s) of interest?

@nynymike
Copy link
Contributor Author

Yes it would simplest to iterate through the claims. It would also be nice if you could provide a way to do a claims mapping. In the mapping, I think using HTTP_KONG_ ia a mistake. If a legacy application is expecting HTTP_SM_uid if we can provide the same header, the app need not be upgraded. So perhaps we could also provide a tool where additional claims could be added. For example, map the given_name claim to HTTP_SM_givenName (in this case you can leave both headers.

@altexy
Copy link
Contributor

altexy commented Oct 31, 2019

It looks for me too complex. Meg created draft config schema and it looks very big and complicated.


            { id_token_jwt = { required = true, type = "boolean", default = true }, },
            { id_token_jwt_header_name = { required = true, type = "string", default = "http-kong-id-token-jwt" }, },
            { user_info_jwt = { required = true, type = "boolean", default = true }, },
            { user_info_jwt_header_name = { required = true, type = "string", default = "http-kong-userinfo-jwt" }, },
            { user_info_claims = { required = true, type = "boolean", default = true }, },
            { user_info_claims_header_prefix_name = { required = true, type = "string", default = "http-kong-userinfo" }, },
            {
                user_info_claims_custom_headers = {
                    required = false,
                    type = "array",
                    elements = {
                        type = "record",
                        fields = {
                            { userinfo_claim_key = { required = true, type = "string" } },
                            { custom_header_key = { required = true, type = "string" } },
                        },
                    },
                }
            },
            { id_token_claims = { required = true, type = "boolean", default = true }, },
            { id_token_claims_header_prefix_name = { required = true, type = "string", default = "http-kong-id-token" }, },
            {
                custom_static_headers = {
                    required = false,
                    type = "array",
                    elements = {
                        type = "record",
                        fields = {
                            { header_key = { required = true, type = "string" } },
                            { header_value = { required = true, type = "string" } },
                        },
                    },
                }
            }
        }

I would prefer to create some universal solution and don't have hardcoded entry for some particular header/data pairs. Let me some time, I will try to design it.

@altexy
Copy link
Contributor

altexy commented Nov 1, 2019

Proposed schema:

                    {
                        custom_headers = {
                            required = false,
                            type = "array",
                            elements = {
                                type = "record",
                                fields = {
                                    { header_name = { required = true, type = "string" } },
                                    { value = { required = true, type = "string" } },
                                    { format = { required = false, type = "string" } }, -- TODO should be an enum JWT, base64, urlencoded, list
                                    { sep = { required = false, type = "string" }
                                    { iterate = { required = false, type = "boolean"} }
                                },
                            },
                        }
                    }
                },

header_name - self-documented, may contain embedded placeholder when we iterate thru claims, take a look at iterate field below
value - the Lua expression, define the value in the environment, for example userinfo.email
For OpenID Connect use case the environment is populated with 2 root values id_token and user_info.
format - the format used to encode the value. Different types of values have different default formats:

  • object - base64
  • scalar value - urlencoded
  • array of scalars - urlencoded values with separator
    The possible formats:
  • urlencoded
  • base64
  • JWT (with none alg)
  • list with separator

sep - make sense only for list format, default values is ,.
iterate - the value should point to an object, for example id_token
We will iterate thru keys/values and create separate header for every key. The captured key is accessible in header_name via special placeholder, for example {*}.

Below is example JSON:

{
  "custom_headers" : [
    { "header_name" : "HTTP_SM_givenName ", "value" : "userinfo.given_name" },
    { "header_name" : "KONG_IDTOKEN_JWT", "value" : "id_token", "format" : "JWT" },
    { "header_name" : "KONG_CUSTON_ARRAY_CLAIM", "value" : "userinfo.array", "format" : "list", "sep" : "; " },
    { "header_name" : "KONG_OPENIDC_USERINFO_{*}", "value" : "userinfo", "iterate" : true }
  ]
}

Current implementation is hardcoded to set 2 headers:

    local new_headers = {
        ["X-OpenId-Connect-idtoken"] = encode_base64(cjson.encode(id_token)),
        ["X-OpenId-Connect-userinfo"] = encode_base64(cjson.encode(session_data.userinfo))
    }

We may provide some defaults in UI for things like above, but an admin will be able to fully customize headers set.

IMO we may use this microframework not only for OpenID Connect plugin, but everywhere we need to set any headers, of course the environment would be different.

@ldeveloperl1985
Copy link
Contributor

ldeveloperl1985 commented Nov 1, 2019

Ok, so admin should have to use userinfo and id_token placeholder keywords during configurations for populating the values, right?

@altexy
Copy link
Contributor

altexy commented Nov 1, 2019

Ok, so admin should have to use userinfo and id_token during configurations for populating the values, right?

No, we will document, which values are set in the environment.
As I wrote, for gluu-openid-connect plugin the environment will consist of 2 root objects id_token and userinfo.
Our plugin will use the config and the environment to form the headers.

@ldeveloperl1985
Copy link
Contributor

ldeveloperl1985 commented Nov 13, 2019

We may send access_token obtained from OP to upstream service in a header, for example, mod_auth_openidc is able to do it.
@nynymike , what is your opinion about this topic? May it be useful for any app protected by gluu-openid-connect plugin?

@nynymike
Copy link
Contributor Author

It would be nice if we can send the access token, but it should be off by default.

@ldeveloperl1985
Copy link
Contributor

Ok, Created another issue for it #382

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement HIGH PRIORITY Need to address asap
Projects
None yet
Development

No branches or pull requests

3 participants