Unable to get JWT to work

I have exciting news! (Well exciting to me at least).

I now see some JWT error messages:

[2022-05-24T17:38:34,985][ERROR][c.a.d.a.h.j.HTTPJwtAuthenticator] [opensearch-node1] Cannot authenticate user with JWT because of
io.jsonwebtoken.security.WeakKeyException: The verification key's size is 64 bits which is not secure enough for the HS256 algorithm.  The JWT JWA Specification (RFC \7518, Section 3.2) states that keys used with HS256 MUST have a size >= 256 bits (the key size must be greater than or equal to the hash output size).  Consider using\ the io.jsonwebtoken.security.Keys class's 'secretKeyFor(SignatureAlgorithm.HS256)' method to create a key guaranteed to be secure enough for HS256.  See https://tool\s.ietf.org/html/rfc7518#section-3.2 for more information.

I will try to fix that and report back.

@iamthealex-es Your secret is too short. You need 32 character long secret. See my example.

After bumping up the size of my key, I no longer see message about the key being too small.
And, I no longer see complaints about missing basic authentication either.

But I am still failing to authenticate using JWT to try to get the cluster health

[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1] AUDIT_LOG: {
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_cluster_name" : "opensearch-cluster",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_node_name" : "opensearch-node1",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_rest_request_method" : "GET",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_category" : "FAILED_LOGIN",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_request_origin" : "REST",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_node_id" : "B1FHXr8hRwOSN9YB7cN1EQ",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_request_layer" : "REST",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_rest_request_path" : "/_cluster/health",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "@timestamp" : "2022-05-24T18:11:11.885+00:00",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_request_effective_user_is_admin" : false,
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_format_version" : 4,
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_request_remote_address" : "169.254.73.1",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_node_host_address" : "169.254.73.2",
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]   "audit_rest_request_headers" : {
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]     "User-Agent" : [
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]       "curl/7.58.0"
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]     ],
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]     "content-length" : [
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]       "0"
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]     ],
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]     "Host" : [
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]       "localhost:9200"
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]     ],
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]     "Accept" : [
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]       "*/*"
[2022-05-24T18:11:11,887][INFO ][stdout                   ] [opensearch-node1]     ]
[2022-05-24T18:11:11,888][INFO ][stdout                   ] [opensearch-node1]   },
[2022-05-24T18:11:11,888][INFO ][stdout                   ] [opensearch-node1]   "audit_node_host_name" : "169.254.73.2"
[2022-05-24T18:11:11,888][INFO ][stdout                   ] [opensearch-node1] }
[2022-05-24T18:11:13,950][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-node1] Authentication finally failed for null from 169.254.73.3:35292

I was hoping for some more verbose tracing to lead me to the problem.

Here is a screenshot of the token from jwt.io:

Or possibly more useful: JSON Web Tokens - jwt.io

Note that I’m using the base64 encoded shared secret of

VWMrL1FmTGRoVnFja2RTcGEza09lbm1YY0w1RW1OUndvZDNhUC80Sy9OND0=

in both the generation of the token via jwt.io

and in my security config that re-applied on the docker instance.

I’d be happy to try a shared secret and token provided by you if you think that will help.

@iamthealex-es You must paste secret in clear from and not base64. base64 format is needed only for config.yml.

The secret before I base64 encode it is

Uc+/QfLdhVqckdSpa3kOenmXcL5EmNRwod3aP/4K/N4=

Note that the secret is base64 encoded, just to avoid having special characters.
Note that I base64 encode that come up the with base64 encoded secret of

VWMrL1FmTGRoVnFja2RTcGEza09lbm1YY0w1RW1OUndvZDNhUC80Sy9OND0=

I put the latter into my security config.yml.
I can use either one in jwt.io (I tick the box when I use the former and don’t tick the box when I use the latter).

@iamthealex-es Based on my example.

clear secret - 12345678901234567890123456789012
base64 encoded secret - MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=

config.yml
image

In jwt.io

I changed my payload to match yours, and now it works!
I finally have an working example of JWT, yay!

I will attempt to determine via experimentation what I need in the payload.

For example, your payload has a sub of “123456789” which I think should not be needed.

I think I would’ve made progress by myself if the error messages were more verbose. Maybe I missed a way to instruct the stack to use a more detailed tracing level?

@pablo , I really appreciate you working through this example with me. You rock!

@iamthealex-es Great to hear it worked.

sub is treated as username. It will fail to authenticate if not defined.

I think you’re saying it must be defined.
But I don’t see that user in internal_user.yml, so I suspect you’re also saying the value is not used when the role is provided (you provided a role of “admin” in your example).

Is there some documentation on the mapping of the payload to the authentication flow?
I found the examples about users, mapping and roles useful, but I didn’t find equivalent for JWT.

@iamthealex-es In regards to the default files location.

/usr/share/opensearch/config contains config files and certificates

/usr/share/opensearch/plugins/opensearch-security/securityconfig/ contains security config files.

In regards to logging maybe this will be helpful.

@iamthealex-es I’ve just checked the documentation and you’re correct. The security config files folder has a new location according to docs. However, I think a mistake was made when documentation for 2.0 was created.

In short, from version 2.0 the new security folder location is config/opensearch-secruity.
In 1.3.x, it is still plugins/opensearch-security/securityconfig