1 Reply Latest reply on Jul 25, 2014 5:26 AM by alekspo

    Custom IDM authentication and Authorizer

    alekspo

      I have custom implementation of Picketlink IDM JPA authentication model. I got it by coping example from here https://github.com/jboss-developer/jboss-picketlink-quickstarts/tree/master/picketlink-idm-custom-identity-model in package org.picketlink.idm.jpa.model.custom.simple. Then I implemented this example https://github.com/pedroigor/picketlink-quickstarts/tree/master/picketlink-deltaspike-authorization .

      I changed User class and UserTypeEntity in picketlink-idm-custom-identity-model example as follow:

      @IdentityStereotype(USER)

      public class User extends AbstractIdentityType implements Account {

        public static final QueryParameter USER_NAME = QUERY_ATTRIBUTE.byName("userName");

        @StereotypeProperty(IDENTITY_USER_NAME)

      @AttributeProperty

      @Unique

      private String userName;

        @AttributeProperty

      private String firstName;

      @AttributeProperty

      private String lastName;

      @AttributeProperty

      private String email;

      @AttributeProperty

      private String middleName;

      @AttributeProperty

      private String telephone;

      @AttributeProperty

      private String address;

      @AttributeProperty

      private int postIndex;

      @AttributeProperty

      private Date registerDate;

      @AttributeProperty

      private Date lastVisitDate;

      @AttributeProperty

      private boolean isOrganizer;

      @AttributeProperty

      private boolean isAdmin;

      @Embedded

      private Organizer organizer;

      @Embedded

      private Customer customer;

      // getters and setters

      }

      class UserTypeEntity

      @IdentityManaged(User.class)

      @Entity

      public class UserTypeEntity extends AbstractIdentityTypeEntity {

      @AttributeValue

      private String userName;

      @OwnerReference

      @ManyToOne(fetch = FetchType.LAZY)

      private RealmTypeEntity realm;

      @AttributeProperty

      private String firstName;

      @AttributeProperty

      private String lastName;

      @AttributeProperty

      private String email;

      @AttributeProperty

      @Column(length = 255)

      private String middleName;

      @AttributeProperty

      @Size(max = 12)

      @Column(length = 12)

      private String telephone;

      @AttributeProperty

      @Column(length = 5000)

      @Size(max = 5000)

      private String address;

      @AttributeProperty

      private int postIndex;

      @AttributeProperty

      private Date registerDate;

      @AttributeProperty

      private Date lastVisitDate;

      @AttributeProperty

      private boolean isOrganizer;

      @AttributeProperty

      private boolean isAdmin;

      @Embedded

      private Organizer organizer;

      @Embedded

      private Customer customer;

      Then I implemented Login controller:

      @Named

      @Stateless

      public class LoginController {

      @Inject

      private Identity identity;

      @Inject

      private FacesContext facesContext;

      public void login() {

      AuthenticationResult result = identity.login();

        if (AuthenticationResult.FAILED.equals(result)) {

      facesContext.addMessage(

      null,

      new FacesMessage("Invalid user name or password"));

        }

        }

      }

      And Registration Controller:

      @Named

      @RequestScoped

      public class RegistrationController {

        private IdentityManager identityManager;

        @Inject

        private PartitionManager partitionManager;

        @Inject

        private FacesContext facesContext;

        @Inject

        private User user;

        private String password;

        private String passwordVerify;

        private boolean isOrganizer;

        public RegistrationController() {

        }

        public User getUser() {

          return user;

        }

        public void setUser(User user) {

          this.user = user;

        }

        public String getPasswordVerify() {

          return passwordVerify;

        }

        public void setPasswordVerify(String passwordVerify) {

          this.passwordVerify = passwordVerify;

        }

        public boolean getIsOrganizer() {

          return isOrganizer;

        }

        public void setIsOrganizer(boolean isOrganizer) {

          this.isOrganizer = isOrganizer;

        }

        public String getPassword() {

          return password;

        }

        public void setPassword(String password) {

          this.password = password;

        }

        @Transactional

        public String register() throws Exception {

          if (password.isEmpty()) {

            String message = LocaleBean.loadErrorMessage(facesContext, LocaleBean.EX_RESOURCE_BUNDLE_NAME, "password.empty");

            facesContext.addMessage("signup:registrationPassword", new FacesMessage(message));

            return "returnToSignup";

          }

          if (!password.equals(passwordVerify)) {

            String message = LocaleBean.loadErrorMessage(facesContext, LocaleBean.EX_RESOURCE_BUNDLE_NAME, "password.NotEqual");

            facesContext.addMessage("signup:registrationPassword", new FacesMessage(message));

            return "returnToSignup";

          }

            identityManager = partitionManager.createIdentityManager(partitionManager.getPartition(Realm.class,

                Resources.REALM_ACME_NAME));

            if (isOrganizer) {

              user.setOrganizer(true);

              user.setOrganizer(new Organizer());

              try {

                identityManager.add(user);

              } catch (IdentityManagementException e) {

                String message = LocaleBean.loadErrorMessage(facesContext, LocaleBean.EX_RESOURCE_BUNDLE_NAME, "login.Registered");

                facesContext.addMessage(null, new FacesMessage(message));

                return "returnToSignup";

              }

              Password password = new Password(this.password);

              identityManager.updateCredential(user, password);

              RelationshipManager relationshipManager = partitionManager.createRelationshipManager();

              IdentityQuery<Group> query = identityManager.createIdentityQuery(Group.class);

              // query all childs of sales unit

              query.setParameter(Group.NAME, Resources.ORGANIZERS_GROUP_NAME);

              List<Group> groups = query.getResultList();

              Group organizersGroup = groups.get(0);

              relationshipManager.add(new GroupMembership(user, organizersGroup));

            } else {

            }

          return "signin";

        }

      }

      After that I implemented Authorizer:

      @ApplicationScoped

      public class SPAuthorizer {

      @Secures

      @Admins

      public boolean doAdminsCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {

      return hasGroup(identity, identityManager, relationshipManager, Resources.ADMINS_GROUP_NAME);

        }

      @Secures

      @Organizers

      public boolean doOrganizersCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {

      return hasGroup(identity, identityManager, relationshipManager, Resources.ORGANIZERS_GROUP_NAME);

        }

      @Secures

      @Customers

      public boolean doCustomersCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {

      return hasGroup(identity, identityManager, relationshipManager, Resources.CUSTOMERS_GROUP_NAME);

        }

      private boolean hasGroup(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager,

      String groupName) {

      IdentityQuery<Group> queryGroup = identityManager.createIdentityQuery(Group.class);

        // query all childs of sales unit

      queryGroup.setParameter(Group.NAME, groupName);

      List<Group> groups = queryGroup.getResultList();

        if (groups.size() == 1) {

      Group group = groups.get(0);

      Account user = identity.getAccount();

      if (user == null) {

      return false;

        }

      RelationshipQuery<GroupMembership> query = relationshipManager.createRelationshipQuery(GroupMembership.class);

      query.setParameter(GroupMembership.GROUP, group);

      query.setParameter(GroupMembership.MEMBER, user);

      // user is assigned with two groups

      List<GroupMembership> resultList = query.getResultList();

      return resultList.size() > 0;

        }

      return false;

        }

      }

      Also I implemented authorization checker to check belonging user to a some group in JSF:

      @Named

      @Stateless

      public class AuthorizationChecker {

      @Inject

      private Identity identity;

      @Inject

      private PartitionManager partitionManager;

      public boolean hasGroup(String groupName) {

      IdentityManager identityManager = partitionManager.createIdentityManager(partitionManager.getPartition(Realm.class,

      Resources.REALM_ACME_NAME));

      IdentityQuery<Group> queryGroup = identityManager.createIdentityQuery(Group.class);

        // query all childs of sales unit

      queryGroup.setParameter(Group.NAME, groupName);

      List<Group> groups = queryGroup.getResultList();

        if (groups.size() == 1) {

      Group group = groups.get(0);

      Account user = identity.getAccount();

      RelationshipManager relationshipManager = partitionManager.createRelationshipManager();

      RelationshipQuery<GroupMembership> query = relationshipManager.createRelationshipQuery(GroupMembership.class);

      query.setParameter(GroupMembership.GROUP, group);

      query.setParameter(GroupMembership.MEMBER, user);

      // user is assigned with two groups

      List<GroupMembership> resultList = query.getResultList();

      return resultList.size() > 0;

        }

      return false;

        }

      }

      But an instance of Identity in hasGroup of SPAuthorizer doesn't corresponds to an instance that I have in AuthorizationChecker. I checked it in debugger. And when I do identity.getAccount(); it returns null also user was authenticated. Any idea why this happens?