Skip to content

KAFKA-7462: Make token optional for OAuthBearerLoginModule - #5733

Merged
rajinisivaram merged 3 commits into
apache:trunkfrom
rajinisivaram:KAFKA-7462
Oct 8, 2018
Merged

KAFKA-7462: Make token optional for OAuthBearerLoginModule#5733
rajinisivaram merged 3 commits into
apache:trunkfrom
rajinisivaram:KAFKA-7462

Conversation

@rajinisivaram

Copy link
Copy Markdown
Contributor

OAuthBearerLoginModule is used both on the server-side and client-side (similar to login modules for other mechanisms). OAUTHBEARER tokens are client credentials used only on the client-side to authenticate with servers, but the current implementation requires tokens to be provided on the server-side even if OAUTHBEARER is not used for inter-broker communication. Tokens should be optional for server-side login context to allow brokers to be configured without a token when OAUTHBEARER is not used for inter-broker communication.

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

@rajinisivaram

Copy link
Copy Markdown
Contributor Author

@rondagostino Can you review, please? Thank you!

@rondagostino

rondagostino commented Oct 3, 2018

Copy link
Copy Markdown
Contributor

@rajinisivaram Before I review, is it possible simply to mark the LoginModule as OPTIONAL in the case where it is one of multiple login modules on the broker side but it is not used for inter-broker communication? The Javadoc (https://docs.oracle.com/javase/7/docs/api/javax/security/auth/spi/LoginModule.html#commit()) says a return of false means the module is ignored, and I confirmed in the debugger that it is in fact the case (see, for example, https://github.com/frohoff/jdk8u-dev-jdk/blob/master/src/share/classes/javax/security/auth/login/LoginContext.java#L779). See also https://docs.oracle.com/javase/7/docs/api/javax/security/auth/login/Configuration.html where it says:

Optional - The LoginModule is not required to succeed. If it succeeds or fails, authentication still continues to proceed down the LoginModule list.

@rondagostino

Copy link
Copy Markdown
Contributor

@rajinisivaram Ah, wait, I think I see the issue. If we want to add a listener, then it may be the only LoginModule listed. Is that correct? In the meantime, I will review.

@rajinisivaram

Copy link
Copy Markdown
Contributor Author

@rondagostino We need one login module that succeeds. With the sasl.jaas.config option, we only have one login module (because it is a per-mechanism config). With static JAAS config, we could have multiple modules if on the same listener, but I think OAuth requires a single login module (

if (Objects.requireNonNull(jaasConfigEntries).size() != 1 || jaasConfigEntries.get(0) == null)
). And as you said, you could have just OAuth on a listener. Thanks for reviewing!

@rondagostino rondagostino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM aside from the minor comments.

@@ -93,7 +93,7 @@ public String errorUri() {
* the mandatory token to set

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Javadoc should say "optional" now instead of "mandatory"

public class OAuthBearerLoginModule implements LoginModule {

private enum LoginState {
NOT_LOGGED_IN,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would be good to comment that this implies logged-out or aborted since the state is null at the beginning (when we aren't logged in, either, but we don't set the state to NOT_LOGGED_IN). Either comment or rename to LOGGED_OUT_OR_ABORTED?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added comment.

identifyExtensions();
} else {
log.info("Logged in without a token, this login cannot be used to establish client connections");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: style seems to be to not include braces when there is only one if or else statement

log.info("Done logging out my extensions");
} else {
log.info("No extensions to logout for this login");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: braces unneeded

log.info("Done committing my token; committed token count is now {}", committedTokenCount());
} else {
log.info("No tokens to commit, this login cannot be used to establish client connections");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: braces unneeded

extensionsRequiringCommit = null;
if (extensionsRequiringCommit != null) {
if (myCommittedToken == null)
throw new IllegalStateException("Extensions being committed without a token");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is the myCommittedToken == null check unnecessary here since it can never be the case when there are extensions? I think we make sure of this since we only call identifyExtensions() when there is a token.

@rajinisivaram

Copy link
Copy Markdown
Contributor Author

@rondagostino Thanks for the review, have addressed the comments.

@rajinisivaram
rajinisivaram requested a review from junrao October 4, 2018 12:25
@rajinisivaram

Copy link
Copy Markdown
Contributor Author

retest this please

@junrao junrao left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@rajinisivaram : Thanks for the patch. LGTM

if (callback.token() != null)
throw new IllegalArgumentException("Callback had a token already");
if (moduleOptions.isEmpty()) {
log.info("Token not provided, this login cannot be used to establish client connections");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this get logged on the broker side? Will that be too noisy?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@junrao Thanks for the review, I have changed all the new log entries to debug. We also have https://issues.apache.org/jira/browse/KAFKA-7478 to reduce the level of some of the existing log entries.

@rajinisivaram

rajinisivaram commented Oct 8, 2018

Copy link
Copy Markdown
Contributor Author

Merging to trunk and 2.1.

@rajinisivaram
rajinisivaram merged commit c26823b into apache:trunk Oct 8, 2018
rajinisivaram added a commit that referenced this pull request Oct 8, 2018
OAuthBearerLoginModule is used both on the server-side and client-side (similar to login modules for other mechanisms). OAUTHBEARER tokens are client credentials used only on the client-side to authenticate with servers, but the current implementation requires tokens to be provided on the server-side even if OAUTHBEARER is not used for inter-broker communication. This commit makes tokens optional for server-side login context to allow brokers to be configured without a token when OAUTHBEARER is not used for inter-broker communication.

Reviewers: Ron Dagostino <rndgstn@gmail.com>, Jun Rao <junrao@gmail.com>
pengxiaolong pushed a commit to pengxiaolong/kafka that referenced this pull request Jun 14, 2019
OAuthBearerLoginModule is used both on the server-side and client-side (similar to login modules for other mechanisms). OAUTHBEARER tokens are client credentials used only on the client-side to authenticate with servers, but the current implementation requires tokens to be provided on the server-side even if OAUTHBEARER is not used for inter-broker communication. This commit makes tokens optional for server-side login context to allow brokers to be configured without a token when OAUTHBEARER is not used for inter-broker communication.

Reviewers: Ron Dagostino <rndgstn@gmail.com>, Jun Rao <junrao@gmail.com>
@AntonSmolkov

AntonSmolkov commented Sep 4, 2023

Copy link
Copy Markdown

@kirktrue, @rajinisivaram Hi!
Looks like the same fix is needed for the new secured org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginCallbackHandler
It also requires clientId/clientSecret even if oidc listener is not user for inter-broker communication.

@kirktrue

kirktrue commented Sep 8, 2023

Copy link
Copy Markdown
Contributor

@AntonSmolkov would you mind filing a new Jira to track? Thanks!

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.

5 participants