docs icon indicating copy to clipboard operation
docs copied to clipboard

What fields should my JWT define?

Open caniko opened this issue 3 years ago • 12 comments

First: I have an authentication server that generates JWTs, and I would like to use it for authentication in StargateAPI. I couldn't find an explicit outline of fields that the JWT needs to store in the docs. What are these fields?

Second: I am interested in implementing row-based permission for modification, and I would like to avoid creating roles in CQLSH, and do it purely over JWTs. The logical operation is simple: if the owner ID (table column) is not identical to the user ID (on the JWT) the client has no modication rights, but can still read the row. I believe at least some devs to be interested in this topic, it should be mentioned.

The authentication documentation should focus on defining/outlining more key concepts, including these.

caniko avatar Mar 02 '22 22:03 caniko

It sounds like you might want to implement a custom AuthenticationService (authn) and AuthorizationService (authz).

The token-based auth. service is very simple and can be used as a skeleton for getting started creating a JWT version: https://github.com/stargate/stargate/tree/v1.0.50/auth-table-based-service/src/main/java/io/stargate/auth/table

The JWT could contain whatever you need to handle authn/authz.

mpenick avatar Mar 14 '22 19:03 mpenick

I want to avoid customizing the code... The dream was to just use the K8ssandra helm chars or Kustomize.

caniko avatar Mar 26 '22 16:03 caniko

@caniko have you taken a look at the JWT docs here?

https://stargate.io/docs/stargate/1.0/developers-guide/authnz.html#_jwt_based_authenticationauthorization

Your JWT should contain a stargate_claims claim and in that a field of x-stargate-role which matches the role in the DB. Here's where all that is handled

https://github.com/stargate/stargate/blob/234becf8db63acb9d680828ea22ed57524b861f8/auth-jwt-service/src/main/java/io/stargate/auth/jwt/AuthnJwtService.java#L39

For row level access control you'll want to create another field inside the stargate_claims with x-stargate-COLUMN_NAME where COLUMN_NAME is the name of the column that you want to use for controlling access. The logic for that is in

https://github.com/stargate/stargate/blob/234becf8db63acb9d680828ea22ed57524b861f8/auth-jwt-service/src/main/java/io/stargate/auth/jwt/AuthzJwtService.java#L83

So, as is, the JWT based auth will perform authn without needing cqlsh but if you want to do full authz then you'll need to modify AuthzJwtService. I also believe you'll need to set -D stargate.cql_use_transitional_auth=true so the persistence module doesn't perform authz and instead trusts it's been done farther up the stack (I haven't looked at that particular functionality in awhile so you'll want to double check).

dougwettlaufer avatar Apr 03 '22 04:04 dougwettlaufer

Thank you @dougwettlaufer. I have a few more questions:

  1. Could you expand on x-stargate-role? Can this role be the admin role? As mentioned earlier read-access on all, but only modify access if the column value matches its counter part in the JWT. I want to avoid making roles for every user.
  2. How do I pass in the public key of my JWT to Stargate for it to be decrypted? Can I give a K8 secret URL and key?

Also, I don't think I need custom authz on the Stargate side.

caniko avatar Apr 20 '22 10:04 caniko

  1. Could you expand on x-stargate-role? Can this role be the admin role? As mentioned earlier read-access on all, but only modify access if the column value matches its counter part in the JWT. I want to avoid making roles for every user.

The x-stargate-role is the role you've created via cqlsh. So if you've created web-user and web-user-admin roles then in your IDP you'll map which users get which role set in the x-stargate-role claim.

  1. How do I pass in the public key of my JWT to Stargate for it to be decrypted? Can I give a K8 secret URL and key?

You'll pass the URL of the "well-known" endpoint to stargate with -Dstargate.auth.jwt_provider_url

dougwettlaufer avatar Apr 25 '22 14:04 dougwettlaufer

The x-stargate-role is the role you've created via cqlsh. So if you've created web-user and web-user-admin roles then in your IDP you'll map which users get which role set in the x-stargate-role claim.

This makes sense, thank you.

You'll pass the URL of the "well-known" endpoint to stargate with -Dstargate.auth.jwt_provider_url

Using JWKS is OK. However, I was hoping to have the option to decrypt the JWT on Stargate by passing the public key from an opaque secret.

caniko avatar Apr 25 '22 15:04 caniko

@dougwettlaufer, could you confirm if the example below is correct?

-D stargate.cql_use_transitional_auth=true

Read scenario The JWT has stargate_claims with a cqlsh_role that has read access -> Stargate returns the queried rows.

Modify scenario The JWT has stargate_claims:

{
  `x-stargate-COLUMN_NAME`: <correct value>
  `x-stargate-role`: `cqlsh role`
}

Stargate relays the modification requested by the client to Cassandra.

caniko avatar Apr 25 '22 17:04 caniko

@caniko that should be correct. Although you can probably leave off stargate.cql_use_transitional_auth

dougwettlaufer avatar Apr 26 '22 23:04 dougwettlaufer

@dougwettlaufer

Lastly, which of the key-value pairs returned from the JWKS endpoint is used by Stargate? JWKS:

{
    "keys": [
        {
            "kid": "vdaec4Br3ZnRFtZN-pimK9v1eGd3gL2MHu8rQ6M5SiE",
            "kty": "RSA",
            "alg": "RS256",
            "use": "sig",
            "n": "4OPCc_LDhU6ADQj7cEgRei4VUf4PZH8GYsxsR6RSdeKmDvZ48hCSEFiEgfc3FIfh-gC4r9PtKucc_nkRofrAKR4qL8KNNoSuzQAOC92Yz6r7Ao4HppHJ8-QVdo5H-d9wfNSlDLBSo5My4b4EnHb1HLuFxDqyhFpGvsoUJdgbt3m_Q3WAVb2yrM83S6HX__vrQvqUk2e7z5RNrI7LSsW3ZOz9fU7pvm8-kFFAIPJ7fOJIC7UQ9wBWg3YdwQ0B2b24jXjVr0QCGzqJ6o1G_UZYSJCDMGQDpDcEuYnvSKBLfVR-0EcAjolRhcSPjHlW0Cp0YU8qwWDHpjkbrMrFmxlO4Q",
            "e": "AQAB"
        }
    ]
}

kid means key id, alg is the algorithm, and n is the public key used for this realm. Example copied from redhat article for keycloak.

Definitely alg and n. Any of the other ones?

And, how does Stargate know which kid to use for the JWT? Is the kid in the JWT?

caniko avatar Apr 27 '22 08:04 caniko

@caniko - Did you ever get further with this project? Is there anything that you believe should be documented from your experience with JWT?

polandll avatar Jun 07 '22 02:06 polandll

@polandll I am currently blocked by #558 on the k8ssandra side for proper testing.

Please answer the questions from my last post in the meantime.

caniko avatar Jun 07 '22 06:06 caniko

@dougwettlaufer additional to my previous question: What if correct value has no match in the COLUMN?

{
  `x-stargate-COLUMN_NAME`: <correct value>
  `x-stargate-role`: `cqlsh role`
}

Is it only read in that case? Or can I provide another role in those cases?

As mentioned before: I want global read-only.

caniko avatar Jul 13 '22 11:07 caniko