Skip to content

Conversation

@jesusVMayor
Copy link
Member

Fix the problems exposed in the issue #815

  • Allows to configure if the cookie is renewed or not
  • If the cookie is renewed allow only to use secret as signature type.
  • Use the validator secret to enconde.

@OCA-git-bot
Copy link
Contributor

Hi @sbidoul,
some modules you are maintaining are being modified, check this out!

@sbidoul
Copy link
Member

sbidoul commented Jul 14, 2025

Hi, I had not noticed #815 so far. Let's first discuss there.

default=True, help="Set to false only for development without https."
)
renew_cookie_on_response = fields.Boolean(
help="Renew the cookie in every response", default=True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expand the help text a bit to explain the risk of setting to True?

"The sginature type should be secret if the cookie is "
"renewed on responses"
)
)
Copy link
Member

@sbidoul sbidoul Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should error in this case. Creating a http-only secure cookie once the client has been authenticated with the bearer token is a valid use case to me. If anything it makes the life of front-end developers easier (and more secure) as they don't need to worry with securely storing the JWT token, as the browser handles the cookie securely for them. I do agree with the caveat regarding session invalidation.

_logger.error("database.secret system parameter is not set.")
raise ConfigurationError()
return secret
return self.secret_key
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the database secret is not adequate for your use case we could a new secret dedicated to signing/encrypting the cookie on the jwt validator record?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified encode and decode functions to use the fields renew_cookie_secret and renew_cookie_algorithm

@jesusVMayor jesusVMayor force-pushed the 16.0_auth_jwt_cookie_renew branch from 255176e to 186faaf Compare July 14, 2025 17:09
"way to invalidate sessions",
default=True,
)
renew_cookie_secret = fields.Char()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
renew_cookie_secret = fields.Char()
cookie_secret = fields.Char()

This secret is not specific to whether the cookie lifetime is renewed or not.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see a relation with the renewal, if is not set, we dont want to change it.
For example, i have a domain.com who creates a cookie with the jwt for the domain, and i have odoo in odoo.domain.com, so the cookie will be shared between domain and subdomains. I want the validator to check that cookie against the secret/public key, not against that new secret, the cookie should only be checked against that secret if odoo creates its own cookie when the renew is checked.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that is your use case, but the two changes are logically independent. Deciding whether renewing the cookie automatically and how to sign it are two independent topics. Reasoning about it that way should make the change simpler while still supporting your use case I think.

renew_cookie_algorithm = fields.Selection(
SECRET_ALGORITHM_SELECTION,
default="HS256",
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced we should propose an algorithm selection here.
For the JWT / bearer token, the algorithm must be agreed with the clients so an algorithm selection makes sense.
But here it's the server which protect the cookie for itself (the cookie is opaque to the clients), and we can let the server select the best algorithm.

@sbidoul
Copy link
Member

sbidoul commented Jul 15, 2025

Thanks for your work on this. Would you split this PR in two that we can discuss independently? As the cookie renewal and the cookie secret are two independent topics, it would be easier to review.

if not secret:
_logger.error("database.secret system parameter is not set.")
raise ConfigurationError()
return secret
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer keeping this method and return the validator cookie_secret if set else the database secret.

raise UnauthorizedCompositeJwtError(exceptions)

if validator.cookie_enabled:
if validator.cookie_enabled and validator.renew_cookie_on_response:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change does not seem necessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't understand why, we need it to not renew the cookie.

token = cls._get_cookie_token(validator.cookie_name)
assert token
return validator._decode(token, secret=validator._get_jwt_cookie_secret())
return validator._decode(token, cookie_secret=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is not necessary.

return jwks_client.get_signing_key(kid).key

def _encode(self, payload, secret, expire):
def _encode(self, payload, expire, secret=False):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not change this method. It is not necessary to change it if all the logic to get the secret is in _get_jwt_cookie_secret().

"way to invalidate sessions",
default=True,
)
renew_cookie_secret = fields.Char()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that is your use case, but the two changes are logically independent. Deciding whether renewing the cookie automatically and how to sign it are two independent topics. Reasoning about it that way should make the change simpler while still supporting your use case I think.

@jesusVMayor
Copy link
Member Author

#824
#825

@sbidoul
Copy link
Member

sbidoul commented Jul 18, 2025

Thanks for splitting the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants