Skip to content

Make validation of typ header for JWTs opt-in #496

@MartinFlores751

Description

@MartinFlores751

Link to original discussion: https://groups.google.com/g/irod-chat/c/rbvr47baFRc/m/oBiahnJtBQAJ

TLDR: Since validation of the typ header in JWTs is introduced by the more modern OAuth 2 JWT RFC, this behavior should be opt-in.


Originally, the implementation for local validation followed the RFC for OAuth 2 JWTs by strictly validating the typ parameter: https://datatracker.ietf.org/doc/html/rfc9068#name-validating-jwt-access-token

After some testing, some wiggle room was given for JWTs with a typ header before the OAuth2 JWT RFC, seen in the following lines of code:

// Manually verify 'typ' matches what is specified in OJWT
// Allow for 'JWT'. Typical pre OJWT use had such claims, based on the JWT standard.
// See OJWT Section 4
if (!(token_type == "at+jwt" || token_type == "application/at+jwt" || token_type == "jwt")) {
logging::error("{}: Access Token with [typ] of type [{}] is not supported.", __func__, token_type);
return std::nullopt;
}

However, for some implementations, JWTs used in bearer tokens might not have the typ member at all. They follow the RFC for JWTs which states that the typ parameter for JWTs are optional: https://www.rfc-editor.org/info/rfc7519/#section-5.1

Since the typ header is not required by the original JWT standard and the OAuth 2 JWT standard is more recent, it may make sense to change the following lines that validate typ to be opt-in:

// Handling missing 'typ'
if (!_jwt.has_type()) {
logging::error("{}: invalid JWT, missing [typ].", __func__);
return std::nullopt;
}
// 'typ' is case insensitive
auto token_type{boost::to_lower_copy<std::string>(_jwt.get_type())};
// Manually verify 'typ' matches what is specified in OJWT
// Allow for 'JWT'. Typical pre OJWT use had such claims, based on the JWT standard.
// See OJWT Section 4
if (!(token_type == "at+jwt" || token_type == "application/at+jwt" || token_type == "jwt")) {
logging::error("{}: Access Token with [typ] of type [{}] is not supported.", __func__, token_type);
return std::nullopt;
}

The opt-in code could also change remove the final check in this if statement to strictly follow the OAuth 2 JWT standard:

if (!(token_type == "at+jwt" || token_type == "application/at+jwt" || token_type == "jwt")) {

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions