8000 Enable MapUserProvider storing username with the letter case signific… by vramik · Pull Request #10332 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content

Enable MapUserProvider storing username with the letter case signific… - #10332

Closed
vramik wants to merge 1 commit into
keycloak:mainfrom
vramik:#10245-username-lettercase
Closed

vramik wants to merge 1 commit into
keycloak:mainfrom
vramik:#10245-username-lettercase

Conversation

@vramik
@vramik vramik commented Feb 19, 2022 •
Copy link
Copy Markdown
Contributor

…ance

Closes #10245

Submitting WIP pull request. Currently it contains only implementation for concurrenthashmap.

I'd like to get opinion whether we can use this approach before going ahead with it. Few notes:

  • Config.Scope is passed from ConcurrentHashMapStorageProviderFactory to MapModelCriteriaBuilder for querying and to UserConcurrentHashMapStorage for persisting a user ... should it be rather different object? E.g. Map<String, Object> options?
  • Should we leave legacy UserCacheSession unchanged?
  • Should we leave UserStorageManager unchanged?

@vramik
vramik requested a review from hmlnarik February 19, 2022 17:01
@vramik vramik added area/storage Storage layer — JPA entities, database schemas, Liquibase migrations, caching kind/enhancement Categorizes a PR related to an enhancement team/storage-sig labels Feb 19, 2022
@vramik
vramik force-pushed the #10245-username-lettercase branch from 1e4c58b to f58d234 Compare February 22, 2022 06:47
@Override
public UserModel getUserByUsername(RealmModel realm, String username) {
logger.tracev("getUserByUsername: {0}", username);
//TODO remove following line?
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.

Good question. I'd think we shouldn't change legacy behavior.

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.

No, we should keep it. It is the storage responsibility to deal with letter case. In the case of legacy storage, lettercase is intentionally ignored.


public Scope getStorageConfigScope() {
return storageConfigScope;
}
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.

I'm not sure this is the correct scope we would want to use. This only contains the storage config that is found inside the particular areas (client, group, etc). The final storage factory that is instantiated actually gets a scope that is broader than this - it combines the this area-specific config with the root config found in the mapStorage configuration (i.e. it falls back to the root config if a property is not defined in the area config). Also, if we go forward with multiple profiles for a particular storage, that would have to be taken into consideration as well.

So wouldn't we want to use the actual scope that was used to init the storage factory instead?

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.

@sguilhen @vramik This scope is the right one for the storage config, the options inherited from the root (and perhaps profile) are available transparently from this scope. See ComponentModelScope. However, storage maintains the capability of the storage to respect letter case. Whether the lettercase should be respected if the store supports it is however setting on the realm, so it has to be a property of the map user provider.


@vramik Factory should translate the configuration Scope values into properties and the objects created by the factory should not be given access to the Scope instance unless justified.

The reason is to keep the configuration management maintained in a single place (factory), and translated once (in the factory) rather than multiple times (in each created instance).

It seems that the only reason for this method is the eventually be searched for username-lettercase option. This by itself is not sufficient justification. Is there any other?

@@ -0,0 +1,75 @@
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates
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.

Nitpick: year


private final Scope config;

public UserConcurrentHashMapStorage(Class<UserModel> modelClass, StringKeyConvertor<K> keyConvertor, DeepCloner cloner, Scope config) {
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.

Perhaps we should only propagate the one property that this storage needs access to instead of the whole scope object.

DefaultModelCriteria<UserModel> mcb = criteria();
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
.compare(SearchableFields.EMAIL, Operator.EQ, email);
.compare(SearchableFields.EMAIL, Operator.EQ, email.toLowerCase());
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.

In UserLookupProvider bellow the javadoc now says " * @PARAM email email address (case-sensitivity is controlled by storage)". This line is doing the opposite, isn't it?

@hmlnarik hmlnarik left a comment
8000 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.

Thank you for the PR. It is a great start.

The ability to ignore the letter case in a particular realm is given by two things:

  • Ability of the store to distinguish letter case (feature of the store, say LDAP might be ignoring letter-case while JPA not)
  • Option on realm which instructs a particular user provider to ignore or respect letter case for name lookups

I believe that most of the changes should only be in the MapUserProvider to handle the flag, and depending on it either use username directly as is, or (say) lowercase it prior to using it in criteria.

Also please see inline.

@Override
public UserModel getUserByUsername(RealmModel realm, String username) {
logger.tracev("getUserByUsername: {0}", username);
//TODO remove following line?
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.

No, we should keep it. It is the storage responsibility to deal with letter case. In the case of legacy storage, lettercase is intentionally ignored.


public Scope getStorageConfigScope() {
return storageConfigScope;
}
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.

@sguilhen @vramik This scope is the right one for the storage config, the options inherited from the root (and perhaps profile) are available transparently from this scope. See ComponentModelScope. However, storage maintains the capability of the storage to respect letter case. Whether the lettercase should be respected if the store supports it is however setting on the realm, so it has to be a property of the map user provider.


@vramik Factory should translate the configuration Scope values into properties and the objects created by the factory should not be given access to the Scope instance unless justified.

The reason is to keep the configuration management maintained in a single place (factory), and translated once (in the factory) rather than multiple times (in each created instance).

It seems that the only reason for this method is the eventually be searched for username-lettercase option. This by itself is not sufficient justification. Is there any other?

@vramik
vramik commented Jun 28, 2022
Copy link
Copy Markdown
Contributor Author

Thank you for the PR. It is a great start.

The ability to ignore the letter case in a particular realm is given by two things:

  • Ability of the store to distinguish letter case (feature of the store, say LDAP might be ignoring letter-case while JPA not)
  • Option on realm which instructs a particular user provider to ignore or respect letter case for name lookups

I believe that most of the changes should only be in the MapUserProvider to handle the flag, and depending on it either use username directly as is, or (say) lowercase it prior to using it in criteria.

Also please see inline.

Thanks @hmlnarik . I have some questions:

  • say store is able to distinguish letter case significance and the option is set to allow it, do we want to allow two different users with usernames let's say Admin and admin?
    • if so, then once the store is started with this option on, it cannot be started again with the option switched off, right?
  • when using tree store configured in a way that it'd be from top to bottom hotrod-jpa-ldap and LDAP is unable to distinguish it and jpa would be configured to switch the option on - is that invalid configuration?

@hmlnarik
Copy link
Copy Markdown
Contributor
  • say store is able to distinguish letter case significance and the option is set to allow it, do we want to allow two different users with usernames let's say Admin and admin?

Yes

  • if so, then once the store is started with this option on, it cannot be started again with the option switched off, right?

It can as long as there are no colliding usernames at the time of the switch. We do not need to support that check from the day 1, a warning to the log would suffice for the start.

  • when using tree store configured in a way that it'd be from top to bottom hotrod-jpa-ldap and LDAP is unable to distinguish it and jpa would be configured to switch the option on - is that invalid configuration?

It might or might not, depending on whether the username is cached in JPA or only loaded from LDAP. This is generally a problematic area, and it will be responsibility of tree store to log a warning about potential consequences of such misconfiguration.

8BD0

@vramik
vramik commented Jul 18, 2022
Copy link
Copy Markdown
Contributor Author

replaced by #13183

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

Labels

area/storage Storage layer — JPA entities, database schemas, Liquibase migrations, caching kind/enhancement Categorizes a PR related to an enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable MapUserProvider storing username with the letter case significance

3 participants

0