Kong and JWT without creating consumers - jwt

I am currently playing around with the Kong API Gateway and I would like to use it to validate the authentication of users at the gateway and restrict access to services if the user is not logged in properly.
I have an authentication service which issues JWTs whenever a user logs in.
I would now like to share the JWT secret with Kong and use it for validation of the issued JWTs to secure services which need proper authentication.
I had a look at this plugin: https://getkong.org/plugins/jwt/
But it seems that this plugin works a bit different than what I would like to achieve. Why do I have to create consumers? I would like to have only one user database at my authentication service to avoid the need of synchronisation. It seems that the approach of this plugin is designed for giving 3rd party stakeholders access to my API.
Any hint would be highly appreciated.

The answer given by Riley is sort of correct in implementation but that is not the intended use of a consumer in the Kong.
A consumer in kong is the application that is is using the API. So, unless you have multiple vendors using your app/web service, I suggest you create a single consumer.
You can create multiple key and secret pair(JWT credentials) for that consumer. Create a JWT for a user by using the users Key and secret. Store this Key and secret in your current database along with your userID and other details. Create your JWT using these and return the JWT to the user.
Anything else you want to append as a claim can be added to the JWT while you are creating it. You can create a check for these claims in Kong. So, when you get a call to any of your APIs along with these JWT Kong will check the validity of the JWT(along with all the claims) and only then allow the access to the API.

It seems to me that the design of the JWT plugin for Kong doesn't want to share a JWT secret with you - it wants to own the JWTs entirely. You will indeed have to create a consumer per user, and let Kong manage that.
I asked a few questions to confirm on the Google Group - see https://groups.google.com/forum/?fromgroups#!topic/konglayer/XHnVEGoxZqo
Two highlights:
Can you just confirm that it should be OK to make one consumer and one credential per user?
Not only that's okay, but that's the recommended way :)
and
Will Kong be happy to have two million consumers of a single api? What about 200 million?
Technically that shouldn't be an issue, I would recommend setting up a POC where you can experiment with a higher number of users, in order to optimize the connection between Kong and the datastore and make sure we tune everything properly.

You can actually pass the secret to the JWT plugin when you create it:
$ curl -X POST http://kong:8001/consumers/${consumer_id}/jwt \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "secret=mysecret&consumer_id=${consumer_id}"

Related

Keycloak token exchange across realms

We use Keycloak 12.02 for this test.
The idea is that we have a lot of customers, that we all have in their own realms. We want to be able to impersonate a user in any non-master realm for an admin/support user in the master realm.
The flow would be to:
login using a super-user/password to login into the master realm
get a list of all available realms and their users
craft a request to exchange the current access token with a new access token for that specific user.
It is the last step I cannot get to work.
Example:
Login to master realm
token=$(curl -s -d 'client_id=security-admin-console'
-d 'username=my-super-user' -d 'password=my-super-pass' \
-d 'grant_type=password' \
'https://login.example.net/auth/realms/master/protocol/openid-connect/token' | jq -r .access_token)
(we now have an access token for the super-user in the master realm)
The Keycloak server has enabled token exchange (-Dkeycloak.profile.feature.token_exchange=enabled) as described here https://www.keycloak.org/docs/latest/securing_apps/#_token-exchange.
Attempt to impersonate a user in another realm (not master):
curl -s -X POST "https://login.example.net/auth/realms/some_realm/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d 'client_id=some_client' \
-d "requested_subject=some_user" \
-d "subject_token=$token"
However, this does not work. The result is: {"error":"invalid_token","error_description":"Invalid token"}
(Doing this inside a single realm work)
What am I doing wrong here? This seems like a very normal feature to utilize in a real-life deployment, so any help is much appreciated!
UPDATE:
First of all, I found the very same use-case here: https://lists.jboss.org/pipermail/keycloak-user/2019-March/017483.html
Further, I can get it to work by working through some major hoops. As described above, one can use the broker client in the master realm as an identity provider:
Login as super-user adminA -> TokenA
use TokenA to get a new external token, TokenExt from the master identity provider.
Use TokenExt to do a token exchange for the user you want to impersonate
The caveat with the above is that the user adminA is created in each of the realms you log into with this method, so still not ideal.
as far as I know what you are describing is not possible. I'm wondering where you are, more than a year afterwards... did you solve your issue?
Before going further, note that I have found Keycloak discourse a good forum for Keycloak questions: https://keycloak.discourse.group/
Second, this is what I understand: for Keycloak, 2 realms or 2 different Keycloaks is the same. There is nothing common, they are 2 completely different id providers. So any reasoning that supposes shared trust or shared users between realms will not work.
For logging in to the other realm, you need a token that is trusted. There is no reason for the other realm to trust the master realm. The way to set that trust is to set up the master realm client as an identity provider to the other realm (I understand that this is what you do not want to do), so that tokens signed by the master realm will be trusted by the other realm.
And once you have that set up, I have not seen any other way of exchanging than having the token exchange create a federated "admin" user in the other realm (I configure it to be created each time from scratch, to avoid any synch). Also, 2 mappings are going to come in to play, the ID provider mapping, and the client mapping, for creating the resulting JWT.
If this doesn't match with your findings, please correct me.
Ah yes: there is also the question of using token exchange as defined in OAuth, with the may_act claim, which would be perfect here. But it would come after the exchange between realms, in addition. See https://datatracker.ietf.org/doc/html/rfc8693#section-4.4
EDIT: to "create the user each time from scratch"
go to "identity providers" / / "settings"
select "sync mode" to "force"
This is the relevant extrant from the tooltip:
The sync mode determines when user data will be synced using the
mappers. Possible values are: 'legacy' to keep the behaviour before
this option was introduced, 'import' to only import the user once
during first login of the user with this identity provider, 'force' to
always update the user during every login with this identity
provider.
so when you choose "force", basically the user will be overwritten at each login.
Ok so it's not really a creation, but as close as you can get :-)
The idea here is to not care about it, which is fine for prototyping. But I guess that in production you may want to optimize this.

Kong + JWT Excluding endpoints from authorization

I am using Kong and the JWT plugin to authenticate my upstream services. I have a use case where i would like to expose an endpoint in one of the services without having Kong authenticate against it. I was wondering if there is any way to specify exclusion patterns to let Kong know to ignore authentication for this endpoint?
Thanks in advance for any help!
Kong looks at the configured APIs in order of length. So it should be possible (without have tested it) that you use a longer uri (the one you want to make publicly accessible) without the JWT plugin, while keeping your current endpoint with the JWT plugin.
For example, if your current configuration is on /myApi and the path you want to make public is /myApi/login, then add an API on the latter without configuring the JWT on it.

how to get client_id and client_secret code in cloud foundry using api's

In cloud foundry how can I get the client_id and client_secret code.
This will be used in Basic authentication instead of passing the user and password for respective api calls
In general, this is something that you would get from your platform administrator. He or she would be able to provide you with a properly configured client id and client secret to fit your needs. If you are not the administrator, then you won't be able to do this.
If you are an administrator, read on. There are many existing client and secret pairs within a Cloud Foundry platform. It's also possible, and suggested, to create custom client and secret pairs for use with non-platform apps. You shouldn't use a platform client for your custom app, you should use your own custom client, that way if the client is compromised you can delete it or change the secret.
All of this, viewing & managing client data, is done through UAA, so I'd recommend starting with the docs on UAA. Make sure that you understand the concepts. You may even want to take a step further back and review concepts of OAuth2 as well. Understanding OAuth2 will make working with UAA much easier.
https://docs.cloudfoundry.org/uaa/uaa-overview.html
After that, you'll need the uaac (i.e. UAA client) installed.
https://github.com/cloudfoundry/cf-uaac
Once you're familiar with UAA & have the client installed, this doc on how to manage clients should provide you with instructions to view or create a new client.
https://github.com/cloudfoundry/uaa/blob/master/docs/Sysadmin-Guide.rst#manage-client-registrations
You will need admin role to be able to create a client or get its details.
Refer https://docs.cloudfoundry.org/api/uaa/version/4.7.1/index.html#clients to see various api to manage and create clients.
You can also use the uaa client to get the client details.
Refer https://docs.cloudfoundry.org/uaa/uaa-user-management.html for more info.

JWT and KONG with custom authrizations

I went through this tutorial on KONG
https://getkong.org/plugins/jwt/
I have an understanding of JWT and authorization concepts. I have prototyped JWT with Spring Boot where I could put my own key value like this {"authorizations":"role_admin, role_user"}.
It is easy to do that in Spring Boot but I am not able to find information on how to do this with KONG. Anyone has any info about it?
Kong community edition can handle only the authentication process, (give or deny access to a customer).
Authorization process (what a given customer can do in your application) is handled by your application or by https://getkong.org/plugins/ee-oauth2-introspection/ oauth2 introspection plugin which is enterprise edition only
you can write your own authorization server based on X-Consumer-Username request header if user passed authentication or original token header proxied by kong
hope helps
The kong jwt plugin does not support sending custom payload parameters to the upstream api. It does however seem like you can use this plugin (I have not tested it):
https://github.com/wshirey/kong-plugin-jwt-claims-headers
Update:
If you set Kong to forward all headers you'll get the raw Authorization header with the jwt token. So you could base64 decode the jwt token and pull out the claims/payload parameters you need manually in your service.

SSO with keycloak

We are considering to use the keycloak as our SSO framework.
According to the keycloak documentation for multi-tenancy support the application server should hold all the keycloak.json authentication files, the way to acquire those files is from the keycloak admin, is there a way to get them dynamically via API ? or at least to get the realm public key ? we would like to avoid to manually add this file for each realm to the application server (to avoid downtime, etc).
Another multi-tenancy related question - according to the documentation the same clients should be created for each realm, so if I have 100 realms and 10 clients, I should define the same 10 clients 100 times ? is there an alternative ?
One of our flows is backend micro-service that should be authenticated against an application (defined as keycloak client), we would like to avoid keeping user/psw on the server for security reasons, is there a way that an admin can acquire a token and place it manually on the server file system for that micro service ? is there a option to generate this token in the keycloak UI ?
Thanks in advance.
All Keycloak functionality is available via the admin REST API, so you can automate this. The realm's public key is available via http://localhost:8080/auth/realms/{realm}/
A realm for each tenant will give a tenant-specific login page. Therefore this is the way to go - 10 clients registered 100 times. See more in the chapter Client Registration of the Keycloak documentation. If you don't need specific themes, you can opt to put everything in one realm, but you will lose a lot of flexibility on that path.
If your backend micro service should appear like one (technical) user, you can issue an offline token that doesn't expire. This is the online documentation for offline tokens. Currently there is no admin functionality to retrieve an offline token for a user by an admin. You'll need to build this yourself. An admin can later revoke offline tokens using the given admin API.