Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow SSO authentication to provide a user secret #27929

Merged
merged 1 commit into from
Jul 18, 2022

Conversation

MichaIng
Copy link
Member

Implementing PR #24837 from immerda

As of my failed attempt to fix #27909 😄.

@summersab
Copy link
Contributor

Thanks, @MichaIng! Sorry for the hassle.

Do you think you could give me a hand with figuring out why this PR is failing? It's the companion code for the user_saml app:
nextcloud/user_saml#537

@MichaIng MichaIng force-pushed the enh/allowSsoToProvideSecret branch 2 times, most recently from 06bc829 to b4af323 Compare August 17, 2021 17:47
@MichaIng
Copy link
Member Author

CI is happy now.

* @return string
* @since 23.0.0
*/
public function getCurrentUserSecret(): string;
Copy link
Member

Choose a reason for hiding this comment

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

Would making this nullable make sense? Especially as $password = null; is the default.

Suggested change
public function getCurrentUserSecret(): string;
public function getCurrentUserSecret(): ?string;

Copy link
Member Author

@MichaIng MichaIng Aug 25, 2021

Choose a reason for hiding this comment

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

I think the idea was to explicitly not allow a null value here, so that checks can be omitted when the interface is implemented. Backends then need to always provide a string.

Ref: #27929 (comment)

But I see this is inconsistent with the description "Optionally returns a stable per-user secret.", which just has not been changed when I copy&pasted it from IApacheBackend (original idea, where it needed to be optional, of course) to its own interface. Shall I replace with:

* Returns a stable per-user secret e.g. used to secure file encryption keys.

Copy link
Member

Choose a reason for hiding this comment

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

I think I suggested to introduce the non-nullable return value earlier. To me it seems more reasonable as the user secret would be used for the user key encryption where I'd argue that if a backend provides user secrets there should be always one set for the user.

Copy link
Contributor

Choose a reason for hiding this comment

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

Two comments/issues:

  1. I've tried the most recent version of this PR with the IProvideUserSecretBackend in conjunction with the associated user_saml plugin PR:
    support for per-user encryption user_saml#537
    .
    Since users logging in with this method would be using the user_saml backend, lib/private/legacy/OC_User.php:177 never gets executed. Therefore, the password is never set. Am I missing something?
  2. With the code from the original PR, there seems to be a problem. After a few minutes, heartbeat requests start returning 401 responses. Then, any getstoragestats request triggers a page refresh after a 401 response because the session is no longer valid. I have yet to determine what is causing the session to fail, but it is a problem.

Any thoughts? I have a local Keycloak -> NC dev setup working, and I'm happy to test.

Copy link
Member Author

@MichaIng MichaIng Sep 11, 2021

Choose a reason for hiding this comment

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

Without a password, getCurrentUserSecret() will return null. So, this suggested change should either be reversed (probably the recommended solution) or a try/catch should be added

Is it possible that user_saml "provides" the IProvideUserSecretBackend only when a user secret is actually set? In theory this would then reduce some overhead, when the backend is used without it and would make allowing/checking for null obsolete, right? But I clearly lack knowledge about theses things, so probably it's nonsense 😄.

Copy link

@immerda immerda Nov 2, 2021

Choose a reason for hiding this comment

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

I have a proposal to get us unstuck here. How about we make IProvideUserSecretBackend::getCurrentUserSecret() nullable (or conditionally implementing IProvideUserSecretBackend is fine too -- anything that gets us unstuck...), but then do the following:

$password = null;
if ($backend instanceof \OCP\Authentication\IProvideUserSecretBackend) {
  $password = $backend->getCurrentUserSecret();
}
if ($password !== null) {
  $userSession->createSessionToken($request, $uid, $uid, $password);
} else {
  $userSession->createSessionToken($request, $uid, $uid);
}

This would allow us to disentangle the two problems, preserve the identical behavior for the non-userSecret case and let createSessionToken decide what to do when there is no password. This solution would also be more robust, as it removes that dependency on the decision if token passwords are nullable or not and allows us to define an interface that is independent of that.

Copy link
Member Author

@MichaIng MichaIng Nov 27, 2021

Choose a reason for hiding this comment

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

Isn't it exactly the same outcome whether passing $password = null or no argument at all? The createSessionToken has it's fourth argument null in both cases, isn't it?

The main question is indeed whether we want to be more explicit and force usage of a password when the backend is implemented or whether we want to allow implementing the backend without the need to provide a password. Generally I'm fans of being more explicit, but I understand that it may make the backend implementation more complicated.

I think it is agreed that we can or even should merge this PR first, before doing so at the backend, especially since the interfaces are defined here, so the above is really the last open question. I think we need someone who is more in charge to simply do a decision and we'll be able to deal with the result. But we need to get unstuck 😄.

@MichaIng MichaIng force-pushed the enh/allowSsoToProvideSecret branch 2 times, most recently from 3bd722b to 32aafe6 Compare November 27, 2021 22:53
@MichaIng MichaIng added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Dec 19, 2021
@MichaIng MichaIng added the php Pull requests that update Php code label Feb 19, 2022
@skjnldsv skjnldsv mentioned this pull request Mar 24, 2022
@blizzz blizzz mentioned this pull request Mar 31, 2022
@blizzz blizzz mentioned this pull request Apr 7, 2022
@MichaIng MichaIng force-pushed the enh/allowSsoToProvideSecret branch from 1e7c0ca to 9a3e63b Compare April 12, 2022 00:04
@blizzz blizzz mentioned this pull request Apr 13, 2022
@blizzz blizzz modified the milestones: Nextcloud 24, Nextcloud 25 Apr 21, 2022
@immerda
Copy link

immerda commented Jun 1, 2022

Hi, what is the status of this PR? It seems to me that we have managed to have fairly non-intrusive changes here, that will not change or break any existing interface, but allows us to continue with the saml side of things.

Are there any remaining objections to address before inclusion, @blizzz since you pushed the milestone?

@MichaIng MichaIng force-pushed the enh/allowSsoToProvideSecret branch from 9a3e63b to ba34c32 Compare June 1, 2022 20:17
@MichaIng
Copy link
Member Author

MichaIng commented Jun 1, 2022

Rebased and resolved conflict. We need someone to decide whether the API function should be allowed to return null or not (see discussion in code review).

@immerda
Copy link

immerda commented Jun 2, 2022

Two things happened:

  1. There is a discussion in this PR if our new interface should be allowed to return null. But everybody in this PR is in favor of returning non-null values. As the original author I agree and it will be possible to rewrite the sso backend for this new api, by simply implementing the behavior in a subclass of the UserBackend. This should be easy, as there is only one central location where it is instantiated.
  2. There was a discussion in wider NC if the password that we pass to createSessionToken can be null. This is indeed a discussion that afaik has not finished. But we resolved the issue here by not passing any more nulls to that function than the code already did. so our PR is decoupled from that discussion.

In summary, the people behind this PR agree on the api, the original author agrees, the api works for the intended usecase and this PR is not blocked by any external decision.

So I think we took that decision that you are talking about. If not, please let me know who can take this decision.

@MichaIng
Copy link
Member Author

MichaIng commented Jun 3, 2022

So we just need another approval.

The failing S3 checks are unrelated, fail randomly, I'll try to resolve with a rebase before merging.

Copy link
Member

@ChristophWurst ChristophWurst left a comment

Choose a reason for hiding this comment

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

Looks good

Implementing PR #24837 from immerda

Signed-off-by: MichaIng <[email protected]>
@MichaIng MichaIng force-pushed the enh/allowSsoToProvideSecret branch from ba34c32 to 21b3e87 Compare July 12, 2022 17:19
@MichaIng
Copy link
Member Author

Drone failure is unrelated, but I cannot merge due to it. Please someone do, so work on nextcloud/user_saml#537 can finally go on 🙂.

@blizzz blizzz merged commit 929aaaa into master Jul 18, 2022
@blizzz blizzz deleted the enh/allowSsoToProvideSecret branch July 18, 2022 09:50
@skjnldsv skjnldsv mentioned this pull request Aug 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3. to review Waiting for reviews feature: authentication php Pull requests that update Php code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants