[DISCUSS] DELTASPIKE-76 Authentication API

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

[DISCUSS] DELTASPIKE-76 Authentication API

Shane Bryzak-2
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.




Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Shane Bryzak-2
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.
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Gerhard Petracek
Administrator
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.

@ AuthenticationStatus.DEFERRED and #postAuthenticate:
it would be great, if you can provide a source-code example which shows the
usage.

@get*Memberships
currently i'm thinking about the dis-/advantages of moving those methods to
User (or something like AuthenticatedUser)

regards,
gerhard



2012/2/28 Shane Bryzak <[hidden email]>

> 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.
>>
>>
>>
>>
>>
>
Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Shane Bryzak-2
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<[hidden email]>
>
>> 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.
>>>
>>>
>>>
>>>
>>>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Gerhard Petracek
Administrator
@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 <[hidden email]>

> 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<[hidden email]>
>>
>>  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.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>
Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Jason Porter
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 <[hidden email]> 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 <[hidden email]>
>
>> 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<[hidden email]>
>>>
>>> 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.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>
Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Boleslaw Dawidowicz
In reply to this post by Shane Bryzak-2

On Feb 29, 2012, at 10:25 PM, Shane Bryzak wrote:

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

I support Shane on this. It could lead to a lot of complications and not sure what would be benefits of having this.

Bolek

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Shane Bryzak-2
Ok I've been thinking about this over the last few days (and come up
with a number of solutions I wasn't happy with), however there is one
idea in particular I quite like.  To take a step back for a moment
though, the reason we were contemplating adding the extra state to the
User class was so that we could convey that state between the
authentication process and the user's Identity.  This state (which
represents the user's group and role privileges) is then used for the
duration of the user's session whenever the Identity.hasRole() or
Identity.hasGroup() methods are invoked, to control the user's access to
the restricted operations of the application and so forth.

Until now I believed that the challenge we had was how we integrate the
mechanism for this state transfer with the Identity Management API,
however I have now come to the conclusion that it should be integrated
with the Identity Management API itself, with the IdentityManager bean
managing all privilege assignment, both persistent and temporary.  With
that in mind, I'd like to propose we add the following methods to the
IdentityManager interface:

grantRoleForSession(User user, Role role);
grantGroupForSession(User user, Group group);

We can see these methods in action by building on top of the
SimpleAuthenticator example we saw earlier to now include role and group
assignment:

public class SimpleAuthenticator extends BaseAuthenticator implements
Authenticator
{
     @Inject
     Credentials credentials;

     @Inject
     IdentityManager idm;

     public void authenticate()
    {
         if ("demo".equals(credentials.getUsername()) &&
                 credentials.getCredential() instanceof
PasswordCredential &&
                 "demo".equals(((PasswordCredential)
credentials.getCredential()).getValue()))
         {
             setUser(new SimpleUser("demo"));
             idm.grantRoleForSession(getUser(), new SimpleRole("ADMIN",
"USERS"));
             idm.grantGroupForSession(getUser(), new SimpleGroup("USERS"));
             setStatus(AuthenticationStatus.SUCCESS);
         }
         else
         {
             setStatus(AuthenticationStatus.FAILURE);
         }
     }
}

This solution is clean, keeps the User class free of additional state
and consolidates all user privilege management in one place.  It also
opens up a number of exciting possibilities, one such example being
session management (manipulation of user privileges at runtime) and
makes much easier to implement features such as more complex role
assignment such as temporal based (i.e. grant role X to user Y between
the hours of 8am and 5pm server time) or expiring (grant role X to user
Y for exactly 30 days).  It also means auditing can be performed all in
one class.



On 02/03/12 06:41, Boleslaw Dawidowicz wrote:
> On Feb 29, 2012, at 10:25 PM, Shane Bryzak wrote:
>
>>> 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.
> I support Shane on this. It could lead to a lot of complications and not sure what would be benefits of having this.
>
> Bolek
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Gerhard Petracek
Administrator
hi shane,

imo it's better than the first draft -> +1 for committing it.

regards,
gerhard



2012/3/5 Shane Bryzak <[hidden email]>

> Ok I've been thinking about this over the last few days (and come up with
> a number of solutions I wasn't happy with), however there is one idea in
> particular I quite like.  To take a step back for a moment though, the
> reason we were contemplating adding the extra state to the User class was
> so that we could convey that state between the authentication process and
> the user's Identity.  This state (which represents the user's group and
> role privileges) is then used for the duration of the user's session
> whenever the Identity.hasRole() or Identity.hasGroup() methods are invoked,
> to control the user's access to the restricted operations of the
> application and so forth.
>
> Until now I believed that the challenge we had was how we integrate the
> mechanism for this state transfer with the Identity Management API, however
> I have now come to the conclusion that it should be integrated with the
> Identity Management API itself, with the IdentityManager bean managing all
> privilege assignment, both persistent and temporary.  With that in mind,
> I'd like to propose we add the following methods to the IdentityManager
> interface:
>
> grantRoleForSession(User user, Role role);
> grantGroupForSession(User user, Group group);
>
> We can see these methods in action by building on top of the
> SimpleAuthenticator example we saw earlier to now include role and group
> assignment:
>
>
> public class SimpleAuthenticator extends BaseAuthenticator implements
> Authenticator
> {
>    @Inject
>    Credentials credentials;
>
>    @Inject
>    IdentityManager idm;
>
>    public void authenticate()
>   {
>
>        if ("demo".equals(credentials.**getUsername()) &&
>                credentials.getCredential() instanceof PasswordCredential &&
>                "demo".equals(((**PasswordCredential)
> credentials.getCredential()).**getValue()))
>        {
>            setUser(new SimpleUser("demo"));
>            idm.grantRoleForSession(**getUser(), new SimpleRole("ADMIN",
> "USERS"));
>            idm.grantGroupForSession(**getUser(), new
> SimpleGroup("USERS"));
>            setStatus(**AuthenticationStatus.SUCCESS);
>        }
>        else
>        {
>            setStatus(**AuthenticationStatus.FAILURE);
>        }
>    }
> }
>
> This solution is clean, keeps the User class free of additional state and
> consolidates all user privilege management in one place.  It also opens up
> a number of exciting possibilities, one such example being session
> management (manipulation of user privileges at runtime) and makes much
> easier to implement features such as more complex role assignment such as
> temporal based (i.e. grant role X to user Y between the hours of 8am and
> 5pm server time) or expiring (grant role X to user Y for exactly 30 days).
>  It also means auditing can be performed all in one class.
>
>
>
>
> On 02/03/12 06:41, Boleslaw Dawidowicz wrote:
>
>> On Feb 29, 2012, at 10:25 PM, Shane Bryzak wrote:
>>
>>  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.
>>>
>> I support Shane on this. It could lead to a lot of complications and not
>> sure what would be benefits of having this.
>>
>> Bolek
>>
>>
>
Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Boleslaw Dawidowicz
In reply to this post by Shane Bryzak-2
I like this idea. However my concern is that it will need clear distinction in the IDM API between all roles (including session ones) and persisted roles (identity store level).

Bolek

On Mar 5, 2012, at 11:45 PM, Shane Bryzak wrote:

> Ok I've been thinking about this over the last few days (and come up with a number of solutions I wasn't happy with), however there is one idea in particular I quite like.  To take a step back for a moment though, the reason we were contemplating adding the extra state to the User class was so that we could convey that state between the authentication process and the user's Identity.  This state (which represents the user's group and role privileges) is then used for the duration of the user's session whenever the Identity.hasRole() or Identity.hasGroup() methods are invoked, to control the user's access to the restricted operations of the application and so forth.
>
> Until now I believed that the challenge we had was how we integrate the mechanism for this state transfer with the Identity Management API, however I have now come to the conclusion that it should be integrated with the Identity Management API itself, with the IdentityManager bean managing all privilege assignment, both persistent and temporary.  With that in mind, I'd like to propose we add the following methods to the IdentityManager interface:
>
> grantRoleForSession(User user, Role role);
> grantGroupForSession(User user, Group group);
>
> We can see these methods in action by building on top of the SimpleAuthenticator example we saw earlier to now include role and group assignment:
>
> public class SimpleAuthenticator extends BaseAuthenticator implements Authenticator
> {
>    @Inject
>    Credentials credentials;
>
>    @Inject
>    IdentityManager idm;
>
>    public void authenticate()
>   {
>        if ("demo".equals(credentials.getUsername()) &&
>                credentials.getCredential() instanceof PasswordCredential &&
>                "demo".equals(((PasswordCredential) credentials.getCredential()).getValue()))
>        {
>            setUser(new SimpleUser("demo"));
>            idm.grantRoleForSession(getUser(), new SimpleRole("ADMIN", "USERS"));
>            idm.grantGroupForSession(getUser(), new SimpleGroup("USERS"));
>            setStatus(AuthenticationStatus.SUCCESS);
>        }
>        else
>        {
>            setStatus(AuthenticationStatus.FAILURE);
>        }
>    }
> }
>
> This solution is clean, keeps the User class free of additional state and consolidates all user privilege management in one place.  It also opens up a number of exciting possibilities, one such example being session management (manipulation of user privileges at runtime) and makes much easier to implement features such as more complex role assignment such as temporal based (i.e. grant role X to user Y between the hours of 8am and 5pm server time) or expiring (grant role X to user Y for exactly 30 days).  It also means auditing can be performed all in one class.
>
>
>
> On 02/03/12 06:41, Boleslaw Dawidowicz wrote:
>> On Feb 29, 2012, at 10:25 PM, Shane Bryzak wrote:
>>
>>>> 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.
>> I support Shane on this. It could lead to a lot of complications and not sure what would be benefits of having this.
>>
>> Bolek
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Paul Dijou
Hi,

I still think the Authenticator should only authenticate and doesn't have
to know anything about how the application handle the notion of User, Group
and Role. Authenticator should take Credentials in entry, knows where to
check (database, ldap, ...) and return the result (success, fail, on going,
...). That's all. So the Authenticator interface shouldn't have a
set/getUser() in my opinion. This method could be on the IdentityManager.

I'm saying that because I think about a generic authenticator used by
several applications connected to a central LDAP for example but each one
having it's own system around User/Group/Role.

In practice, if an implementation of the Authenticator wants to modify
directly the User, I'm fine with that, but the API should be as minimalist
as possible.

Regards,

Paul.

2012/3/6 Boleslaw Dawidowicz <[hidden email]>

> I like this idea. However my concern is that it will need clear
> distinction in the IDM API between all roles (including session ones) and
> persisted roles (identity store level).
>
> Bolek
>
> On Mar 5, 2012, at 11:45 PM, Shane Bryzak wrote:
>
> > Ok I've been thinking about this over the last few days (and come up
> with a number of solutions I wasn't happy with), however there is one idea
> in particular I quite like.  To take a step back for a moment though, the
> reason we were contemplating adding the extra state to the User class was
> so that we could convey that state between the authentication process and
> the user's Identity.  This state (which represents the user's group and
> role privileges) is then used for the duration of the user's session
> whenever the Identity.hasRole() or Identity.hasGroup() methods are invoked,
> to control the user's access to the restricted operations of the
> application and so forth.
> >
> > Until now I believed that the challenge we had was how we integrate the
> mechanism for this state transfer with the Identity Management API, however
> I have now come to the conclusion that it should be integrated with the
> Identity Management API itself, with the IdentityManager bean managing all
> privilege assignment, both persistent and temporary.  With that in mind,
> I'd like to propose we add the following methods to the IdentityManager
> interface:
> >
> > grantRoleForSession(User user, Role role);
> > grantGroupForSession(User user, Group group);
> >
> > We can see these methods in action by building on top of the
> SimpleAuthenticator example we saw earlier to now include role and group
> assignment:
> >
> > public class SimpleAuthenticator extends BaseAuthenticator implements
> Authenticator
> > {
> >    @Inject
> >    Credentials credentials;
> >
> >    @Inject
> >    IdentityManager idm;
> >
> >    public void authenticate()
> >   {
> >        if ("demo".equals(credentials.getUsername()) &&
> >                credentials.getCredential() instanceof PasswordCredential
> &&
> >                "demo".equals(((PasswordCredential)
> credentials.getCredential()).getValue()))
> >        {
> >            setUser(new SimpleUser("demo"));
> >            idm.grantRoleForSession(getUser(), new SimpleRole("ADMIN",
> "USERS"));
> >            idm.grantGroupForSession(getUser(), new SimpleGroup("USERS"));
> >            setStatus(AuthenticationStatus.SUCCESS);
> >        }
> >        else
> >        {
> >            setStatus(AuthenticationStatus.FAILURE);
> >        }
> >    }
> > }
> >
> > This solution is clean, keeps the User class free of additional state
> and consolidates all user privilege management in one place.  It also opens
> up a number of exciting possibilities, one such example being session
> management (manipulation of user privileges at runtime) and makes much
> easier to implement features such as more complex role assignment such as
> temporal based (i.e. grant role X to user Y between the hours of 8am and
> 5pm server time) or expiring (grant role X to user Y for exactly 30 days).
>  It also means auditing can be performed all in one class.
> >
> >
> >
> > On 02/03/12 06:41, Boleslaw Dawidowicz wrote:
> >> On Feb 29, 2012, at 10:25 PM, Shane Bryzak wrote:
> >>
> >>>> 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.
> >> I support Shane on this. It could lead to a lot of complications and
> not sure what would be benefits of having this.
> >>
> >> Bolek
> >>
> >
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Gerhard Petracek
Administrator
hi paul,

we already had a short (irc) discussion about it and imo we have the same
(or at least a similar) opinion about it.

regards,
gerhard



2012/3/7 Paul Dijou <[hidden email]>

> Hi,
>
> I still think the Authenticator should only authenticate and doesn't have
> to know anything about how the application handle the notion of User, Group
> and Role. Authenticator should take Credentials in entry, knows where to
> check (database, ldap, ...) and return the result (success, fail, on going,
> ...). That's all. So the Authenticator interface shouldn't have a
> set/getUser() in my opinion. This method could be on the IdentityManager.
>
> I'm saying that because I think about a generic authenticator used by
> several applications connected to a central LDAP for example but each one
> having it's own system around User/Group/Role.
>
> In practice, if an implementation of the Authenticator wants to modify
> directly the User, I'm fine with that, but the API should be as minimalist
> as possible.
>
> Regards,
>
> Paul.
>
> 2012/3/6 Boleslaw Dawidowicz <[hidden email]>
>
> > I like this idea. However my concern is that it will need clear
> > distinction in the IDM API between all roles (including session ones) and
> > persisted roles (identity store level).
> >
> > Bolek
> >
> > On Mar 5, 2012, at 11:45 PM, Shane Bryzak wrote:
> >
> > > Ok I've been thinking about this over the last few days (and come up
> > with a number of solutions I wasn't happy with), however there is one
> idea
> > in particular I quite like.  To take a step back for a moment though, the
> > reason we were contemplating adding the extra state to the User class was
> > so that we could convey that state between the authentication process and
> > the user's Identity.  This state (which represents the user's group and
> > role privileges) is then used for the duration of the user's session
> > whenever the Identity.hasRole() or Identity.hasGroup() methods are
> invoked,
> > to control the user's access to the restricted operations of the
> > application and so forth.
> > >
> > > Until now I believed that the challenge we had was how we integrate the
> > mechanism for this state transfer with the Identity Management API,
> however
> > I have now come to the conclusion that it should be integrated with the
> > Identity Management API itself, with the IdentityManager bean managing
> all
> > privilege assignment, both persistent and temporary.  With that in mind,
> > I'd like to propose we add the following methods to the IdentityManager
> > interface:
> > >
> > > grantRoleForSession(User user, Role role);
> > > grantGroupForSession(User user, Group group);
> > >
> > > We can see these methods in action by building on top of the
> > SimpleAuthenticator example we saw earlier to now include role and group
> > assignment:
> > >
> > > public class SimpleAuthenticator extends BaseAuthenticator implements
> > Authenticator
> > > {
> > >    @Inject
> > >    Credentials credentials;
> > >
> > >    @Inject
> > >    IdentityManager idm;
> > >
> > >    public void authenticate()
> > >   {
> > >        if ("demo".equals(credentials.getUsername()) &&
> > >                credentials.getCredential() instanceof
> PasswordCredential
> > &&
> > >                "demo".equals(((PasswordCredential)
> > credentials.getCredential()).getValue()))
> > >        {
> > >            setUser(new SimpleUser("demo"));
> > >            idm.grantRoleForSession(getUser(), new SimpleRole("ADMIN",
> > "USERS"));
> > >            idm.grantGroupForSession(getUser(), new
> SimpleGroup("USERS"));
> > >            setStatus(AuthenticationStatus.SUCCESS);
> > >        }
> > >        else
> > >        {
> > >            setStatus(AuthenticationStatus.FAILURE);
> > >        }
> > >    }
> > > }
> > >
> > > This solution is clean, keeps the User class free of additional state
> > and consolidates all user privilege management in one place.  It also
> opens
> > up a number of exciting possibilities, one such example being session
> > management (manipulation of user privileges at runtime) and makes much
> > easier to implement features such as more complex role assignment such as
> > temporal based (i.e. grant role X to user Y between the hours of 8am and
> > 5pm server time) or expiring (grant role X to user Y for exactly 30
> days).
> >  It also means auditing can be performed all in one class.
> > >
> > >
> > >
> > > On 02/03/12 06:41, Boleslaw Dawidowicz wrote:
> > >> On Feb 29, 2012, at 10:25 PM, Shane Bryzak wrote:
> > >>
> > >>>> 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.
> > >> I support Shane on this. It could lead to a lot of complications and
> > not sure what would be benefits of having this.
> > >>
> > >> Bolek
> > >>
> > >
> >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-76 Authentication API

Shane Bryzak-2
In reply to this post by Paul Dijou
The getRoleMemberships() / getGroupMemberships() methods have now been
removed, and if the Authenticator wishes to still grant these privileges
for the user's session it can simply inject the IdentityManager and set
them there, leaving the Authenticator with just a few concise methods
related to the authentication process only.  The getUser() method is
still required as Identity needs to know who the actual user is, but the
User object contains no state pertaining to the user's privileges.


On 07/03/12 23:31, Paul Dijou wrote:

> Hi,
>
> I still think the Authenticator should only authenticate and doesn't have
> to know anything about how the application handle the notion of User, Group
> and Role. Authenticator should take Credentials in entry, knows where to
> check (database, ldap, ...) and return the result (success, fail, on going,
> ...). That's all. So the Authenticator interface shouldn't have a
> set/getUser() in my opinion. This method could be on the IdentityManager.
>
> I'm saying that because I think about a generic authenticator used by
> several applications connected to a central LDAP for example but each one
> having it's own system around User/Group/Role.
>
> In practice, if an implementation of the Authenticator wants to modify
> directly the User, I'm fine with that, but the API should be as minimalist
> as possible.
>
> Regards,
>
> Paul.
>
> 2012/3/6 Boleslaw Dawidowicz<[hidden email]>
>
>> I like this idea. However my concern is that it will need clear
>> distinction in the IDM API between all roles (including session ones) and
>> persisted roles (identity store level).
>>
>> Bolek
>>
>> On Mar 5, 2012, at 11:45 PM, Shane Bryzak wrote:
>>
>>> Ok I've been thinking about this over the last few days (and come up
>> with a number of solutions I wasn't happy with), however there is one idea
>> in particular I quite like.  To take a step back for a moment though, the
>> reason we were contemplating adding the extra state to the User class was
>> so that we could convey that state between the authentication process and
>> the user's Identity.  This state (which represents the user's group and
>> role privileges) is then used for the duration of the user's session
>> whenever the Identity.hasRole() or Identity.hasGroup() methods are invoked,
>> to control the user's access to the restricted operations of the
>> application and so forth.
>>> Until now I believed that the challenge we had was how we integrate the
>> mechanism for this state transfer with the Identity Management API, however
>> I have now come to the conclusion that it should be integrated with the
>> Identity Management API itself, with the IdentityManager bean managing all
>> privilege assignment, both persistent and temporary.  With that in mind,
>> I'd like to propose we add the following methods to the IdentityManager
>> interface:
>>> grantRoleForSession(User user, Role role);
>>> grantGroupForSession(User user, Group group);
>>>
>>> We can see these methods in action by building on top of the
>> SimpleAuthenticator example we saw earlier to now include role and group
>> assignment:
>>> public class SimpleAuthenticator extends BaseAuthenticator implements
>> Authenticator
>>> {
>>>     @Inject
>>>     Credentials credentials;
>>>
>>>     @Inject
>>>     IdentityManager idm;
>>>
>>>     public void authenticate()
>>>    {
>>>         if ("demo".equals(credentials.getUsername())&&
>>>                 credentials.getCredential() instanceof PasswordCredential
>> &&
>>>                 "demo".equals(((PasswordCredential)
>> credentials.getCredential()).getValue()))
>>>         {
>>>             setUser(new SimpleUser("demo"));
>>>             idm.grantRoleForSession(getUser(), new SimpleRole("ADMIN",
>> "USERS"));
>>>             idm.grantGroupForSession(getUser(), new SimpleGroup("USERS"));
>>>             setStatus(AuthenticationStatus.SUCCESS);
>>>         }
>>>         else
>>>         {
>>>             setStatus(AuthenticationStatus.FAILURE);
>>>         }
>>>     }
>>> }
>>>
>>> This solution is clean, keeps the User class free of additional state
>> and consolidates all user privilege management in one place.  It also opens
>> up a number of exciting possibilities, one such example being session
>> management (manipulation of user privileges at runtime) and makes much
>> easier to implement features such as more complex role assignment such as
>> temporal based (i.e. grant role X to user Y between the hours of 8am and
>> 5pm server time) or expiring (grant role X to user Y for exactly 30 days).
>>   It also means auditing can be performed all in one class.
>>>
>>>
>>> On 02/03/12 06:41, Boleslaw Dawidowicz wrote:
>>>> On Feb 29, 2012, at 10:25 PM, Shane Bryzak wrote:
>>>>
>>>>>> 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.
>>>> I support Shane on this. It could lead to a lot of complications and
>> not sure what would be benefits of having this.
>>>> Bolek
>>>>
>>