107 User Admin Service Specification

107.1 Introduction

OSGi frameworks are often used in places where end users or devices initiate actions. These kinds of actions inevitably create a need for authenticating the initiator. Authenticating can be done in many different ways, including with passwords, one-time token cards, biometrics, and certificates.

Once the initiator is authenticated, it is necessary to verify that this principal is authorized to perform the requested action. This authorization can only be decided by the operator of the OSGi environment, and thus requires administration.

The User Admin service provides this type of functionality. Bundles can use the User Admin service to authenticate an initiator and represent this authentication as an Authorization object. Bundles that execute actions on behalf of this user can use the Authorization object to verify if that user is authorized.

The User Admin service provides authorization based on who runs the code, instead of using the Java code-based permission model. See [1] The Java Security Architecture for JDK 1.2. It performs a role similar to [2] Java Authentication and Authorization Service.

107.1.1 Essentials

  • Authentication - A large number of authentication schemes already exist, and more will be developed. The User Admin service must be flexible enough to adapt to the many different authentication schemes that can be run on a computer system.

  • Authorization - All bundles should use the User Admin service to authenticate users and to find out if those users are authorized. It is therefore paramount that a bundle can find out authorization information with little effort.

  • Security - Detailed security, based on the Framework security model, is needed to provide safe access to the User Admin service. It should allow limited access to the credentials and other properties.

  • Extensibility - Other bundles should be able to build on the User Admin service. It should be possible to examine the information from this service and get real-time notifications of changes.

  • Properties - The User Admin service must maintain a persistent database of users. It must be possible to use this database to hold more information about this user.

  • Administration - Administering authorizations for each possible action and initiator is time-consuming and error-prone. It is therefore necessary to have mechanisms to group end users and make it simple to assign authorizations to all members of a group at one time.

107.1.2 Entities

This Specification defines the following User Admin service entities:

  • User Admin - This interface manages a database of named roles which can be used for authorization and authentication purposes.

  • Role - This interface exposes the characteristics shared by all roles: a name, a type, and a set of properties.

  • User - This interface (which extends Role) is used to represent any entity which may have credentials associated with it. These credentials can be used to authenticate an initiator.

  • Group - This interface (which extends User) is used to contain an aggregation of named Role objects (Group or User objects).

  • Authorization - This interface encapsulates an authorization context on which bundles can base authorization decisions.

  • User Admin Event - This class is used to represent a role change event.

  • User Admin Listener - This interface provides a listener for events of type UserAdminEvent that can be registered as a service.

  • User Admin Permission - This permission is needed to configure and access the roles managed by a User Admin service.

  • Role.USER_ANYONE - This is a special User object that represents any user, it implies all other User objects. It is also used when a Group is used with only basic members. The Role.USER_ANYONE is then the only required member.

Figure 107.1 User Admin Service, org.osgi.service.useradmin

User Admin Service, org.osgi.service.useradmin

107.1.3 Operation

An Operator uses the User Admin service to define OSGi framework users and configure them with properties, credentials, and roles.

A Role object represents the initiator of a request (human or otherwise). This specification defines two types of roles:

  • User - A User object can be configured with credentials, such as a password, and properties, such as address, telephone number, and so on.

  • Group - A Group object is an aggregation of basic and required roles. Basic and required roles are used in the authorization phase.

An OSGi framework can have several entry points, each of which will be responsible for authenticating incoming requests. An example of an entry point is the Servlet Whiteboard Specification, which delegates authentication of incoming requests to the handleSecurity method of the ServletContextHelper object that was specified when the target servlet or resource of the request was registered.

The OSGi framework entry points should use the information in the User Admin service to authenticate incoming requests, such as a password stored in the private credentials or the use of a certificate.

A bundle can determine if a request for an action is authorized by looking for a Role object that has the name of the requested action.

The bundle may execute the action if the Role object representing the initiator implies the Role object representing the requested action.

For example, an initiator Role object X implies an action Group object A if:

  • X implies at least one of A's basic members, and

  • X implies all of A's required members.

An initiator Role object X implies an action User object A if:

  • A and X are equal.

The Authorization class handles this non-trivial logic. The User Admin service can capture the privileges of an authenticated User object into an Authorization object. The Authorization.hasRole method checks if the authenticate User object has (or implies) a specified action Role object.

For example, in the case of a web application, a server component like a servlet filter can authenticate the initiator and place an Authorization object in the request. The servlet calls the hasRole method on this Authorization object to verify that the initiator has the authority to perform a certain action.

107.2 Authentication

The authentication phase determines if the initiator is actually the one it says it is. Mechanisms to authenticate always need some information related to the user or the OSGi framework to authenticate an external user. This information can consist of the following:

  • A secret known only to the initiator.

  • Knowledge about cards that can generate a unique token.

  • Public information like certificates of trusted signers.

  • Information about the user that can be measured in a trusted way.

  • Other specific information.

107.2.1 Repository

The User Admin service offers a repository of Role objects. Each Role object has a unique name and a set of properties that are readable by anyone, and are changeable when the changer has the UserAdminPermission. Additionally, User objects, a sub-interface of Role, also have a set of private protected properties called credentials. Credentials are an extra set of properties that are used to authenticate users and that are protected by UserAdminPermission.

Properties are accessed with the Role.getProperties() method and credentials with the User.getCredentials() method. Both methods return a Dictionary object containing key/value pairs. The keys are String objects and the values of the Dictionary object are limited to String or byte[ ] objects.

This specification does not define any standard keys for the properties or credentials. The keys depend on the implementation of the authentication mechanism and are not formally defined by OSGi specifications.

The repository can be searched for objects that have a unique property (key/value pair) with the method UserAdmin.getUser(String,String). This makes it easy to find a specific user related to a specific authentication mechanism. For example, a secure card mechanism that generates unique tokens could have a serial number identifying the user. The owner of the card could be found with the method

User owner = useradmin.getUser(
    "secure-card-serial", "132456712-1212" );

If multiple User objects have the same property (key and value), a null is returned.

There is a convenience method to verify that a user has a credential without actually getting the credential. This is the User.hasCredential(String,Object) method.

Access to credentials is protected on a name basis by UserAdminPermission. Because properties can be read by anyone with access to a User object, UserAdminPermission only protects change access to properties.

107.2.2 Basic Authentication

The following example shows a very simple authentication algorithm based on passwords.

The vendor of the authentication bundle uses the property "com.acme.basic-id" to contain the name of a user as it logs in. This property is used to locate the User object in the repository. Next, the credential "com.acme.password" contains the password and is compared to the entered password. If the password is correct, the User object is returned. In all other cases a SecurityException is thrown.

public User authenticate(
        UserAdmin ua, String name, String pwd )
    throws SecurityException {
    User user = ua.getUser("com.acme.basicid",
        username);
    if (user == null)
        throw new SecurityException( "No such user" );

    if (!user.hasCredential("com.acme.password", pwd))
        throw new SecurityException( 
            "Invalid password" );
    return user;
}

107.2.3 Certificates

Authentication based on certificates does not require a shared secret. Instead, a certificate contains a name, a public key, and the signature of one or more signers.

The name in the certificate can be used to locate a User object in the repository. Locating a User object, however, only identifies the initiator and does not authenticate it.

  1. The first step to authenticate the initiator is to verify that it has the private key of the certificate.

  2. Next, the User Admin service must verify that it has a User object with the right property, for example "com.acme.certificate"="Fudd".

  3. The next step is to see if the certificate is signed by a trusted source. The bundle could use a central list of trusted signers and only accept certificates signed by those sources. Alternatively, it could require that the certificate itself is already stored in the repository under a unique key as a byte[] in the credentials.

  4. In any case, once the certificate is verified, the associated User object is authenticated.

107.3 Authorization

The User Admin service authorization architecture is a role-based model. In this model, every action that can be performed by a bundle is associated with a role. Such a role is a Group object (called group from now on) from the User Admin service repository. For example, if a servlet could be used to activate the alarm system, there should be a group named AlarmSystemActivation.

The operator can administrate authorizations by populating the group with User objects (users) and other groups. Groups are used to minimize the amount of administration required. For example, it is easier to create one Administrators group and add administrative roles to it rather than individually administer all users for each role. Such a group requires only one action to remove or add a user as an administrator.

The authorization decision can now be made in two fundamentally different ways:

An initiator could be allowed to carry out an action (represented by a Group object) if it implied any of the Group object's members. For example, the AlarmSystemActivation Group object contains an Administrators and a Family Group object:

    Administrators        = { Elmer, Pepe,Bugs }
    Family                = { Elmer, Pepe, Daffy }

    AlarmSystemActivation = { Administrators, Family}

Any of the four members Elmer, Pepe, Daffy, or Bugs can activate the alarm system.

Alternatively, an initiator could be allowed to perform an action (represented by a Group object) if it implied all the Group object's members. In this case, using the same AlarmSystemActivation group, only Elmer and Pepe would be authorized to activate the alarm system, since Daffy and Bugs are not members of both the Administrators and Family Group objects.

The User Admin service supports a combination of both strategies by defining both a set of basic members (any) and a set of required members (all).

Administrators            = { Elmer, Pepe, Bugs}
Family                    = { Elmer, Pepe, Daffy }

AlarmSystemActivation 
    required              = { Administrators }
    basic                 = { Family }

The difference is made when Role objects are added to the Group object. To add a basic member, use the Group.addMember(Role) method. To add a required member, use the Group.addRequiredMember(Role) method.

Basic members define the set of members that can get access and required members reduce this set by requiring the initiator to imply each required member.

A User object implies a Group object if it implies the following:

  • All of the Group's required members, and

  • At least one of the Group's basic members

A User object always implies itself.

If only required members are used to qualify the implication, then the standard user Role.USER_ANYONE can be obtained from the User Admin service and added to the Group object. This Role object is implied by anybody and therefore does not affect the required members.

107.3.1 The Authorization Object

The complexity of authorization is hidden in an Authorization class. Normally, the authenticator should retrieve an Authorization object from the User Admin service by passing the authenticated User object as an argument. This Authorization object is then passed to the bundle that performs the action. This bundle checks the authorization with the Authorization.hasRole(String) method. The performing bundle must pass the name of the action as an argument. The Authorization object checks whether the authenticated user implies the Role object, specifically a Group object, with the given name. This is shown in the following example.

public void activateAlarm(Authorization auth) {
    if ( auth.hasRole( "AlarmSystemActivation" ) ) {
        // activate the alarm
        ...
    }
    else throw new SecurityException( 
        "Not authorized to activate alarm" );
}

107.3.2 Authorization Example

This section demonstrates a possible use of the User Admin service. The service has a flexible model and many other schemes are possible.

Assume an Operator installs an OSGi framework. Bundles in this environment have defined the following action groups:

AlarmSystemControl
InternetAccess
TemperatureControl
PhotoAlbumEdit
PhotoAlbumView
PortForwarding

Installing and uninstalling bundles could potentially extend this set. Therefore, the Operator also defines a number of groups that can be used to contain the different types of system users.

Administrators
Buddies
Children
Adults
Residents

In a particular instance, the Operator installs it in a household with the following residents and buddies:

Residents:      Elmer, Fudd, Marvin, Pepe
Buddies:        Daffy, Foghorn

First, the residents and buddies are assigned to the system user groups. Second, the user groups need to be assigned to the action groups.

The following tables show how the groups could be assigned.

Table 107.1 Example Groups with Basic and Required Members

Groups Elmer Fudd Marvin Pepe Daffy Foghorn
Residents Basic Basic Basic Basic - -
Buddies - - - - Basic Basic
Children - - Basic Basic - -
Adults Basic Basic - - - -
Administrators Basic - - - - -

Table 107.2 Example Action Groups with their Basic and Required Members

Groups Residents Buddies Children Adults Admin
AlarmSystemControl Basic - - - Required
InternetAccess Basic - - Required -
TemperatureControl Basic - - Required -
PhotoAlbumEdit Basic - Basic Basic -
PhotoAlbumView Basic Basic - - -
PortForwarding Basic - - - Required

107.4 Repository Maintenance

The UserAdmin interface is a straightforward API to maintain a repository of User and Group objects. It contains methods to create new Group and User objects with the createRole(String,int) method. The method is prepared so that the same signature can be used to create new types of roles in the future. The interface also contains a method to remove a Role object.

The existing configuration can be obtained with methods that list all Role objects using a filter argument. This filter, which has the same syntax as the Framework filter, must only return the Role objects for which the filter matches the properties.

Several utility methods simplify getting User objects depending on their properties.

107.5 User Admin Events

Changes in the User Admin service can be determined in real time. Each User Admin service implementation must send a UserAdminEvent object to any service in the Framework service registry that is registered under the UserAdminListener interface. This event must be send asynchronously from the cause of the event. The way events must be delivered is the same as described in Delivering Events of OSGi Core Release 8.

This procedure is demonstrated in the following code sample.

class Listener implements UserAdminListener{
    public void roleChanged( UserAdminEvent event ) {
        ...
    }
}
public class MyActivator 
    implements BundleActivator {
    public void start( BundleContext context ) {
        context.registerService( 
            UserAdminListener.class.getName(),
            new Listener(), null );
    }
    public void stop( BundleContext context ) {}
}

It is not necessary to unregister the listener object when the bundle is stopped because the Framework automatically unregisters it. Once registered, the UserAdminListener object must be notified of all changes to the role repository.

107.5.1 Event Admin and User Admin Change Events

User Admin events must be delivered asynchronously to the Event Admin service by the implementation, if present. The topic of a User Admin Event is:

org/osgi/service/useradmin/UserAdmin/<eventtype>

The following event types are supported:

ROLE_CREATED
ROLE_CHANGED
ROLE_REMOVED

All User Admin Events must have the following properties:

  • event - (UserAdminEvent) The event that was broadcast by the User Admin service.

  • role - (Role) The Role object that was created, modified or removed.

  • role.name - (String) The name of the role.

  • role.type - (Integer) One of ROLE, USER or GROUP.

  • service - (ServiceReference) The Service Reference of the User Admin service.

  • service.id - (Long) The User Admin service's ID.

  • service.objectClass - (String[]) The User Admin service's object class (which must include org.osgi.service.useradmin.UserAdmin)

  • service.pid - (String) The User Admin service's persistent identity

107.6 Security

The User Admin service is related to the security model of the OSGi framework, but is complementary to the [1] The Java Security Architecture for JDK 1.2. The final permission of most code should be the intersection of the Java 2 Permissions, which are based on the code that is executing, and the User Admin service authorization, which is based on the user for whom the code runs.

107.6.1 User Admin Permission

The User Admin service defines the UserAdminPermission class that can be used to restrict bundles in accessing credentials. This permission class has the following actions:

  • changeProperty - This permission is required to modify properties. The name of the permission is the prefix of the property name.

  • changeCredential - This action permits changing credentials. The name of the permission is the prefix of the name of the credential.

  • getCredential - This action permits getting credentials. The name of the permission is the prefix of the credential.

If the name of the permission is "admin", it allows the owner to administer the repository. No action is associated with the permission in that case.

Otherwise, the permission name is used to match the property name. This name may end with a ".*" string to indicate a wildcard. For example, com.acme.* matches com.acme.fudd.elmer and com.acme.bugs.

107.7 Relation to JAAS

At a glance, the Java Authorization and Authentication Service (JAAS) seems to be a very suitable model for user administration. The OSGi organization, however, decided to develop an independent User Admin service because JAAS was not deemed applicable. The reasons for this include dependency on Java SE version 1.3 ("JDK 1.3") and existing mechanisms in the previous OSGi Service Gateway 1.0 specification.

107.7.1 JDK 1.3 Dependencies

The authorization component of JAAS relies on the java.security.DomainCombiner interface, which provides a means to dynamically update the ProtectionDomain objects affiliated with an AccessControlContext object.

This interface was added in JDK 1.3. In the context of JAAS, the SubjectDomainCombiner object, which implements the DomainCombiner interface, is used to update ProtectionDomain objects. The permissions of ProtectionDomain objects depend on where code came from and who signed it, with permissions based on who is running the code.

Leveraging JAAS would have resulted in user-based access control on the OSGi framework being available only with JDK 1.3, which was not deemed acceptable.

107.7.2 Existing OSGi Mechanism

JAAS provides a plugable authentication architecture, which enables applications and their underlying authentication services to remain independent from each other.

The Servlet Whiteboard Specification already provides a similar feature by allowing servlet and resource registrations to be supported by an ServletContextHelper object, which uses a callback mechanism to perform any required authentication checks before granting access to the servlet or resource. This way, the registering bundle has complete control on a per-servlet and per-resource basis over which authentication protocol to use, how the credentials presented by the remote requester are to be validated, and who should be granted access to the servlet or resource.

107.7.3 Future Road Map

In the future, the main barrier of 1.3 compatibility will be removed. JAAS could then be implemented in an OSGi environment. At that time, the User Admin service will still be needed and will provide complementary services in the following ways:

  • The authorization component relies on group membership information to be stored and managed outside JAAS. JAAS does not manage persistent information, so the User Admin service can be a provider of group information when principals are assigned to a Subject object.

  • The authorization component allows for credentials to be collected and verified, but a repository is needed to actually validate the credentials.

In the future, the User Admin service can act as the back-end database to JAAS. The only aspect JAAS will remove from the User Admin service is the need for the Authorization interface.

107.8 org.osgi.service.useradmin

Version 1.1

User Admin Package Version 1.1.

Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.

Example import for consumers using the API in this package:

Import-Package: org.osgi.service.useradmin; version="[1.1,2.0)"

Example import for providers implementing the API in this package:

Import-Package: org.osgi.service.useradmin; version="[1.1,1.2)"

107.8.1 Summary

  • Authorization - The Authorization interface encapsulates an authorization context on which bundles can base authorization decisions, where appropriate.

  • Group - A named grouping of roles (Role objects).

  • Role - The base interface for Role objects managed by the User Admin service.

  • User - A User role managed by a User Admin service.

  • UserAdmin - This interface is used to manage a database of named Role objects, which can be used for authentication and authorization purposes.

  • UserAdminEvent - Role change event.

  • UserAdminListener - Listener for UserAdminEvents.

  • UserAdminPermission - Permission to configure and access the Role objects managed by a User Admin service.

107.8.2 public interface Authorization

The Authorization interface encapsulates an authorization context on which bundles can base authorization decisions, where appropriate.

Bundles associate the privilege to access restricted resources or operations with roles. Before granting access to a restricted resource or operation, a bundle will check if the Authorization object passed to it possess the required role, by calling its hasRole method.

Authorization contexts are instantiated by calling the UserAdmin.getAuthorization(User) method.

Trusting Authorization objects

There are no restrictions regarding the creation of Authorization objects. Hence, a service must only accept Authorization objects from bundles that has been authorized to use the service using code based (or Java 2) permissions.

In some cases it is useful to use ServicePermission to do the code based access control. A service basing user access control on Authorization objects passed to it, will then require that a calling bundle has the ServicePermission to get the service in question. This is the most convenient way. The OSGi environment will do the code based permission check when the calling bundle attempts to get the service from the service registry.

Example: A servlet using a service on a user's behalf. The bundle with the servlet must be given the ServicePermission to get the Http Service.

However, in some cases the code based permission checks need to be more fine-grained. A service might allow all bundles to get it, but require certain code based permissions for some of its methods.

Example: A servlet using a service on a user's behalf, where some service functionality is open to anyone, and some is restricted by code based permissions. When a restricted method is called (e.g., one handing over an Authorization object), the service explicitly checks that the calling bundle has permission to make the call.

Consumers of this API must not implement this interface

107.8.2.1 public String getName()

Gets the name of the User that this Authorization context was created for.

The name of the User object that this Authorization context was created for, or null if no user was specified when this Authorization context was created.

107.8.2.2 public String[] getRoles()

Gets the names of all roles implied by this Authorization context.

The names of all roles implied by this Authorization context, or null if no roles are in the context. The predefined role user.anyone will not be included in this list.

107.8.2.3 public boolean hasRole(String name)

The name of the role to check for.

Checks if the role with the specified name is implied by this Authorization context.

Bundles must define globally unique role names that are associated with the privilege of accessing restricted resources or operations. Operators will grant users access to these resources, by creating a Group object for each role and adding User objects to it.

true if this Authorization context implies the specified role, otherwise false.

107.8.3 public interface Group
extends User

A named grouping of roles (Role objects).

Whether or not a given Authorization context implies a Group object depends on the members of that Group object.

A Group object can have two kinds of members: basic and required . A Group object is implied by an Authorization context if all of its required members are implied and at least one of its basic members is implied.

A Group object must contain at least one basic member in order to be implied. In other words, a Group object without any basic member roles is never implied by any Authorization context.

A User object always implies itself.

No loop detection is performed when adding members to Group objects, which means that it is possible to create circular implications. Loop detection is instead done when roles are checked. The semantics is that if a role depends on itself (i.e., there is an implication loop), the role is not implied.

The rule that a Group object must have at least one basic member to be implied is motivated by the following example:

 
  group foo
    required members: marketing
    basic members: alice, bob

Privileged operations that require membership in "foo" can be performed only by "alice" and "bob", who are in marketing.

If "alice" and "bob" ever transfer to a different department, anybody in marketing will be able to assume the "foo" role, which certainly must be prevented. Requiring that "foo" (or any Group object for that matter) must have at least one basic member accomplishes that.

However, this would make it impossible for a Group object to be implied by just its required members. An example where this implication might be useful is the following declaration: "Any citizen who is an adult is allowed to vote." An intuitive configuration of "voter" would be:

 
  group voter
    required members: citizen, adult
       basic members:

However, according to the above rule, the "voter" role could never be assumed by anybody, since it lacks any basic members. In order to address this issue a predefined role named "user.anyone" can be specified, which is always implied. The desired implication of the "voter" group can then be achieved by specifying "user.anyone" as its basic member, as follows:

 
  group voter
    required members: citizen, adult
       basic members: user.anyone

Consumers of this API must not implement this interface

107.8.3.1 public boolean addMember(Role role)

The role to add as a basic member.

Adds the specified Role object as a basic member to this Group object.

true if the given role could be added as a basic member, and false if this Group object already contains a Role object whose name matches that of the specified role.

SecurityException– If a security manager exists and the caller does not have the UserAdminPermission with name admin.

107.8.3.2 public boolean addRequiredMember(Role role)

The Role object to add as a required member.

Adds the specified Role object as a required member to this Group object.

true if the given Role object could be added as a required member, and false if this Group object already contains a Role object whose name matches that of the specified role.

SecurityException– If a security manager exists and the caller does not have the UserAdminPermission with name admin.

107.8.3.3 public Role[] getMembers()

Gets the basic members of this Group object.

The basic members of this Group object, or null if this Group object does not contain any basic members.

107.8.3.4 public Role[] getRequiredMembers()

Gets the required members of this Group object.

The required members of this Group object, or null if this Group object does not contain any required members.

107.8.3.5 public boolean removeMember(Role role)

The Role object to remove from this Group object.

Removes the specified Role object from this Group object.

true if the Role object could be removed, otherwise false.

SecurityException– If a security manager exists and the caller does not have the UserAdminPermission with name admin.

107.8.4 public interface Role

The base interface for Role objects managed by the User Admin service.

This interface exposes the characteristics shared by all Role classes: a name, a type, and a set of properties.

Properties represent public information about the Role object that can be read by anyone. Specific UserAdminPermission objects are required to change a Role object's properties.

Role object properties are Dictionary objects. Changes to these objects are propagated to the User Admin service and made persistent.

Every User Admin service contains a set of predefined Role objects that are always present and cannot be removed. All predefined Role objects are of type ROLE. This version of the org.osgi.service.useradmin package defines a single predefined role named "user.anyone", which is inherited by any other role. Other predefined roles may be added in the future. Since "user.anyone" is a Role object that has properties associated with it that can be read and modified. Access to these properties and their use is application specific and is controlled using UserAdminPermission in the same way that properties for other Role objects are.

Consumers of this API must not implement this interface

107.8.4.1 public static final int GROUP = 2

The type of a Group role.

The value of GROUP is 2.

107.8.4.2 public static final int ROLE = 0

The type of a predefined role.

The value of ROLE is 0.

107.8.4.3 public static final int USER = 1

The type of a User role.

The value of USER is 1.

107.8.4.4 public static final String USER_ANYONE = "user.anyone"

The name of the predefined role, user.anyone, that all users and groups belong to.

1.1

107.8.4.5 public String getName()

Returns the name of this role.

The role's name.

107.8.4.6 public Dictionary<String, Object> getProperties()

Returns a Dictionary of the (public) properties of this Role object. Any changes to the returned Dictionary will change the properties of this Role object. This will cause a UserAdminEvent object of type UserAdminEvent.ROLE_CHANGED to be broadcast to any UserAdminListener objects.

Only objects of type String may be used as property keys, and only objects of type String or byte[] may be used as property values. Any other types will cause an exception of type IllegalArgumentException to be raised.

In order to add, change, or remove a property in the returned Dictionary, a UserAdminPermission named after the property name (or a prefix of it) with action changeProperty is required.

Dictionary containing the properties of this Role object.

107.8.4.7 public int getType()

Returns the type of this role.

The role's type.

107.8.5 public interface User
extends Role

A User role managed by a User Admin service.

In this context, the term "user" is not limited to just human beings. Instead, it refers to any entity that may have any number of credentials associated with it that it may use to authenticate itself.

In general, User objects are associated with a specific User Admin service (namely the one that created them), and cannot be used with other User Admin services.

A User object may have credentials (and properties, inherited from the Role class) associated with it. Specific UserAdminPermission objects are required to read or change a User object's credentials.

Credentials are Dictionary objects and have semantics that are similar to the properties in the Role class.

Consumers of this API must not implement this interface

107.8.5.1 public Dictionary<String, Object> getCredentials()

Returns a Dictionary of the credentials of this User object. Any changes to the returned Dictionary object will change the credentials of this User object. This will cause a UserAdminEvent object of type UserAdminEvent.ROLE_CHANGED to be broadcast to any UserAdminListeners objects.

Only objects of type String may be used as credential keys, and only objects of type String or of type byte[] may be used as credential values. Any other types will cause an exception of type IllegalArgumentException to be raised.

In order to retrieve a credential from the returned Dictionary object, a UserAdminPermission named after the credential name (or a prefix of it) with action getCredential is required.

In order to add or remove a credential from the returned Dictionary object, a UserAdminPermission named after the credential name (or a prefix of it) with action changeCredential is required.

Dictionary object containing the credentials of this User object.

107.8.5.2 public boolean hasCredential(String key, Object value)

The credential key.

The credential value.

Checks to see if this User object has a credential with the specified key set to the specified value.

If the specified credential value is not of type String or byte[], it is ignored, that is, false is returned (as opposed to an IllegalArgumentException being raised).

true if this user has the specified credential; false otherwise.

SecurityException– If a security manager exists and the caller does not have the UserAdminPermission named after the credential key (or a prefix of it) with action getCredential.

107.8.6 public interface UserAdmin

This interface is used to manage a database of named Role objects, which can be used for authentication and authorization purposes.

This version of the User Admin service defines two types of Role objects: "User" and "Group". Each type of role is represented by an int constant and an interface. The range of positive integers is reserved for new types of roles that may be added in the future. When defining proprietary role types, negative constant values must be used.

Every role has a name and a type.

A User object can be configured with credentials (e.g., a password) and properties (e.g., a street address, phone number, etc.).

A Group object represents an aggregation of User and Group objects. In other words, the members of a Group object are roles themselves.

Every User Admin service manages and maintains its own namespace of Role objects, in which each Role object has a unique name.

Consumers of this API must not implement this interface

107.8.6.1 public Role createRole(String name, int type)

The name of the Role object to create.

The type of the Role object to create. Must be either a Role.USER type or Role.GROUP type.

Creates a Role object with the given name and of the given type.

If a Role object was created, a UserAdminEvent object of type UserAdminEvent.ROLE_CREATED is broadcast to any UserAdminListener object.

The newly created Role object, or null if a role with the given name already exists.

IllegalArgumentException– if type is invalid.

SecurityException– If a security manager exists and the caller does not have the UserAdminPermission with name admin.

107.8.6.2 public Authorization getAuthorization(User user)

The User object to create an Authorization object for, or null for the anonymous user.

Creates an Authorization object that encapsulates the specified User object and the Role objects it possesses. The null user is interpreted as the anonymous user. The anonymous user represents a user that has not been authenticated. An Authorization object for an anonymous user will be unnamed, and will only imply groups that user.anyone implies.

the Authorization object for the specified User object.

107.8.6.3 public Role getRole(String name)

The name of the Role object to get.

Gets the Role object with the given name from this User Admin service.

The requested Role object, or null if this User Admin service does not have a Role object with the given name.

107.8.6.4 public Role[] getRoles(String filter) throws InvalidSyntaxException

The filter criteria to match.

Gets the Role objects managed by this User Admin service that have properties matching the specified LDAP filter criteria. See org.osgi.framework.Filter for a description of the filter syntax. If a null filter is specified, all Role objects managed by this User Admin service are returned.

The Role objects managed by this User Admin service whose properties match the specified filter criteria, or all Role objects if a null filter is specified. If no roles match the filter, null will be returned.

InvalidSyntaxException– If the filter is not well formed.

107.8.6.5 public User getUser(String key, String value)

The property key to look for.

The property value to compare with.

Gets the user with the given property key-value pair from the User Admin service database. This is a convenience method for retrieving a User object based on a property for which every User object is supposed to have a unique value (within the scope of this User Admin service), such as for example a X.500 distinguished name.

A matching user, if exactly one is found. If zero or more than one matching users are found, null is returned.

107.8.6.6 public boolean removeRole(String name)

The name of the Role object to remove.

Removes the Role object with the given name from this User Admin service and all groups it is a member of.

If the Role object was removed, a UserAdminEvent object of type UserAdminEvent.ROLE_REMOVED is broadcast to any UserAdminListener object.

true If a Role object with the given name is present in this User Admin service and could be removed, otherwise false.

SecurityException– If a security manager exists and the caller does not have the UserAdminPermission with name admin.

107.8.7 public class UserAdminEvent

Role change event.

UserAdminEvent objects are delivered asynchronously to any UserAdminListener objects when a change occurs in any of the Role objects managed by a User Admin service.

A type code is used to identify the event. The following event types are defined: ROLE_CREATED type, ROLE_CHANGED type, and ROLE_REMOVED type. Additional event types may be defined in the future.

UserAdmin, UserAdminListener

107.8.7.1 public static final int ROLE_CHANGED = 2

A Role object has been modified.

The value of ROLE_CHANGED is 0x00000002.

107.8.7.2 public static final int ROLE_CREATED = 1

A Role object has been created.

The value of ROLE_CREATED is 0x00000001.

107.8.7.3 public static final int ROLE_REMOVED = 4

A Role object has been removed.

The value of ROLE_REMOVED is 0x00000004.

107.8.7.4 public UserAdminEvent(ServiceReference<UserAdmin> ref, int type, Role role)

The ServiceReference object of the User Admin service that generated this event.

The event type.

The Role object on which this event occurred.

Constructs a UserAdminEvent object from the given ServiceReference object, event type, and Role object.

107.8.7.5 public Role getRole()

Gets the Role object this event was generated for.

The Role object this event was generated for.

107.8.7.6 public ServiceReference<UserAdmin> getServiceReference()

Gets the ServiceReference object of the User Admin service that generated this event.

The User Admin service's ServiceReference object.

107.8.7.7 public int getType()

Returns the type of this event.

The type values are ROLE_CREATED type, ROLE_CHANGED type, and ROLE_REMOVED type.

The event type.

107.8.8 public interface UserAdminListener

Listener for UserAdminEvents.

UserAdminListener objects are registered with the Framework service registry and notified with a UserAdminEvent object when a Role object has been created, removed, or modified.

UserAdminListener objects can further inspect the received UserAdminEvent object to determine its type, the Role object it occurred on, and the User Admin service that generated it.

UserAdmin, UserAdminEvent

107.8.8.1 public void roleChanged(UserAdminEvent event)

The UserAdminEvent object.

Receives notification that a Role object has been created, removed, or modified.

107.8.9 public final class UserAdminPermission
extends BasicPermission

Permission to configure and access the Role objects managed by a User Admin service.

This class represents access to the Role objects managed by a User Admin service and their properties and credentials (in the case of User objects).

The permission name is the name (or name prefix) of a property or credential. The naming convention follows the hierarchical property naming convention. Also, an asterisk may appear at the end of the name, following a ".", or by itself, to signify a wildcard match. For example: "org.osgi.security.protocol.*" or "*" is valid, but "*protocol" or "a*b" are not valid.

The UserAdminPermission with the reserved name "admin" represents the permission required for creating and removing Role objects in the User Admin service, as well as adding and removing members in a Group object. This UserAdminPermission does not have any actions associated with it.

The actions to be granted are passed to the constructor in a string containing a list of one or more comma-separated keywords. The possible keywords are: changeProperty,changeCredential, and getCredential. Their meaning is defined as follows:

  action
  changeProperty    Permission to change (i.e., add and remove)
                    Role object properties whose names start with
                    the name argument specified in the constructor.
  changeCredential  Permission to change (i.e., add and remove)
                    User object credentials whose names start
                    with the name argument specified in the constructor.
  getCredential     Permission to retrieve and check for the
                    existence of User object credentials whose names
                    start with the name argument specified in the
                    constructor.

The action string is converted to lowercase before processing.

Following is a PermissionInfo style policy entry which grants a user administration bundle a number of UserAdminPermission object:

  (org.osgi.service.useradmin.UserAdminPermission "admin")
  (org.osgi.service.useradmin.UserAdminPermission "com.foo.*"
                "changeProperty,getCredential,changeCredential")
  (org.osgi.service.useradmin.UserAdminPermission "user.*"
                              "changeProperty,changeCredential")

The first permission statement grants the bundle the permission to perform any User Admin service operations of type "admin", that is, create and remove roles and configure Group objects.

The second permission statement grants the bundle the permission to change any properties as well as get and change any credentials whose names start with com.foo..

The third permission statement grants the bundle the permission to change any properties and credentials whose names start with user.. This means that the bundle is allowed to change, but not retrieve any credentials with the given prefix.

The following policy entry empowers the Http Service bundle to perform user authentication:

  grant codeBase "${jars}http.jar" {
    permission org.osgi.service.useradmin.UserAdminPermission
      "user.password", "getCredential";
  };

The permission statement grants the Http Service bundle the permission to validate any password credentials (for authentication purposes), but the bundle is not allowed to change any properties or credentials.

Thread-safe

107.8.9.1 public static final String ADMIN = "admin"

The permission name "admin".

107.8.9.2 public static final String CHANGE_CREDENTIAL = "changeCredential"

The action string "changeCredential".

107.8.9.3 public static final String CHANGE_PROPERTY = "changeProperty"

The action string "changeProperty".

107.8.9.4 public static final String GET_CREDENTIAL = "getCredential"

The action string "getCredential".

107.8.9.5 public UserAdminPermission(String name, String actions)

the name of this UserAdminPermission

the action string.

Creates a new UserAdminPermission with the specified name and actions. name is either the reserved string "admin" or the name of a credential or property, and actions contains a comma-separated list of the actions granted on the specified name. Valid actions are changeProperty,changeCredential, and getCredential.

IllegalArgumentException– If name equals "admin" and actions are specified.

107.8.9.6 public boolean equals(Object obj)

the object to be compared for equality with this object.

Checks two UserAdminPermission objects for equality. Checks that obj is a UserAdminPermission, and has the same name and actions as this object.

true if obj is a UserAdminPermission object, and has the same name and actions as this UserAdminPermission object.

107.8.9.7 public String getActions()

Returns the canonical string representation of the actions, separated by comma.

the canonical string representation of the actions.

107.8.9.8 public int hashCode()

Returns the hash code value for this object.

A hash code value for this object.

107.8.9.9 public boolean implies(Permission p)

the permission to check against.

Checks if this UserAdminPermission object "implies" the specified permission.

More specifically, this method returns true if:

  • p is an instanceof UserAdminPermission,

  • p's actions are a proper subset of this object's actions, and

  • p's name is implied by this object's name. For example, "java.*" implies "java.home".

true if the specified permission is implied by this object; false otherwise.

107.8.9.10 public PermissionCollection newPermissionCollection()

Returns a new PermissionCollection object for storing UserAdminPermission objects.

a new PermissionCollection object suitable for storing UserAdminPermission objects.

107.8.9.11 public String toString()

Returns a string describing this UserAdminPermission object. This string must be in PermissionInfo encoded format.

The PermissionInfo encoded string for this UserAdminPermission object.

org.osgi.service.permissionadmin.PermissionInfo.getEncoded()

107.9 References

[1]The Java Security Architecture for JDK 1.2Version 1.0, Sun Microsystems, October 1998