001/* 002 * (C) Copyright 2006-2013 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nelson Silva 018 */ 019 020package org.nuxeo.ecm.platform.oauth2.openid; 021 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.Collection; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.nuxeo.ecm.platform.oauth2.providers.OAuth2ServiceProvider; 032import org.nuxeo.ecm.platform.oauth2.providers.OAuth2ServiceProviderRegistry; 033import org.nuxeo.ecm.platform.ui.web.auth.LoginScreenHelper; 034import org.nuxeo.runtime.api.Framework; 035import org.nuxeo.runtime.model.ComponentContext; 036import org.nuxeo.runtime.model.ComponentInstance; 037import org.nuxeo.runtime.model.DefaultComponent; 038 039/** 040 * @author Nelson Silva <nelson.silva@inevo.pt> 041 * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a> 042 * @since 5.7 043 */ 044public class OpenIDConnectProviderRegistryImpl extends DefaultComponent implements OpenIDConnectProviderRegistry { 045 046 protected static final Log log = LogFactory.getLog(OpenIDConnectProviderRegistryImpl.class); 047 048 public static final String PROVIDER_EP = "providers"; 049 050 protected Map<String, OpenIDConnectProvider> providers = new HashMap<String, OpenIDConnectProvider>(); 051 052 protected OpenIDProviderFragmentRegistry pendingProviders = new OpenIDProviderFragmentRegistry(); 053 054 protected OAuth2ServiceProviderRegistry getOAuth2ServiceProviderRegistry() { 055 return Framework.getLocalService(OAuth2ServiceProviderRegistry.class); 056 } 057 058 @Override 059 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 060 if (PROVIDER_EP.equals(extensionPoint)) { 061 OpenIDConnectProviderDescriptor provider = (OpenIDConnectProviderDescriptor) contribution; 062 063 if (provider.getClientId() == null || provider.getClientSecret() == null) { 064 log.info("OpenId provider for " + provider.getName() 065 + " is disabled because clientId and/or clientSecret are empty (component id = " 066 + contributor.getName().toString() + ")"); 067 provider.setEnabled(false); 068 } 069 log.info("OpenId provider for " + provider.getName() + " will be registred at application startup"); 070 // delay registration because data sources may not be available 071 // at this point 072 pendingProviders.addContribution(provider); 073 } 074 } 075 076 @Override 077 public Collection<OpenIDConnectProvider> getProviders() { 078 return providers.values(); 079 } 080 081 @Override 082 public Collection<OpenIDConnectProvider> getEnabledProviders() { 083 List<OpenIDConnectProvider> result = new ArrayList<OpenIDConnectProvider>(); 084 for (OpenIDConnectProvider provider : getProviders()) { 085 if (provider.isEnabled()) { 086 result.add(provider); 087 } 088 } 089 return result; 090 } 091 092 @Override 093 public OpenIDConnectProvider getProvider(String name) { 094 return providers.get(name); 095 } 096 097 protected void registerPendingProviders() { 098 for (OpenIDConnectProviderDescriptor provider : pendingProviders.getContribs()) { 099 registerOpenIdProvider(provider); 100 } 101 } 102 103 protected void registerOpenIdProvider(OpenIDConnectProviderDescriptor provider) { 104 105 OAuth2ServiceProviderRegistry oauth2ProviderRegistry = getOAuth2ServiceProviderRegistry(); 106 RedirectUriResolver redirectUriResolver; 107 try { 108 redirectUriResolver = provider.getRedirectUriResolver().newInstance(); 109 } catch (ReflectiveOperationException e) { 110 throw new RuntimeException(e); 111 } 112 113 if (oauth2ProviderRegistry != null) { 114 115 OAuth2ServiceProvider oauth2Provider = oauth2ProviderRegistry.getProvider(provider.getName()); 116 117 if (oauth2Provider == null) { 118 oauth2Provider = oauth2ProviderRegistry.addProvider(provider.getName(), provider.getDescription(), 119 provider.getTokenServerURL(), provider.getAuthorizationServerURL(), provider.getClientId(), 120 provider.getClientSecret(), Arrays.asList(provider.getScopes())); 121 } else { 122 log.warn("Provider " + provider.getName() 123 + " is already in the Database, XML contribution won't overwrite it"); 124 } 125 providers.put(provider.getName(), new OpenIDConnectProvider(oauth2Provider, provider.getAccessTokenKey(), 126 provider.getUserInfoURL(), provider.getUserInfoClass(), provider.getIcon(), provider.isEnabled(), 127 redirectUriResolver, provider.getUserResolverClass(), provider.getUserMapper())); 128 129 // contribute icon and link to the Login Screen 130 LoginScreenHelper.registerLoginProvider(provider.getName(), provider.getIcon(), provider.getUserInfoURL(), 131 provider.getLabel(), provider.getDescription(), providers.get(provider.getName())); 132 133 } else { 134 if (Framework.isTestModeSet()) { 135 providers.put(provider.getName(), 136 new OpenIDConnectProvider(null, provider.getAccessTokenKey(), provider.getUserInfoURL(), 137 provider.getUserInfoClass(), provider.getIcon(), provider.isEnabled(), 138 redirectUriResolver, provider.getUserResolverClass(),provider.getUserMapper())); 139 } else { 140 log.error("Can not register OAuth Provider since OAuth Registry is not available"); 141 } 142 } 143 144 } 145 146 @Override 147 public void applicationStarted(ComponentContext context) { 148 super.applicationStarted(context); 149 registerPendingProviders(); 150 } 151 152}