Sounds like a good approach. The selected authenticator will be done via some sort of config or via a setter or similar?
Sent from my iPhone On Feb 29, 2012, at 15:36, Gerhard Petracek <[email protected]> wrote: > @others: > > fyi - it looks like there was just a misunderstanding and after a short > discussion we agreed on: > - authenticators are cdi beans > - just one authenticator is active for the authorization process > - we need something like AuthenticatorSelector#getSelectedAuthenticator to > provide the current authenticator > > regards, > gerhard > > > > 2012/2/29 Shane Bryzak <[email protected]> > >> On 29/02/12 21:42, Gerhard Petracek wrote: >> >>> hi shane, >>> >>> imo implementations of Authenticator should be normal cdi beans annotated >>> with @Alternative, if they shouldn't be enabled by default (and we can use >>> (global) cdi alternatives to allow custom implementations). >>> -> we wouldn't need Identity.authenticatorClass and >>> Identity.authenticatorName. >>> >> >> I don't see any advantage in making the Authenticators alternatives, on >> the contrary it creates an additional configuration burden for the >> developer who must then enable the ones they want to use. It also wouldn't >> alleviate the requirement for Identity.authenticatorClass and >> Identity.authenticatorName as there are use-cases for these, one of which >> I've already mentioned in the sourceforge.net example. >> >> Another example of a use case where Identity.authenticatorClass is >> important was described by a Seam user some time ago - Say your application >> has both a public and private facing user interface; for the default, >> public interface authentication should be performed one way using one >> particular Authenticator implementation, while for the private interface >> the authentication process may be required to use a different database >> table (or some other identity storage) to authenticate against, requiring a >> different Authenticator to be used. By being able to set the specific >> Authenticator class the login process can control which Authenticator is >> used. Here's some code to demonstrate: >> >> public @Model class SecurityActions >> { >> @Inject Identity identity; >> >> public void publicLogin() >> { >> identity.**setAuthenticatorClass(**DefaultAuthenticator.class); >> identity.login(); >> } >> >> public void internalLogin() >> { >> identity.**setAuthenticatorClass(**InternalAuthenticator.class); >> identity.login(); >> >> } >> } >> >> >>> @ AuthenticationStatus.DEFERRED and #postAuthenticate: >>> it would be great, if you can provide a source-code example which shows >>> the >>> usage. >>> >> >> Here's an example of a deferred authentication from Seam's >> OpenIdAuthenticator: >> >> public void authenticate() >> { >> OpenIdProvider selectedProvider = getSelectedProvider(); >> if (selectedProvider == null) >> { >> throw new IllegalStateException("No OpenID provider has been >> selected"); >> } >> >> OpenIdRelyingPartyApi openIdApi = openIdApiInstance.get(); >> >> List<OpenIdRequestedAttribute> attributes = new LinkedList<** >> OpenIdRequestedAttribute>(); >> >> selectedProvider.**requestAttributes(openIdApi, attributes); >> >> openIdApi.login(**selectedProvider.getUrl(), attributes, >> getResponse()); >> >> setStatus(**AuthenticationStatus.DEFERRED)**; >> } >> >> In this case, control of the user's browser is handed off to an OpenID >> provider. Once the user authenticates successfully, they are then >> redirected back to a landing page in your own application which then >> completes the authentication process. >> >> I don't have a specific example for postAuthenticate(), however it could >> be used for any number of things ranging from auditing, to >> post-authentication population of roles and groups in environments where >> loading these resources may be an expensive operation that you may not wish >> to perform until authentication is successful. >> >> >> >> >>> @get*Memberships >>> currently i'm thinking about the dis-/advantages of moving those methods >>> to >>> User (or something like AuthenticatedUser) >>> >> >> I think this would create complications when we start getting into the >> Identity Management API. The User object is intended to be a >> self-contained, atomic representation of a single user and isn't intended >> to contain state regarding the user's relationships or membership >> privileges. It's used in many Identity Management related operations and >> the addition of this extra state would likely be problematic - I'm sure >> Bolek could add more to this. >> >>> >>> regards, >>> gerhard >>> >>> >>> >>> 2012/2/28 Shane Bryzak<[email protected]> >>> >>> Following on, here's an extremely basic example of an Authenticator. If >>>> a >>>> developer were to simply include this class in their application and >>>> perform no further configuration, then it would be used during the >>>> authentication process: >>>> >>>> public class SimpleAuthenticator extends BaseAuthenticator implements >>>> Authenticator >>>> { >>>> @Inject >>>> Credentials credentials; >>>> >>>> public void authenticate() >>>> { >>>> if ("demo".equals(credentials.****getUsername())&& >>>> credentials.getCredential() instanceof >>>> PasswordCredential&& >>>> "demo".equals(((****PasswordCredential) >>>> credentials.getCredential()).****getValue())) { >>>> setStatus(****AuthenticationStatus.SUCCESS); >>>> >>>> setUser(new SimpleUser("demo")); >>>> } >>>> else >>>> { >>>> setStatus(****AuthenticationStatus.FAILURE); >>>> >>>> } >>>> } >>>> } >>>> >>>> In this example, BaseAuthenticator is an abstract class that implements >>>> most of the Authenticator methods and simply allows the subclass to >>>> invoke >>>> setStatus / setUser / addGroup etc to set the user's authentication >>>> state. >>>> >>>> >>>> On 29/02/12 08:15, Shane Bryzak wrote: >>>> >>>> With the basic implementation of Identity now in place, it's now a good >>>>> time to discuss authentication. The authentication API comes into play >>>>> during the user authentication process, and is responsible for ensuring >>>>> that the user is who they claim to be, and providing the application >>>>> with >>>>> the user's assigned role and group privileges. The authentication API >>>>> is >>>>> not invoked directly by the user, rather it is consumed by the login >>>>> process when the user invokes Identity.login(). It should be easily >>>>> configured and simple to extend. >>>>> >>>>> The following code shows the proposed SPI interface for Authenticator, >>>>> an >>>>> implementation of which manages the authentication process: >>>>> >>>>> public interface Authenticator >>>>> { >>>>> public enum AuthenticationStatus {SUCCESS, FAILURE, DEFERRED} >>>>> >>>>> void authenticate(); >>>>> >>>>> void postAuthenticate(); >>>>> >>>>> AuthenticationStatus getStatus(); >>>>> >>>>> User getUser(); >>>>> >>>>> Set<Role> getRoleMemberships(); >>>>> >>>>> Set<Group> getGroupMemberships(); >>>>> } >>>>> >>>>> The AuthenticationStatus enum / getStatus() method are used to indicate >>>>> the current state of authentication. Once the authenticate() method has >>>>> been invoked and completed, in most cases the getStatus() method will >>>>> return a result of SUCCESS or FAILURE, indicating whether the >>>>> authentication process was successful or not. In more complex forms of >>>>> Authentication (such as OpenID) the getStatus() method will return an >>>>> immediate result of DEFERRED, indicating that the authentication >>>>> process is >>>>> still underway. >>>>> >>>>> The postAuthenticate() method in most cases will do nothing, however is >>>>> provided once again for more complex authentication scenarios. It >>>>> allows >>>>> the authenticator to perform finalisation of the authentication process, >>>>> for example in cases where authentication is asynchronous. >>>>> >>>>> The last three methods are responsible for providing the user's state to >>>>> the Identity bean. The User instance, along with their role and group >>>>> privileges will be used to populate Identity for the duration of the >>>>> user's >>>>> session. >>>>> >>>>> I propose that we provide the following Authenticator implementations >>>>> out >>>>> of the box: >>>>> >>>>> 1. IdmAuthenticator - Performs user authentication against the Identity >>>>> Management API >>>>> >>>>> 2. JaasAuthenticator - Allows the user to use an existing JAAS >>>>> configuration to authenticate with >>>>> >>>>> 3. OpenIdAuthenticator - Performs authentication using an OpenID >>>>> provider, such as Google >>>>> >>>>> We can easily extend this list in the future. I furthermore propose the >>>>> following logic to select which Authenticator will be used when invoking >>>>> Identity.login(), in descending order of priority: >>>>> >>>>> 1. If the developer has configured a specific Authenticator >>>>> implementation to use by setting Identity.authenticatorClass, then use >>>>> that >>>>> Authenticator. >>>>> >>>>> 2. If the user has selected a specific authenticator to use by name, by >>>>> setting Identity.authenticatorName, then lookup the Authenticator with >>>>> that >>>>> name and use it. This use case is useful for when you wish to provide >>>>> multiple authentication alternatives to the user. For example, >>>>> Sourceforge >>>>> allows a user to either log in using their Sourceforge username and >>>>> password, or with their OpenID account. >>>>> >>>>> 3. If the developer has provided their own Authenticator implementation, >>>>> then use it to authenticate. This is the simplest use case and allows >>>>> the >>>>> developer to control the authentication process themselves. >>>>> >>>>> 4. If the Identity Management API has been configured and identity >>>>> management services are available, then use IdmAuthenticator to >>>>> authenticate the user against the configured identity store. >>>>> >>>>> This authenticator selection process provides sensible defaults, while >>>>> allowing the developer to easily control and/or override the >>>>> authenticator >>>>> configuration. >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>
