...
- @Secured
- @SecurityBindingType
- AccessDecisionVoter
- SecurityStrategy
Agreed API
...
and SPI
...
of Part 1
Feature | Comments | Objections | Discussion finished |
---|---|---|---|
Login via Username/Password |
|
|
|
Password-Hash-Service |
|
|
|
Logout |
|
|
|
Authentication API and SPI | Credentials vs Credential (one of it needs a better name) |
|
|
Duration of a valid authentication | ExpirationEvaluator SPI |
|
|
Basic User/Identity API |
|
|
|
Part 2
Feature | Comments | Objections | Discussion finished |
---|---|---|---|
Object level permission |
|
|
|
Basic Roles and groups API | optional type-safe (-> static) groups (and roles) |
|
|
@SecurityMethodBinding |
|
|
|
Super-users |
|
|
|
User/Identity management |
|
|
|
Group management | optional support for typ-safe groups/group-types |
|
|
Part 3
Feature | Comments | Objections | Discussion finished |
---|---|---|---|
Support for deputies (see Impersonalization) |
|
|
|
Privileges concept |
|
|
|
Grant or revoke permissions |
|
|
|
UI SPI (Component based authorization) | add optional type-safe authorization; integration with JSF |
|
|
Permissions of resources | Merge with CODI view-configs,... |
|
|
Persistence SPI | integration with JPA |
|
|
Identity Store SPI |
|
|
|
Query API |
|
|
|
Application roles |
|
|
|
Part 4
Feature | Comments | Objections | Discussion finished |
---|---|---|---|
Support of alternative authentication concepts | Extend the Authentication SPI |
|
|
Integration with authentication concepts of (application-) servers | Extend the Authentication SPI |
|
|
Personalization |
|
|
|
Alternatives for roles/groups |
|
|
|
Permission for external applications |
|
|
|
Ongoing discussions
API
1. draft: http://s.apache.org/Vyg
Identity
Session scoped result of the authentication process.
commit: 1a2c7ffd0d0a1ad3dea34515a54958f0a6ce2932
API
Identity
Session scoped result of the authentication process.
Code Block |
---|
public interface Identity extends Serializable
{
public enum AuthenticationResult
{
SUCCESS, FAILED
}
AuthenticationResult login();
void logout();
boolean isLoggedIn();
User getUser();
}
|
User
Depending on further use-cases it can be refactored to an interface
The id is an unique identifier for an user. It isn't defined if it is an internal identifier or an identifier known by the user (like the user-name).
If users login e.g. via their e-mail address, it's possible to lookup an internal id in a custom implementation of LoginCredential
or a bean which is in between (and LoginCredential
doesn't get called directly in the 2nd case).
Code Block |
---|
@Typed()
public class User implements Serializable
{
private static final long serialVersionUID = -2234530384311026364L;
private final String id;
public User(String id)
{
this.id = id;
}
public String getId()
{
return id;
}
}
|
Credential
Credential is a holder for the "secret key" like a password.
Code Block |
---|
public interface Credential<T>
{
T getValue();
}
|
LoginCredential (former Credentials)
Request scoped holder for the authentication process.
TODO we need a better name for it
- LoginCredentialState
- LoginCredentialHolder
- LoginCredentialProvider
Code Block |
---|
public interface LoginCredential
{
String getUserId();
void setUserId(String userId |
Code Block |
public interface Identity extends Serializable { public enum AuthenticationResult { success, failed, exception //TODO discuss upper- or lower-case } boolean isLoggedIn(); UserCredential getUsergetCredential(); AuthenticationResultvoid loginsetCredential(Credential credential); void logoutinvalidate(); } |
...
Events
- LoggedInEvent
- LoginFailedEvent
- AlreadyLoggedInEvent
- PreLoggedOutEvent
- PostLoggedOutEvent
- PreAuthenticateEvent
- PostAuthenticateEvent
SPI
AuthenticatorSelector
Request scoped bean used to find the current Authenticator
for the authentication process - e.g. to provide different login-types used by the same client (e.g. a component in an UI).
TODO discuss default (internal) Authenticator if there is no custom implementation.
Code Block |
---|
public interface AuthenticatorSelector |
Code Block |
@Typed() public class User implements Serializable { privateClass<? staticextends final long serialVersionUID = -2234530384311026364LAuthenticator> getAuthenticatorClass(); private String idvoid setAuthenticatorClass(Class<? extends Authenticator> authenticatorClass); publicString UsergetAuthenticatorName(); { } public Uservoid setAuthenticatorName(String idauthenticatorName); { this.id = id; } public String getId()Authenticator getSelectedAuthenticator(); } |
Authenticator
Called by Identity
and performs the final authentication based on the information in LoginCredential
.
Code Block |
---|
public interface Authenticator { public enum AuthenticationStatus { SUCCESS, returnFAILURE, id;DEFERRED } public void setIdauthenticate(String id); { void postAuthenticate(); this.id =AuthenticationStatus idgetStatus(); }User getUser(); } |
Credential
Code Blockcode |
---|
public interface Credential<T> abstract class BaseAuthenticator implements Authenticator { T getValue()private AuthenticationStatus status; } |
LoginCredential (former Credentials)
Request scoped holder for the authentication process.
Code Block |
---|
public interface LoginCredential { public AuthenticationStatus getStatus() { Userreturn getUser()status; Credential getCredential();} protected void setCredentialsetStatus(CredentialAuthenticationStatus credentialstatus); void invalidate(); } |
AuthenticatorSelector
Code Block |
---|
public interface AuthenticatorSelector { { Class<? extendsthis.status Authenticator>= getAuthenticatorClass()status; void setAuthenticatorClass(Class<? extends Authenticator> authenticatorClass);} public Stringvoid getAuthenticatorNamepostAuthenticate(); { void setAuthenticatorName(String authenticatorName); // No-op, override Authenticator getSelectedAuthenticator();if any post-authentication processing is required. } } |
...
Usage
Simple Login/Logout by Example (Java-SE)
Code Block |
---|
@ApplicationScoped public interfaceclass AuthenticatorLoginBean { public@Inject enum AuthenticationStatus private LoginCredential loginCredential; { @Inject private SUCCESS,Identity identity; public boolean login(String userName, final FAILURE,String password) { DEFERRED } void authenticate(); this.loginCredential.setUserId(userName); void postAuthenticate(); AuthenticationStatus getStatus(); this.loginCredential.setCredential(new Credential<String>() { User getUser(); } |
Code Block |
public abstract class BaseAuthenticator implements Authenticator { @Override private AuthenticationStatus status; public AuthenticationStatusString getStatusgetValue() { return{ status; } return password; } protected void setStatus(AuthenticationStatus status}); { this.identity.login(); return this.status = status; } public void postAuthenticate() { // No-op, override if any post-authentication processing is required. } } identity.isLoggedIn(); } public boolean logout() { this.identity.logout(); return !this.identity.isLoggedIn(); } } public class CustomBean { @Inject private Identity identity; @Inject private LoginBean loginBean; public void execute() { if(this.loginBean.login("spike", "apache")) { User user = this.identity.getUser(); //... } else { //... } } } |
Under discussion
API/SPI
Packages
- */authentication
- */authentication/events
- */authorization
- */authorization/annotation
- */credential or */authentication/credential
Part 1
Feature | Comments | Objections | Discussion finished |
---|---|---|---|
Login via Username/Password |
|
| |
Logout |
|
| |
Authentication API and SPI | Credentials vs Credential (one of it needs a better name) |
| |
Basic User/Identity API |
|
| |
Duration of a valid authentication | ExpirationEvaluator SPI |
|
|
Part 2
Feature | Comments | Objections | Discussion finished |
---|---|---|---|
Object level permission |
|
|
|
Grant or revoke permissions |
|
|
|
Basic Roles and groups API | optional type-safe (-> static) groups (and roles) |
|
|
@SecurityMethodBinding |
|
|
|
Super-users |
|
|
|
User/Identity management |
|
|
|
Password-Hash-Service |
|
|
|
Group management | optional support for typ-safe groups/group-types |
|
|
Part 3
Feature | Comments | Objections | Discussion finished |
---|---|---|---|
Support for deputies (see Impersonalization) |
|
|
|
Privileges concept |
|
|
|
UI SPI (Component based authorization) | add optional type-safe authorization; integration with JSF |
|
|
Permissions of resources | Merge with CODI view-configs,... |
|
|
Persistence SPI | integration with JPA |
|
|
Identity Store SPI |
|
|
|
Query API |
|
|
|
Application roles |
|
|
|
Part 4
Feature | Comments | Objections | Discussion finished |
---|---|---|---|
Support of alternative authentication concepts | Extend the Authentication SPI |
|
|
Integration with authentication concepts of (application-) servers | Extend the Authentication SPI |
|
|
Personalization |
|
|
|
Alternatives for roles/groups |
|
|
|
Permission for external applications |
|
|
|
Use-cases
Authentication
Scenario
...
Example JSF code:
Code Block | ||||
---|---|---|---|---|
| ||||
Username: <h:inputText value="#{credentials.username}"/>
Password: <h:inputSecret id="password" value="#{credentials.password}"/>
<h:commandButton value="LOGIN" action="#{identity.login}"/>
|
...
Code Block |
---|
public class SimpleAuthenticator extends BaseAuthenticator implements Authenticator { @Inject Credentials credentials; @Override 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); } } } |
Scenario
It should be possible to provide an optional password service to create a password-hash based on the given password which will be stored instead of the real password.
Maybe there should be different default implementations (provided via qualifiers).
...
Code Block |
---|
Group itsec = identityManager.createGroup(“itsec”, “/organization/engineering/security”);
itsec.addRole(“manager”, “johnDoe”);
Group hr = identityManager.createGroup(“hr”, “/organization”);
hr.addRole(“supervisor”, “aliceDoe”);
hr.addRole(“headhunter”, “chrisDoe”);
aliceDoe.hasRole(“headhunter”);
List<User> headHunters = identityManager.createUserQuery().setRole(“headhunter”).sort(true).setRange(Range.of(0,50).execute();
|
Scenario
Application needs to expose capabilities to associate authenticated user with specific roles in application context.
...
Code Block |
---|
identityManager.getSupportedFeatures().isUserSortSupported(); identityManager.getSupportedFeatures().isUserQueryPaginationSupported(); |
Events
Scenario
Application developer needs to add specific hooks for common IDM or Security operations
...