| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.jackrabbit.oak.exercise.security.authentication.external; |
| |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| import javax.jcr.Credentials; |
| import javax.jcr.SimpleCredentials; |
| import javax.security.auth.login.LoginException; |
| |
| import com.google.common.base.Function; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Iterables; |
| import org.apache.felix.scr.annotations.Activate; |
| import org.apache.felix.scr.annotations.Component; |
| import org.apache.felix.scr.annotations.Modified; |
| import org.apache.felix.scr.annotations.Properties; |
| import org.apache.felix.scr.annotations.Property; |
| import org.apache.felix.scr.annotations.Service; |
| import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser; |
| import org.apache.jackrabbit.util.Text; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| @Component(metatype = true, |
| label = "Apache Jackrabbit Oak CustomExternalIdentityProvider", |
| immediate = true |
| ) |
| @Service |
| @Properties({ |
| @Property(name = "externalidentities", |
| label = "External Identities", |
| value = "testUser,a,b,c", |
| cardinality = Integer.MAX_VALUE) |
| }) |
| public class CustomExternalIdentityProvider implements ExternalIdentityProvider { |
| |
| private static final Logger log = LoggerFactory.getLogger(CustomExternalIdentityProvider.class); |
| |
| private Map<String, Set<String>> userGroupMap = new HashMap<String, Set<String>>(); |
| private Set<String> groupIds = new HashSet<String>(); |
| |
| public CustomExternalIdentityProvider() {}; |
| |
| |
| //----------------------------------------------------< SCR integration >--- |
| @SuppressWarnings("UnusedDeclaration") |
| @Activate |
| public void activate(Map<String, Object> properties) { |
| ConfigurationParameters config = ConfigurationParameters.of(properties); |
| for (String entry : config.getConfigValue("externalidentities", Collections.<String>emptySet())) { |
| String[] strs = Text.explode(entry, ',', false); |
| String uid = strs[0].trim(); |
| Set<String> declaredGroups = new HashSet<String>(); |
| if (strs.length > 1) { |
| for (int i = 1; i < strs.length; i++) { |
| groupIds.add(strs[i]); |
| declaredGroups.add(strs[i]); |
| |
| } |
| } |
| userGroupMap.put(uid, declaredGroups); |
| } |
| log.info("activated IDP: " + getName()); |
| } |
| |
| @SuppressWarnings("UnusedDeclaration") |
| @Modified |
| public void modified(Map<String, Object> properties) { |
| activate(properties); |
| log.info("modified IDP: " + getName()); |
| } |
| |
| @NotNull |
| @Override |
| public String getName() { |
| return "CustomExternalIdentityProvider"; |
| } |
| |
| @Override |
| public ExternalIdentity getIdentity(@NotNull ExternalIdentityRef ref) throws ExternalIdentityException { |
| if (getName().equals(ref.getProviderName())) { |
| String id = ref.getId(); |
| ExternalIdentity ei = getUser(id); |
| if (ei == null) { |
| ei = getGroup(id); |
| } |
| return ei; |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| public ExternalUser getUser(@NotNull final String userId) throws ExternalIdentityException { |
| if (userGroupMap.containsKey(userId)) { |
| return new ExternalUser() { |
| |
| @NotNull |
| @Override |
| public ExternalIdentityRef getExternalId() { |
| return new ExternalIdentityRef(userId, getName()); |
| } |
| |
| @NotNull |
| @Override |
| public String getId() { |
| return userId; |
| } |
| |
| @NotNull |
| @Override |
| public String getPrincipalName() { |
| return "p_" + getExternalId().getString(); |
| } |
| |
| @Override |
| public String getIntermediatePath() { |
| return null; |
| } |
| |
| @NotNull |
| @Override |
| public Iterable<ExternalIdentityRef> getDeclaredGroups() throws ExternalIdentityException { |
| Set<String> groupIds = userGroupMap.get(userId); |
| if (groupIds == null || groupIds.isEmpty()) { |
| return ImmutableSet.of(); |
| } else { |
| return Iterables.transform(groupIds, new Function<String, ExternalIdentityRef>() { |
| @Nullable |
| @Override |
| public ExternalIdentityRef apply(String input) { |
| return new ExternalIdentityRef(input, getName()); |
| } |
| }); |
| } |
| } |
| |
| @NotNull |
| @Override |
| public Map<String, ?> getProperties() { |
| return ImmutableMap.of(); |
| } |
| }; |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| public ExternalUser authenticate(@NotNull Credentials credentials) throws ExternalIdentityException, LoginException { |
| if (credentials instanceof SimpleCredentials) { |
| String userId = ((SimpleCredentials) credentials).getUserID(); |
| return getUser(userId); |
| } else { |
| throw new LoginException("unsupported credentials"); |
| } |
| } |
| |
| @Override |
| public ExternalGroup getGroup(@NotNull final String name) throws ExternalIdentityException { |
| if (groupIds.contains(name)) { |
| return new ExternalGroup() { |
| @NotNull |
| @Override |
| public Iterable<ExternalIdentityRef> getDeclaredMembers() throws ExternalIdentityException { |
| Set<ExternalIdentityRef> members = new HashSet<ExternalIdentityRef>(); |
| for (Map.Entry<String, Set<String>> entry : userGroupMap.entrySet()) { |
| if (entry.getValue().contains(name)) { |
| members.add(new ExternalIdentityRef(entry.getKey(), getName())); |
| } |
| } |
| return members; |
| } |
| |
| @NotNull |
| @Override |
| public ExternalIdentityRef getExternalId() { |
| return new ExternalIdentityRef(name, getName()); |
| } |
| |
| @NotNull |
| @Override |
| public String getId() { |
| return name; |
| } |
| |
| @NotNull |
| @Override |
| public String getPrincipalName() { |
| return "p_" + getExternalId().getString(); |
| } |
| |
| @Override |
| public String getIntermediatePath() { |
| return null; |
| } |
| |
| @NotNull |
| @Override |
| public Iterable<ExternalIdentityRef> getDeclaredGroups() throws ExternalIdentityException { |
| return ImmutableSet.of(); |
| } |
| |
| @NotNull |
| @Override |
| public Map<String, ?> getProperties() { |
| return ImmutableMap.of(); |
| } |
| }; |
| } else { |
| return null; |
| } |
| } |
| |
| @NotNull |
| @Override |
| public Iterator<ExternalUser> listUsers() throws ExternalIdentityException { |
| throw new UnsupportedOperationException("listUsers"); |
| } |
| |
| @NotNull |
| @Override |
| public Iterator<ExternalGroup> listGroups() throws ExternalIdentityException { |
| throw new UnsupportedOperationException("listGroups"); |
| } |
| } |