/* * Copyright 2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.keycloak.adapters.saml.wildfly; import org.jboss.security.NestableGroup; import org.jboss.security.SecurityConstants; import org.jboss.security.SecurityContextAssociation; import org.jboss.security.SimpleGroup; import org.jboss.security.SimplePrincipal; import org.keycloak.adapters.spi.KeycloakAccount; import javax.security.auth.Subject; import java.security.Principal; import java.security.acl.Group; import java.util.Collection; import java.util.Enumeration; import java.util.Iterator; import java.util.Set; /** * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @version $Revision: 1 $ */ public class SecurityInfoHelper { public static void propagateSessionInfo(KeycloakAccount account) { Subject subject = new Subject(); Set<Principal> principals = subject.getPrincipals(); principals.add(account.getPrincipal()); Group[] roleSets = getRoleSets(account.getRoles()); for (int g = 0; g < roleSets.length; g++) { Group group = roleSets[g]; String name = group.getName(); Group subjectGroup = createGroup(name, principals); if (subjectGroup instanceof NestableGroup) { /* A NestableGroup only allows Groups to be added to it so we need to add a SimpleGroup to subjectRoles to contain the roles */ SimpleGroup tmp = new SimpleGroup("Roles"); subjectGroup.addMember(tmp); subjectGroup = tmp; } // Copy the group members to the Subject group Enumeration<? extends Principal> members = group.members(); while (members.hasMoreElements()) { Principal role = (Principal) members.nextElement(); subjectGroup.addMember(role); } } // add the CallerPrincipal group if none has been added in getRoleSets Group callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP); callerGroup.addMember(account.getPrincipal()); principals.add(callerGroup); org.jboss.security.SecurityContext sc = SecurityContextAssociation.getSecurityContext(); Principal userPrincipal = getPrincipal(subject); sc.getUtil().createSubjectInfo(userPrincipal, account, subject); } /** * Get the Principal given the authenticated Subject. Currently the first subject that is not of type {@code Group} is * considered or the single subject inside the CallerPrincipal group. * * @param subject * @return the authenticated subject */ protected static Principal getPrincipal(Subject subject) { Principal principal = null; Principal callerPrincipal = null; if (subject != null) { Set<Principal> principals = subject.getPrincipals(); if (principals != null && !principals.isEmpty()) { for (Principal p : principals) { if (!(p instanceof Group) && principal == null) { principal = p; } if (p instanceof Group) { Group g = Group.class.cast(p); if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) { Enumeration<? extends Principal> e = g.members(); if (e.hasMoreElements()) callerPrincipal = e.nextElement(); } } } } } return callerPrincipal == null ? principal : callerPrincipal; } protected static Group createGroup(String name, Set<Principal> principals) { Group roles = null; Iterator<Principal> iter = principals.iterator(); while (iter.hasNext()) { Object next = iter.next(); if (!(next instanceof Group)) continue; Group grp = (Group) next; if (grp.getName().equals(name)) { roles = grp; break; } } // If we did not find a group create one if (roles == null) { roles = new SimpleGroup(name); principals.add(roles); } return roles; } protected static Group[] getRoleSets(Collection<String> roleSet) { SimpleGroup roles = new SimpleGroup("Roles"); Group[] roleSets = {roles}; for (String role : roleSet) { roles.addMember(new SimplePrincipal(role)); } return roleSets; } }