Open ssnippets opened 6 years ago
I have some sample code for interfacing with Kong directly (bash script), I can take a stab at updating the adapter, some direction from someone with a bit more experience in the codebase would be helpful (any pointers?).
#Create a consumer for JWTs:
curl -d "username=jwt" -k $PROTO://$KONG_API/consumers
#get the ID for the consumer:
JWT=$(curl -X GET -k $PROTO://$KONG_API/consumers/jwt | jq .id | sed "s/\"//g")
# ACLs, if needed
curl -k -X POST $PROTO://$KONG_API/consumers/jwt/acls \
-d "group=test_group"
#Set up the plug-in for an API.
curl -k -X POST $PROTO://$KONG_API/apis/$API_NAME/plugins \
-d "name=jwt"
#Send up the public and private keys which are stored in jwt/key.pem and jwt/pubkey.pem:
RET=$(curl -k -X POST $PROTO://$KONG_API/consumers/$JWT/jwt \
-d "secret=$(cat jwt/key.pem | sed 's/$/\\n/' | tr -d '\n')" \
--data-urlencode "rsa_public_key=[[
$(cat jwt/pubkey.pem)
]]" \
-d "algorithm=RS256")
#this is the issuer that will be validated via Kong and needs to be a claim when generating JWTs for use in Kong,:
JWT_KEY=$(echo $RET | jq .key)
echo "JWT KEY: $JWT_KEY" # This value needs to be in the 'iss' claim for jwts
#I write it out to a file so I can read it in when generating JWTs. There needs to be a method to retrieve this key:
echo $JWT_KEY |sed 's/["]//g' |tr -d '\n' > jwt/iss.dat
Also, this might help, generation of the key pairs can be done as follows:
openssl genrsa -out key.pem 1024
openssl rsa -in key.pem -pubout > pubkey.pem
Hi @ssnippets - Germany has two public holidays in a row this week (woo!), so I missed out on this a little. It's perfectly possible to just add a plugin
to the API configuration, that's intended use. If you then just add a ${JWT_KEY}
in the configuration of the plugin, the Kickstarter will pick it up and display that env var in the "Environments" section.
There you can then paste your private key and have the Kickstarter encrypt it using the deployment key. Alternatively, you can inject the key as an env var "from the outside" to the portal-api
container; the Portal API will replace it correctly inside the plugin configuration.
I must admit I haven't been using JWTs much, and neither wicked nor Kong as JWT authoring capabilities. It might be a good idea to add that kind of capability to a default implementation of an Auhtorization Server.
Hope your holidays went (or are going?) well. Thanks for the tip. I still think there might be an issue with retrieving the issuer. I'll give your suggesting a whirl and let you know how it goes. Thank you.
Still going on, and fine, thank you :-D
Yes, that's what I meant, you will still need to query Kong to get the issuer when crafting the JWT. This could be made a part of the Kong Adapter, or in the future, of a Kong OAuth2 adapter library, as we are planning to remove the stateless end points from the Kong Adapter in the future (the code is almost done, but there is still quite a way to go until wicked 1.0).
Actually, crafting JWTs could be a part of that library, that sounds like a good idea.
Great. That sounds viable. As a side note, I'm working on a DC/OS deployment and have most of my marathon json files set up. I'll share a sample deployment when I get it up and running, hopefully it can help with your documentation.
And again, thank you.
I've tried a few things but am still not quite there. The plugin config works to set up the plugin but not the consumer. I'm assuming I'm still missing something since key-auth works similar to the jwt plugin:
Everything I put under config seems to be getting sent to the api config $KONG/apis/{api}/plugins
though which returns with an error for unknown values:
{ 'config.secret': 'secret is an unknown field',
'config.rsa_public_key': 'rsa_public_key is an unknown field',
'config.algorithm': 'algorithm is an unknown field' }
What I would like, if it exists, is to be able to send config parameters to the consumer setup $KONG/consumers/{consumer}/jwt
to provide the JWT setup, which should look something like:
{"rsa_public_key": "${JWT_KEY}",
"secret": "${JWT_PRIVATE_KEY}",
"algorithm": "RS256"}
Have I just not found the right way of configuring Wicked or am I in uncharted waters?
Ah, you're right. Kong's JWT implementation requires a consumer to be resolved. I wasn't aware of this from the top of my head, but you're right.
This is not possible OOTB with wicked, let us think about how that could work out. In principle this might be a third way of authenticating a consumer, in addition to key-auth
and oauth2
.
Hum hum hum.
OK good, I'm not just failing miserably 😄 ... thanks for taking a look. I'll take a look from my end and see if I can add that in... I need to get acquainted with the code a bit more though.
I’ll also keep it in mind. You will also need an AuthZ Server of some sorts. And it should be done using OAuth2, albeit not with Kong‘s oauth2 plugin. Let’s keep in touch on this.
I created a PR yesterday as a quick fix for the specific issue I was having with the jwt plugin, but in thinking about it a bit more, that solution is really not all that useful for the general problem of plugins that need consumers to be configured. My thought is that ideally, the general "plugin" spec allows an object to be passed to consumers that are created when using it.
Yes, it's not ideal. It could be a patch for your specific problem, but it's not a generic solution. I'll try to think more about it next week.
So, I think this would be "the real" solution to enabling JWT with wicked:
oauth2+jwt
or similaroauth2
plugin, it crafts JWT tokens itself which it issues as OAuth2 tokensjwt
plugin instead of the oauth2
plugin for these APIsThis would fit nicely into the concept of wicked 1.0 (see the current collection of design documents). The default AS could support both plain OAuth2 with opaque tokens registered with Kong, or JWT tokens; the Kong Adapter would configure the APIs and consumers accordingly and automatically, so there would be no need for a custom plugin configuration.
What is your timeline for this? I don't have an ETA on wicked 1.0 just yet, but would aim to release an alpha or beta in November (no promises, depends on other things, like my current project).
Thoughts?
A couple of things that come to mind:
I wonder though, if this isn't functionality that would be better suited for a Kong plugin instead of at the Wicked level -- perhaps a fork of the oauth2 plugin that allows for JWT generation instead of the tokens.
I like what you've built for the configuration aspect: defining APIs, and managing subscriptions. I think you might get a bit more flexibility out of the system by making the custom plugin configuration a bit more robust, allowing consumers to be configured the same way you pass in parameters to the plugin.
I don't have any sort of urgency on this. The patch that I applied works for what I need it to do for now. I would love to help if I can -- I see a lot of good coming from this project. Let me know if I can be of any assistance.
Good points. The former (payload) is something that has to be solved for the Authorization Server anyway, and my plan was to have a set of defaults which are always added (like name, email, ids and such) and then add a "plugin" which can be "asked" for additional values.
This is needed for deciding on scopes anyway, and it fits quite nicely for the additional claims in the JWTs as well.
The secrets are just configuration, as far as I see it, and can be added without much effort to the existing configuration mechanism.
Not sure about the Kong plugin part, will give that some more thought. The thing with the oauth2
plugin is that it generates opaque tokens, and that they are "registered" with Kong. Which is kind of the thing which is not necessary with JWT. On the other hand, you can't do completely without Kong either, as you need the iss
when crafting the token.
One thing on the iss
field, you can pass that in to the Kong config, so you can set up an issuer for your JWT authoring tool. If you don't pass it in, it gets automatically generated. that field ends up being the key
field that is sent to the consumer.
I would like to know the status of the JWT authentication of the consumers with kong (not kong with the upstream api) handled by Wicked. Is currently JWT an alternative to key-auth and oauth?
Many thanks, Miguel
Currently it's not really supported; I have given this quite some thought, and currently the primary use cases are not needing JWTs, and/or they are not better using JWTs than opaque tokens.
From my point of view, JWTs shine for distributed authorization scenarios where you use a separate authorization server to author JWTs for use with an API which is located somewhere else. This is not the main use case for wicked: Acting as an API Gateway in front of your APIs.
There could be a separate way of authorizing using JWTs, but I currently don't see the real benefit of it in the current architecture. It would make sense as a separate feature of the Authorization Server (much like Auth0 does it), but IMHO not as a default solution for wicked. The drawback of not being able to revoke the token is in my eyes difficult, or the need of adding blacklists for this, is not something I would want to enforce.
But: Please describe your use cases, it's more than possible I am missing something obvious. Thanks for pitching in in the discussion!
A use case would be when an existing client coupled to an API that uses JWT and you want to put Wicked+Kong in the middle without changing the client code. I don't thing its a big change for the client, but you never know.
I share your point of view on JWT having redundant functionality when used with Wicked. I will try to collect more requirements and to adapt clients to key-auth.
Many thanks for the quick response!
Kong requires JWT consumers to be configured with a public key when using RS256. Is there a way to incorporate input of public keys or consumer configuration for a plugin like JWT in the config files so the kong adapter sends them when it's setting up?
In order to generate the JWTs, access to the iss field will also be needed. It would be nice if one consumer could accept JWTs for the entire Kong configuration