-
Notifications
You must be signed in to change notification settings - Fork 3k
Provide fluent API to set up SecurityIdentityAugmentors and IdentityProviders such as Security JPA programmatically
#51279
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
base: main
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
3d9f827 to
86e5b6a
Compare
|
🎊 PR Preview 3f428b9 has been successfully built and deployed to https://quarkus-pr-main-51279-preview.surge.sh/version/main/guides/
|
Status for workflow
|
This comment has been minimized.
This comment has been minimized.
extensions/security-jpa-common/runtime/src/main/java/io/quarkus/security/jpa/SecurityJpa.java
Show resolved
Hide resolved
| * Registers given {@link HttpAuthenticationMechanism} in addition to all other global authentication mechanisms. | ||
| * | ||
| * @param mechanism {@link HttpAuthenticationMechanism} | ||
| * @param identityProviders {@link IdentityProvider}s that should be used for authentication instead |
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.
What is not clear to me is why these identity providers and augmentors must be used instead of CDI registered identity providers and augmentors, while the mechanism is not meant to be used instead of other mechanisms.
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.
Before I answer, I would like to summarize so that we speak about the same thing:
- this method adds a new mechanism (like
new CustomAuthMechanismor any other mechanism at all) and allows you to use your own identity providers and augmentors - if you want to use global identity providers or augmentors, then don't use it
- if you want to use global identity providers/augmentors and some other providers/augmentors, specific for only this mechanism, you can create collection with global identity providers/augmentors and your own, specific for only this mechanism; nothing stops you
What is not clear to me is why these identity providers and augmentors must be used instead of CDI registered identity providers and augmentors, while the mechanism is not meant to be used instead of other mechanisms.
- how many times do you want to use both identity providers registered as CDI beans and dedicated ones for this mechanism? I'd say you usually need one or two
- this methods facilitates programmatic setup for Quarkus Security JPA, if with
httpSecurity.basic()we already use Quarkus Security JPA from CDI, then why would we need the programmatic setup at all? Only answer I could come with is flexibility - unlike CDI providers, which are there for every mechanism, here you can explicitly select which provider and augmentors you want to apply
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.
Well, CDI registered augmentor may be used with any mechanism.
I think it would make sense not to mix augmentors and identity providers in such methods.
I'd also consider providing a generic option for adding identity providers without focusing on JPA first, as part of the fluent API, where an option to add an identity provider becomes available only after a method registering a custom mechanism is chosen...
IMHO it should be a draft PR
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.
Well, CDI registered augmentor may be used with any mechanism.
I think it would make sense not to mix augmentors and identity providers in such methods.
I'd also consider providing a generic option for adding identity providers without focusing on JPA first, as part of the fluent API, where an option to add an identity provider becomes available only after a method registering a custom mechanism is chosen...
I wrote it based on this comment quarkusio/quarkus-security#76 (comment) which suggests this:
Mechanism -> Identity Provider(s) -> Augmentors(s) or Mechanism -> Augmentors(s)
and that is the hierarchy introduced here (except I chose one of tem - I don't order augmentors under identity providers, it would only bring work and no pros I know about).
whether we write it like:
httpSecurity.mechanism(form, jpa)
as my tests do, or we do something like:
httpSecurity.buildMechanism(form).identityProvider(jpa).augmentor(customAugmentor)
is just matter of finding the right name for that HttpSecurity method. I put it into one httpSecurity.mechanism method because I am not aware of a good name (we cannot do httpSecurity.mechanism(form).augmentor... because the return type is HttpSecurity). I don't mind rewriting it if you have a suggestion.
IMHO it should be a draft PR
I'll make it draft right now. Drafts make only sense when there is something to work on. Let's establish what is it.
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.
Well, CDI registered augmentor may be used with any mechanism.
Sure. What do you want to say? This PR gives you 3 options:
- use CDI augmentors if you don't configure augmentors via
HttpSecurity - use your own augmentors, whether you create instance or inject them
- use your own augmentors and CDI augmentors. Nothing stops you to do
new ArrayList<>()thenaddAll(cdiAugmentors)andaddAll(customAugmentors)
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.
Thanks @michalvavrik, right, so we have .mechanism(HttpAuthenticationMechanism) right now, so, perhaps we can, to start with, offer .mechanism(HttpAuthenticationMechanism, IdentityProvider), .mechanism(HttpAuthenticationMechanism, IdentityProvider, SecurityIdentityAugmentor), that are typical setup options for custom authentication mechanisms ?
As far as a JPA identity provider is concerned, you have a good point that it is already CDI registered, but I'm thinking it would a bit confusing to users the way it is offered in this PR, if they say want to add it to a custom mechanism dealing with a name and password, seeing a collection, references to CDI, etc.
Perhaps, when it comes to JPA, it, it should be offered in a typed fashion for existing typed basic or form methods or as a single IdentityProvider produced by a JPA IdentityProvider builder.
But what should be offered is a JPA setup, like a DB setup (persistence unit name), as the whole idea of the API is to let users avoid application.properties.
So for example,
.basic().jpa().persistence("orders")..., .form().jpa().persistence("orders")...,
and with the generic method added here,
.mechanism(new MyHttpMechanism(), JpaIdenityProvider().persistence("order").build())
Perhaps something like this...
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.
hey, okay, in principle I agree.
.basic().jpa().persistence("orders")..., .form().jpa().persistence("orders")...
that looks nice, but it means we cannot have the same httpSecurity.basic() as we did until now, because it allows you to just continue, e.g. httpSecurity.basic().path(...)... If httpSecurity.basic()....end() has to be ended, it will be bit clumsy. It is really just about lack of ideas how to nicely call it. That is why I kept it like:
httpSecurity.basic(jpa())
# which will allow us to do
httpSecurity.basic(jpa().persistence("abc"))
this way, we have extendability, because HttpSecurity doesn't know anything about JPA Security. I agree that httpSecurity.basic().jpa() looks nice though.
I'll try to produce something along these lines, though unless you suggest some names, we need to have basic(jpa()..).
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.
basic(jpa().persistence("abc")) looks ok too, so the basic override will take IdentityProvider ? That should be fine and perhaps we can fail early if the identity provider's request type is not UsernamePasswordAuthenticationRequest
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.
basic(jpa().persistence("abc"))looks ok too, so thebasicoverride will takeIdentityProvider? That should be fine and perhaps we can fail early if the identity provider's request type is notUsernamePasswordAuthenticationRequest
I think it will take some other trick, it doesn't make sense to have different jpa() static method for form and different for basic auth mechanism. I am starting working on this right now.
|
I run the OIDC wiremock IT Module tests and they are passing for me locally. |
Status for workflow
|

Uh oh!
There was an error while loading. Please reload this page.