JWT Authentication Issue

Elasticsearch Version: 5.5.0

Searchguard Version: 5.5.0-16

Kibana Version: 5.5.0

Installed modules: JWT, repository-s3, ec2-discovery

JVM: OpenJDK 1.8.0

We are running in AWS cloud and using AWS Cognito to produce JWT tokens for us. We have a custom JWT attribute “custom:kibana_role” that we use to specify the SG role, in all cases this is “sg_all_access”.

sg_roles_mapping.yml:

sg_all_access:

users:

  • admin

  • lambdaingester

backendroles:

  • ‘sg_all_access’

sg_config.yml (in which JWT_PLACEHOLDER) gets replaced with our RSA256 certificate:

jwt_auth_domain:

enabled: true

order: 0

http_authenticator:

type: jwt

challenge: false

config:

signing_key: |-

JWT_PLACEHOLDER

jwt_header: “jwtheader”

jwt_url_parameter: null

roles_key: “custom:kibana_role”

subject_key: “cognito:username”

authentication_backend:

type: noop

The issue we are seeing in the Elasticsearch log is:

[2017-12-07T09:30:21,072][WARN ][c.f.d.a.h.j.HTTPJwtAuthenticator] Failed to get roles from JWT claims with roles_key ‘custom:kibana_role’. Check if this key is correct and available in the JWT payload.

[2017-12-07T09:30:21,073][INFO ][c.f.s.c.PrivilegesEvaluator] No index-level perm match for User [name=test2, roles=] [IndexType [index=searchguard, type=], IndexType [index=.kibana, type=], IndexType [index=stix, type=*]] [Action [indices:admin/get]] [RolesChecked [sg_own_index, sg_public]]

[2017-12-07T09:30:21,073][INFO ][c.f.s.c.PrivilegesEvaluator] No permissions for {sg_public=[IndexType [index=stix, type=], IndexType [index=searchguard, type=], IndexType [index=.kibana, type=]], sg_own_index=[IndexType [index=stix, type=], IndexType [index=searchguard, type=], IndexType [index=.kibana, type=]]}

We are calling Elasticsearch with the header:

authorization: Bearer eyJraWQiOiI0NDdzTkFcL1BjMGtEdUNxQmRERklNSHUraml1c3VZa3dtMktmR1gxdkpMVT0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI0OGEzNWNhOC03ZTYzLTQ5NjQtOWFhZi0zNDU2Yzc4YmQ2MWQiLCJhdWQiOiJrbDQxcWVnMzBnNTNrMXFwZTU3MWdkYXNsIiwiZXZlbnRfaWQiOiIzOTRjYTJlOC1kYjM2LTExZTctODAxMS00OTFmYTdhOWFjNTIiLCJ0b2tlbl91c2UiOiJpZCIsImF1dGhfdGltZSI6MTUxMjY0MTE2MiwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLmV1LXdlc3QtMi5hbWF6b25hd3MuY29tXC9ldS13ZXN0LTJfVlRCeW1FTG00IiwiY29nbml0bzp1c2VybmFtZSI6InRlc3QyIiwiZXhwIjoxNTEyNjQ0NzYyLCJjdXN0b206a2liYW5hX3JvbGUiOiJzZ19hbGxfYWNjZXNzIiwiaWF0IjoxNTEyNjQxMTYyfQ.b8yMiokuH52ra6iWzCYWuaHXKRpAKxnC6eDHFCKvcK9JBG2dnBSTYB7ewuDGLKB1JE7CG8-Pu4BHfij04mdFKb1j45T9T76spOwG1HdcwnBsa_w6vG9EeU2XjVerGVq32s1UEoayXWUSSKRZPx4QnMAOdgqOP6Y7MV0pjMW-ILMXfQnq3cv3do9eY7vT-R6nYqgjYdfqCBkBihMZg3zCrgRFAMfjq_UerNXZY8wdkvINjdphwJix-REzxU_v5aFJD0l7GlpkO58EtUoskfO8NnhP2Ll9CL1pVFcP7m4v9BeSc_-lK21UYJ5uZw4iIOwx_QVnWbvZlKodOCMJ8-z4Hw

The above JWT is a valid one that we’ve used. Decoding it in www.jwt.io shows the custom attribute as expected.

When logging into our application for the first time we set the attribute in AWS Cognito which sets it in our JWT for us. When the user attempts to use Elastic or Kibana they recieve the error above. Now here is the weird thing. After 1 hour (the AWS Cognito JWT refresh expiry) it seems to then start working.

Do you know what might be causing this? I’m not sure if it’s strictly a SG issue. Given that using www.jwt.io to decode the JWT and seeing that the attribute is there suggests that SG should be happy with it?

Any help would be great. Happy to post any further configuration.

While this is probably not a solution for the root cause, I can at least explain parts of the behavior.

  • Let’s say you start your nodes fresh. All internal Search Guard caches, including the user cache, are empty.
  • Now you send the first request with the JWT token. For one reason or another the custom:kibana_role field can’t be parsed
  • can you please post the JSON content of your token?
  • This is also what the SG error says: Failed to get roles from JWT claims with roles_key ‘custom:kibana_role’.
  • This user object with the missing roles is then stored in the SG user cache.
  • The default TTL is 1 hour.
  • After the cache entry expired, you send another request
  • This time the role field can be parsed, and everything works

Since JWT is self-contained, you can and should actually disable the SG User Cache completely by setting the TTL to 0:

This means the JWT is parsed fresh everytime and you don’t see the “1 hour delay effecty” anymore.

But the question remains - why could the role claim from the token in the initial request not be parsed? If it works for one request but not for another request, I would say that there must be two different tokens involved?

···

On Thursday, December 7, 2017 at 11:28:19 AM UTC+1, Richard Caunt wrote:

Elasticsearch Version: 5.5.0

Searchguard Version: 5.5.0-16

Kibana Version: 5.5.0

Installed modules: JWT, repository-s3, ec2-discovery

JVM: OpenJDK 1.8.0

We are running in AWS cloud and using AWS Cognito to produce JWT tokens for us. We have a custom JWT attribute “custom:kibana_role” that we use to specify the SG role, in all cases this is “sg_all_access”.

sg_roles_mapping.yml:

sg_all_access:

users:

  • admin
  • lambdaingester

backendroles:

  • ‘sg_all_access’

sg_config.yml (in which JWT_PLACEHOLDER) gets replaced with our RSA256 certificate:

jwt_auth_domain:

enabled: true

order: 0

http_authenticator:

type: jwt

challenge: false

config:

signing_key: |-

JWT_PLACEHOLDER

jwt_header: “jwtheader”

jwt_url_parameter: null

roles_key: “custom:kibana_role”

subject_key: “cognito:username”

authentication_backend:

type: noop

The issue we are seeing in the Elasticsearch log is:

[2017-12-07T09:30:21,072][WARN ][c.f.d.a.h.j.HTTPJwtAuthenticator] Failed to get roles from JWT claims with roles_key ‘custom:kibana_role’. Check if this key is correct and available in the JWT payload.

[2017-12-07T09:30:21,073][INFO ][c.f.s.c.PrivilegesEvaluator] No index-level perm match for User [name=test2, roles=] [IndexType [index=searchguard, type=], IndexType [index=.kibana, type=], IndexType [index=stix, type=*]] [Action [indices:admin/get]] [RolesChecked [sg_own_index, sg_public]]

[2017-12-07T09:30:21,073][INFO ][c.f.s.c.PrivilegesEvaluator] No permissions for {sg_public=[IndexType [index=stix, type=], IndexType [index=searchguard, type=], IndexType [index=.kibana, type=]], sg_own_index=[IndexType [index=stix, type=], IndexType [index=searchguard, type=], IndexType [index=.kibana, type=]]}

We are calling Elasticsearch with the header:

authorization: Bearer eyJraWQiOiI0NDdzTkFcL1BjMGtEdUNxQmRERklNSHUraml1c3VZa3dtMktmR1gxdkpMVT0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI0OGEzNWNhOC03ZTYzLTQ5NjQtOWFhZi0zNDU2Yzc4YmQ2MWQiLCJhdWQiOiJrbDQxcWVnMzBnNTNrMXFwZTU3MWdkYXNsIiwiZXZlbnRfaWQiOiIzOTRjYTJlOC1kYjM2LTExZTctODAxMS00OTFmYTdhOWFjNTIiLCJ0b2tlbl91c2UiOiJpZCIsImF1dGhfdGltZSI6MTUxMjY0MTE2MiwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLmV1LXdlc3QtMi5hbWF6b25hd3MuY29tXC9ldS13ZXN0LTJfVlRCeW1FTG00IiwiY29nbml0bzp1c2VybmFtZSI6InRlc3QyIiwiZXhwIjoxNTEyNjQ0NzYyLCJjdXN0b206a2liYW5hX3JvbGUiOiJzZ19hbGxfYWNjZXNzIiwiaWF0IjoxNTEyNjQxMTYyfQ.b8yMiokuH52ra6iWzCYWuaHXKRpAKxnC6eDHFCKvcK9JBG2dnBSTYB7ewuDGLKB1JE7CG8-Pu4BHfij04mdFKb1j45T9T76spOwG1HdcwnBsa_w6vG9EeU2XjVerGVq32s1UEoayXWUSSKRZPx4QnMAOdgqOP6Y7MV0pjMW-ILMXfQnq3cv3do9eY7vT-R6nYqgjYdfqCBkBihMZg3zCrgRFAMfjq_UerNXZY8wdkvINjdphwJix-REzxU_v5aFJD0l7GlpkO58EtUoskfO8NnhP2Ll9CL1pVFcP7m4v9BeSc_-lK21UYJ5uZw4iIOwx_QVnWbvZlKodOCMJ8-z4Hw

The above JWT is a valid one that we’ve used. Decoding it in www.jwt.io shows the custom attribute as expected.

When logging into our application for the first time we set the attribute in AWS Cognito which sets it in our JWT for us. When the user attempts to use Elastic or Kibana they recieve the error above. Now here is the weird thing. After 1 hour (the AWS Cognito JWT refresh expiry) it seems to then start working.

Do you know what might be causing this? I’m not sure if it’s strictly a SG issue. Given that using www.jwt.io to decode the JWT and seeing that the attribute is there suggests that SG should be happy with it?

Any help would be great. Happy to post any further configuration.

Many thanks for the reply. I think you’ve nailed the issue there. We discovered an issue with our login process this morning that meant the original JWT was missing the attribute but subsequent ones were OK, we think… I’ll try a cache of 0 too and let you know what happens.