-
Notifications
You must be signed in to change notification settings - Fork 492
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
Handle unregistered users in BearerTokenAuthMechanism and implement user registration mechanism #10972
base: develop
Are you sure you want to change the base?
Conversation
… is validated but there is no registered user account
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…nAuthMechanism to AuthenticationServiceBean
…earer token auth feature flags compatibility
This was sort of a mistake, there was a typo in the docs, the dataverse flag is not |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Ok, I see two distinct topics here. First, we have user consent, which is configured independently from the Terms of Service (ToS) in the client settings. It controls whether a user is prompted to approve data sharing and permissions with a specific client during login. On the other hand, the 'Fine Grain OpenID Connect Configuration > Terms of Service' option allows you to attach the Relying Party's (in this case, Dataverse) ToS URL in the OIDC metadata. Just to clarify, it is not valid to assume that accepting the consent prompted by 'Login Settings: Consent Required' automatically means the user has accepted the Terms of Service (ToS). While the two concepts may be related, they serve distinct purposes and have different legal and technical implications. I'm not entirely sure if we're on the same page here, so I wanted to mention this to avoid misunderstandings. Sometimes, with so many concepts involved, it's difficult to clarify everything through GitHub messages. I’d also be happy to discuss it on Zoom if that’s easier. To address user consent acceptance, we could create a specific feature flag in Dataverse for Keycloak providers that checks whether the consent has been accepted in the provider before accessing the user’s information. This could be done using the Keycloak API. On the other hand, Keycloak doesn’t have a built-in feature to automatically handle ToS acceptance as part of the standard consent flow for OIDC. The Terms of Service URL configured under Fine Grain OpenID Connect Configuration is part of the OIDC discovery document metadata and is not shown in the Keycloak UI. It is meant to be referenced by OIDC clients, and if you want users to accept the ToS explicitly, you would need to handle that separately. One potential workaround could be to include the ToS link in the client consent text, which is configurable. However, I believe this might be too much of a workaround and could lead to misunderstandings. Another option could be to create a custom flag (e.g., tosAccepted=true) stored as a user attribute. But the question is: Isn’t it easier to manage the ToS from Dataverse, which is under our control, than to wait for Keycloak IdPs to apply ad-hoc configurations for ToS acceptance? |
Those topics are depending on the jursitication and legal team involved different, overlapping or the same concepts. But in most cases its easier to ask once for permission than many times. Thus, the combination of both* into one conceptional technical step. Sorry, that I wasn't clear about this.
Yes, this is part of the protocol definition of OIDC:
I think we are, but we can still chat in zulip later..
First, if you do implement it, please do not make it keylock-specific. Second, you do not need to store this information in the resource server (dataverse). If the permission is given, you get the data, otherwise you cannot get the information because the permission server does not give out user data. The protocol even indicates why no information is transmitted. See here:
Yes, this is a fundamental issue with OIDC. The What can we do about it? We as resource servers (developers/operators) want a (legally binding) property that tells us that the user has read, understood and accepted the required terms/policies, right? This means that every user has to set this flag. When we create and control a user interface, we can ensure that the required information is available, displayed to a user, scrolled through and actively accepted by a click. Once we no longer control the visualisation (i.e. a user-facing API sets the property), we cannot infer that the user has seen, interacted with or accepted anything. All we have is a property claiming that this happened. Whether this is sufficient is a question for a legal team and will vary from jurisdiction to jurisdiction. (For our installation it is not!) The ODIC protocol with So how do we solve this problem? Let the user configure what they need (i.e. what their legal team requires) and set reasonable defaults. First, allow |
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
…flag in RegisterOIDCUserCommand
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…ance-in-idp feature flag usage
…ptance-in-idp feature flag usage
This comment has been minimized.
This comment has been minimized.
1 similar comment
📦 Pushed preview images as
🚢 See on GHCR. Use by referencing with full name as printed above, mind the registry name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK - looks good. I suggested some rewording in the docs for the API call - feel free to accept or edit further - I was basically trying to make the default path come first.
What this PR does / why we need it:
This PR includes a mechanism for registering new users in Dataverse through a Bearer Token.
BearerTokenAuthMechanism
The Bearer Token authentication functionality (available through feature flag) has been extended to properly handle cases where BearerTokenAuthMechanism successfully validates the token but cannot identify any Dataverse user because there is no account associated with the token. See the current development version of BearerTokenAuthMechanism. (https://github.com/IQSS/dataverse/blob/develop/src/main/java/edu/harvard/iq/dataverse/api/auth/BearerTokenAuthMechanism.java#L58).
The BearerTokenAuthMechanism has been extended to return a meaningful error in the scenario described above. Specifically, the calling user would receive a 403 error, indicating that the token is validated but the user is not registered in Dataverse.
Additionally, the entire BearerTokenAuthMechanism class has been refactored, moving authentication and token verification logic to AuthService, since this logic is also utilized by the new user registration functionality included in this PR, and it also results in a simpler version of BearerTokenAuthMechanism, more testable and with more limited responsability.
User registration endpoint
The new endpoint takes the bearer token and a UserDTO object with the required properties to create a user account in Dataverse. It only works if the bearer token feature flag is enabled. A RegisterOidcUserCommand handles the validation of the bearer token and user data, and the account creation process. It can return various errors, including a new InvalidFieldsCommandException, which lists any validation errors in the UserDTO. This exception is now handled by AbstractApiBean like other command exceptions and can be used for future purposes.
Which issue(s) this PR closes:
Special notes for your reviewer:
See Handle unregistered users in BearerTokenAuthMechanism and implement user registration mechanism #10972 (comment) to understand why the OIDC UserInfo endpoint is not used in this design
The IT for the new registration endpoint is disabled because it depends on the containerized environment, which is not available in Jenkins. Additionally, the feature flag would not be active, so it would fail for this reason as well. Changes have been made to the Keycloak realm JSON to suit the needs of this IT, particularly the modification of roles in the test realm to allow an admin user to create a random test user in the IT setup.
Suggestions on how to test this:
Visual inspection of the API integration tests. Overall, this PR is extensively tested with unit and integration tests, but it is in the ITs where we can see how the endpoint calls work and the different responses that can be obtained.
We can also run this branch locally and reproduce the same calls made in the ITs using curl.
Does this PR introduce a user interface change? If mockups are available, please link/include them here:
No
Is there a release notes update needed for this change?:
Yes, attached.
Additional documentation:
None