Return-Path: X-Original-To: apmail-incubator-deltaspike-dev-archive@minotaur.apache.org Delivered-To: apmail-incubator-deltaspike-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 769BB9FB1 for ; Wed, 29 Feb 2012 21:26:24 +0000 (UTC) Received: (qmail 27298 invoked by uid 500); 29 Feb 2012 21:26:24 -0000 Delivered-To: apmail-incubator-deltaspike-dev-archive@incubator.apache.org Received: (qmail 27269 invoked by uid 500); 29 Feb 2012 21:26:24 -0000 Mailing-List: contact deltaspike-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: deltaspike-dev@incubator.apache.org Delivered-To: mailing list deltaspike-dev@incubator.apache.org Received: (qmail 27185 invoked by uid 99); 29 Feb 2012 21:26:24 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Feb 2012 21:26:24 +0000 X-ASF-Spam-Status: No, hits=-5.0 required=5.0 tests=RCVD_IN_DNSWL_HI,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of sbryzak@redhat.com designates 209.132.183.28 as permitted sender) Received: from [209.132.183.28] (HELO mx1.redhat.com) (209.132.183.28) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Feb 2012 21:26:18 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q1TLPuqa031523 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Feb 2012 16:25:56 -0500 Received: from [10.11.10.215] (vpn-10-215.rdu.redhat.com [10.11.10.215]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q1TLPp71018285; Wed, 29 Feb 2012 16:25:53 -0500 Message-ID: <4F4E97DE.4070601@redhat.com> Date: Thu, 01 Mar 2012 07:25:50 +1000 From: Shane Bryzak User-Agent: Mozilla/5.0 (X11; Linux i686; rv:9.0) Gecko/20111222 Thunderbird/9.0 MIME-Version: 1.0 To: deltaspike-dev@incubator.apache.org CC: Gerhard Petracek Subject: Re: [DISCUSS] DELTASPIKE-76 Authentication API References: <4F4D5211.2030907@redhat.com> <4F4D5424.2050307@redhat.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Virus-Checked: Checked by ClamAV on apache.org 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 attributes = new LinkedList(); 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 > >> 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 getRoleMemberships(); >>> >>> Set 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. >>> >>> >>> >>> >>>