@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. >>>> >>>> >>>> >>>> >>>> >>>> >
