2 * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.aaa.shiro.idm;
10 import static java.util.Objects.requireNonNull;
12 import java.util.ArrayList;
13 import java.util.List;
15 import java.util.concurrent.ConcurrentHashMap;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.aaa.api.AuthenticationException;
19 import org.opendaylight.aaa.api.Claim;
20 import org.opendaylight.aaa.api.ClaimCache;
21 import org.opendaylight.aaa.api.IDMStoreException;
22 import org.opendaylight.aaa.api.IIDMStore;
23 import org.opendaylight.aaa.api.IdMService;
24 import org.opendaylight.aaa.api.IdMServiceImpl;
25 import org.opendaylight.aaa.api.PasswordCredentialAuth;
26 import org.opendaylight.aaa.api.PasswordCredentials;
27 import org.opendaylight.aaa.api.model.Domain;
28 import org.opendaylight.aaa.api.model.Grant;
29 import org.opendaylight.aaa.api.model.Grants;
30 import org.opendaylight.aaa.api.model.Role;
31 import org.opendaylight.aaa.api.model.User;
32 import org.opendaylight.aaa.api.model.Users;
33 import org.opendaylight.aaa.api.password.service.PasswordHashService;
34 import org.opendaylight.aaa.tokenauthrealm.auth.ClaimBuilder;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * An OSGi proxy for the IdmLight server.
42 public class IdmLightProxy implements PasswordCredentialAuth, IdMService, ClaimCache {
43 private static final Logger LOG = LoggerFactory.getLogger(IdmLightProxy.class);
46 * Responsible for storing the active claims per domain. The outer map is keyed by domain, and the inner map is
47 * keyed by <code>PasswordCredentials</code>.
49 private final Map<String, Map<PasswordCredentials, Claim>> claimCache = new ConcurrentHashMap<>();
51 private final IIDMStore idmStore;
52 private final PasswordHashService passwordService;
55 public IdmLightProxy(final IIDMStore idmStore, final PasswordHashService passwordService) {
56 this.idmStore = idmStore;
57 this.passwordService = requireNonNull(passwordService);
61 public Claim authenticate(final PasswordCredentials creds) {
62 requireNonNull(creds);
63 requireNonNull(creds.username());
64 requireNonNull(creds.password());
65 String domain = creds.domain() == null ? IIDMStore.DEFAULT_DOMAIN : creds.domain();
67 // FIXME: Add cache invalidation
68 return claimCache.computeIfAbsent(domain, k -> new ConcurrentHashMap<>())
69 .computeIfAbsent(creds, this::dbAuthenticate);
73 * Clears the cache of any active claims.
77 LOG.info("Clearing the claim cache");
81 private Claim dbAuthenticate(final PasswordCredentials creds) {
84 String credsDomain = creds.domain() == null ? IIDMStore.DEFAULT_DOMAIN : creds.domain();
85 // check to see domain exists
86 // TODO: ensure domain names are unique change to 'getDomain'
87 LOG.debug("get domain");
89 domain = idmStore.readDomain(credsDomain);
91 throw new AuthenticationException("Domain :" + credsDomain + " does not exist");
93 } catch (IDMStoreException e) {
94 throw new AuthenticationException("Error while fetching domain", e);
97 // check to see user exists and passes cred check
99 LOG.debug("check user / pwd");
100 Users users = idmStore.getUsers(creds.username(), credsDomain);
101 List<User> userList = users.getUsers();
102 if (userList.size() == 0) {
103 throw new AuthenticationException("User :" + creds.username()
104 + " does not exist in domain " + credsDomain);
106 user = userList.get(0);
107 if (!passwordService.passwordsMatch(creds.password(), user.getPassword(), user.getSalt())) {
108 throw new AuthenticationException("UserName / Password not found");
110 if (!user.isEnabled()) {
111 throw new AuthenticationException("Account is disabled");
114 // get all grants & roles for this domain and user
115 LOG.debug("get grants");
116 List<String> roles = new ArrayList<>();
117 Grants grants = idmStore.getGrants(domain.getDomainid(), user.getUserid());
118 for (Grant grant : grants.getGrants()) {
119 Role role = idmStore.readRole(grant.getRoleid());
121 roles.add(role.getName());
125 // build up the claim
126 LOG.debug("build a claim");
127 ClaimBuilder claim = new ClaimBuilder();
128 claim.setUserId(user.getUserid());
129 claim.setUser(creds.username());
130 claim.setDomain(credsDomain);
131 for (String role : roles) {
134 return claim.build();
135 } catch (IDMStoreException se) {
136 throw new AuthenticationException("idm data store exception :" + se.toString() + se);
141 public List<String> listDomains(final String userId) {
142 return new IdMServiceImpl(idmStore).listDomains(userId);
146 public List<String> listRoles(final String userId, final String domainName) {
147 return new IdMServiceImpl(idmStore).listRoles(userId, domainName);
151 public List<String> listUserIDs() throws IDMStoreException {
152 return new IdMServiceImpl(idmStore).listUserIDs();