/** * Copyright (c) 2011-2014, OpenIoT * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL"). If you do not alter this * notice, a recipient may use your version of this file under the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL for * the specific language governing rights and limitations. * * Contact: OpenIoT mailto: info@openiot.eu */ package org.openiot.security.client; import io.buji.pac4j.ClientRealm; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.subject.PrincipalCollection; import org.pac4j.core.exception.HttpCommunicationException; import org.pac4j.oauth.client.BaseOAuthClient; import org.pac4j.oauth.profile.JsonHelper; import org.pac4j.oauth.profile.casoauthwrapper.CasOAuthWrapperProfile; import org.scribe.model.OAuthConstants; import org.scribe.model.ProxyOAuthRequest; import org.scribe.model.Response; import org.scribe.model.Verb; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; /** * @author Mehdi Riahi * */ public class CasOAuthClientRealm extends ClientRealm implements ACRealm { private static Logger log = LoggerFactory.getLogger(CasOAuthClientRealm.class); private String permissionsURL; private List<ClearCacheListener> clearCacheListeners = new ArrayList<>(); @Override protected AuthorizationInfo doGetAuthorizationInfo(final PrincipalCollection principals) { log.debug("clients : {}", getClients()); final BaseOAuthClient<?> client = (BaseOAuthClient<?>) getClients().findClient("CasOAuthWrapperClient"); log.debug("client : {}", client); final CasOAuthWrapperProfile profile = principals.oneByType(CasOAuthWrapperProfile.class); log.debug("profile: {} ", profile); final String accessToken = profile.getAccessToken(); final ArrayNode roleNames = (ArrayNode) profile.getAttribute("role_name"); log.debug("accessToken: {} , key : {} ", accessToken, client.getKey()); // create simple authorization info final SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); // add roles for (JsonNode element : roleNames) { String role = element.asText(); log.debug("adding role: {}", role); simpleAuthorizationInfo.addRole(role); } // add default role simpleAuthorizationInfo.addRoles(split(getDefaultRoles())); // get permissions final String body = sendRequestForPermissions(accessToken, client); JsonNode json = JsonHelper.getFirstNode(body); if (json != null) { json = json.get("role_permissions"); if (json != null) { final Iterator<JsonNode> nodes = json.iterator(); while (nodes.hasNext()) { for (Iterator<Entry<String, JsonNode>> fields = nodes.next().fields(); fields.hasNext();) { Iterator<JsonNode> permIter = fields.next().getValue().iterator(); while (permIter.hasNext()) { json = permIter.next(); String permission = json.asText(); simpleAuthorizationInfo.addStringPermission(permission); log.debug("next permission: {}", permission); } } } } } // add default permissions simpleAuthorizationInfo.addStringPermissions(split(getDefaultPermissions())); return simpleAuthorizationInfo; } protected String sendRequestForPermissions(final String accessToken, final BaseOAuthClient<?> client) { log.debug("accessToken : {} / permissionsUrl : {}", accessToken, permissionsURL); final long t0 = System.currentTimeMillis(); final ProxyOAuthRequest request = new ProxyOAuthRequest(Verb.GET, permissionsURL, client.getConnectTimeout(), client.getReadTimeout(), client.getProxyHost(), client.getProxyPort()); request.addQuerystringParameter(OAuthConstants.CLIENT_ID, client.getKey()); request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken); request.addQuerystringParameter(SecurityConstants.TARGET_CLIENT_ID, client.getKey()); request.addQuerystringParameter(SecurityConstants.USER_ACCESS_TOKEN, accessToken); final Response response = request.send(); final int code = response.getCode(); final String body = response.getBody(); final long t1 = System.currentTimeMillis(); log.debug("Request took : " + (t1 - t0) + " ms for : " + permissionsURL); log.debug("response code : {} / response body : {}", code, body); if (code != 200) { log.error("Failed to get permissions, code : " + code + " / body : " + body); throw new HttpCommunicationException(code, body); } return body; } public String getPermissionsURL() { return permissionsURL; } public void setPermissionsURL(String permissionsURL) { this.permissionsURL = permissionsURL; } public void addClearCacheListener(ClearCacheListener listener) { clearCacheListeners.add(listener); } @Override protected void doClearCache(PrincipalCollection principals) { for (ClearCacheListener listener : clearCacheListeners) listener.clearCache(principals); } }