001/* 002 * (C) Copyright 2006-2017 Nuxeo (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 */ 019package org.nuxeo.ecm.platform.oauth2.openid; 020 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.Collection; 024import java.util.HashMap; 025import java.util.List; 026import java.util.Map; 027 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.ecm.platform.oauth2.providers.OAuth2ServiceProvider; 031import org.nuxeo.ecm.platform.oauth2.providers.OAuth2ServiceProviderRegistry; 032import org.nuxeo.ecm.platform.ui.web.auth.LoginScreenHelper; 033import org.nuxeo.runtime.api.Framework; 034import org.nuxeo.runtime.model.ComponentContext; 035import org.nuxeo.runtime.model.ComponentInstance; 036import org.nuxeo.runtime.model.DefaultComponent; 037 038/** 039 * @author Nelson Silva <[email protected]> 040 * @author <a href="mailto:[email protected]">Tiry</a> 041 * @since 5.7 042 */ 043public class OpenIDConnectProviderRegistryImpl extends DefaultComponent implements OpenIDConnectProviderRegistry { 044 045 protected static final Log log = LogFactory.getLog(OpenIDConnectProviderRegistryImpl.class); 046 047 public static final String PROVIDER_EP = "providers"; 048 049 protected Map<String, OpenIDConnectProvider> providers = new HashMap<>(); 050 051 protected OpenIDProviderFragmentRegistry pendingProviders = new OpenIDProviderFragmentRegistry(); 052 053 protected OAuth2ServiceProviderRegistry getOAuth2ServiceProviderRegistry() { 054 return Framework.getService(OAuth2ServiceProviderRegistry.class); 055 } 056 057 @Override 058 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 059 if (PROVIDER_EP.equals(extensionPoint)) { 060 OpenIDConnectProviderDescriptor provider = (OpenIDConnectProviderDescriptor) contribution; 061 062 if (provider.getClientId() == null || provider.getClientSecret() == null) { 063 log.info("OpenId provider for " + provider.getName() 064 + " is disabled because clientId and/or clientSecret are empty (component id = " 065 + contributor.getName().toString() + ")"); 066 provider.setEnabled(false); 067 } 068 log.info("OpenId provider for " + provider.getName() + " will be registred at application startup"); 069 // delay registration because data sources may not be available 070 // at this point 071 pendingProviders.addContribution(provider); 072 } 073 } 074 075 @Override 076 public Collection<OpenIDConnectProvider> getProviders() { 077 return providers.values(); 078 } 079 080 @Override 081 public Collection<OpenIDConnectProvider> getEnabledProviders() { 082 List<OpenIDConnectProvider> result = new ArrayList<>(); 083 for (OpenIDConnectProvider provider : getProviders()) { 084 if (provider.isEnabled()) { 085 result.add(provider); 086 } 087 } 088 return result; 089 } 090 091 @Override 092 public OpenIDConnectProvider getProvider(String name) { 093 return providers.get(name); 094 } 095 096 protected void registerPendingProviders() { 097 for (OpenIDConnectProviderDescriptor provider : pendingProviders.getContribs()) { 098 registerOpenIdProvider(provider); 099 } 100 } 101 102 protected void registerOpenIdProvider(OpenIDConnectProviderDescriptor provider) { 103 104 OAuth2ServiceProviderRegistry oauth2ProviderRegistry = getOAuth2ServiceProviderRegistry(); 105 RedirectUriResolver redirectUriResolver; 106 try { 107 redirectUriResolver = provider.getRedirectUriResolver().newInstance(); 108 } catch (ReflectiveOperationException e) { 109 throw new RuntimeException(e); 110 } 111 112 if (oauth2ProviderRegistry != null) { 113 114 OAuth2ServiceProvider oauth2Provider = oauth2ProviderRegistry.getProvider(provider.getName()); 115 116 if (oauth2Provider == null) { 117 oauth2Provider = oauth2ProviderRegistry.addProvider(provider.getName(), provider.getDescription(), 118 provider.getTokenServerURL(), provider.getAuthorizationServerURL(), provider.getClientId(), 119 provider.getClientSecret(), Arrays.asList(provider.getScopes())); 120 } else { 121 log.warn("Provider " + provider.getName() 122 + " is already in the Database, XML contribution won't overwrite it"); 123 } 124 providers.put(provider.getName(), 125 new OpenIDConnectProvider(oauth2Provider, provider.getAccessTokenKey(), provider.getUserInfoURL(), 126 provider.getUserInfoClass(), provider.getIcon(), provider.isEnabled(), redirectUriResolver, 127 provider.getUserResolverClass(), provider.getUserMapper())); 128 129 // contribute icon and link to the Login Screen 130 LoginScreenHelper.registerSingleProviderLoginScreenConfig(provider.getName(), provider.getIcon(), 131 provider.getUserInfoURL(), provider.getLabel(), provider.getDescription(), 132 providers.get(provider.getName())); 133 134 } else { 135 if (Framework.isTestModeSet()) { 136 providers.put(provider.getName(), 137 new OpenIDConnectProvider(null, provider.getAccessTokenKey(), provider.getUserInfoURL(), 138 provider.getUserInfoClass(), provider.getIcon(), provider.isEnabled(), 139 redirectUriResolver, provider.getUserResolverClass(), provider.getUserMapper())); 140 } else { 141 log.error("Can not register OAuth Provider since OAuth Registry is not available"); 142 } 143 } 144 145 } 146 147 @Override 148 public void start(ComponentContext context) { 149 registerPendingProviders(); 150 } 151 152}