001/*******************************************************************************
002 * Copyright 2017 The MIT Internet Trust Consortium
003 *
004 * Portions copyright 2011-2013 The MITRE Corporation
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 *******************************************************************************/
018package org.mitre.openid.connect.client.keypublisher;
019
020import java.util.Map;
021import java.util.UUID;
022
023import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
024import org.mitre.openid.connect.view.JWKSetView;
025import org.springframework.beans.BeansException;
026import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
027import org.springframework.beans.factory.support.BeanDefinitionBuilder;
028import org.springframework.beans.factory.support.BeanDefinitionRegistry;
029import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
030import org.springframework.web.servlet.ModelAndView;
031
032import com.google.common.base.Strings;
033import com.nimbusds.jose.jwk.JWK;
034
035/**
036 * @author jricher
037 *
038 */
039public class ClientKeyPublisher implements BeanDefinitionRegistryPostProcessor {
040
041        private JWTSigningAndValidationService signingAndValidationService;
042
043        private String jwkPublishUrl;
044
045        private BeanDefinitionRegistry registry;
046
047        private String jwkViewName = JWKSetView.VIEWNAME;
048
049        /**
050         * If the jwkPublishUrl field is set on this bean, set up a listener on that URL to publish keys.
051         */
052        @Override
053        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
054                if (!Strings.isNullOrEmpty(getJwkPublishUrl())) {
055
056                        // add a mapping to this class
057                        BeanDefinitionBuilder clientKeyMapping = BeanDefinitionBuilder.rootBeanDefinition(ClientKeyPublisherMapping.class);
058                        // custom view resolver
059                        BeanDefinitionBuilder viewResolver = BeanDefinitionBuilder.rootBeanDefinition(JwkViewResolver.class);
060
061                        if (!Strings.isNullOrEmpty(getJwkPublishUrl())) {
062                                clientKeyMapping.addPropertyValue("jwkPublishUrl", getJwkPublishUrl());
063
064                                // randomize view name to make sure it doesn't conflict with local views
065                                jwkViewName = JWKSetView.VIEWNAME + "-" + UUID.randomUUID().toString();
066                                viewResolver.addPropertyValue("jwkViewName", jwkViewName);
067
068                                // view bean
069                                BeanDefinitionBuilder jwkView = BeanDefinitionBuilder.rootBeanDefinition(JWKSetView.class);
070                                registry.registerBeanDefinition(JWKSetView.VIEWNAME, jwkView.getBeanDefinition());
071                                viewResolver.addPropertyReference("jwk", JWKSetView.VIEWNAME);
072                        }
073
074                        registry.registerBeanDefinition("clientKeyMapping", clientKeyMapping.getBeanDefinition());
075                        registry.registerBeanDefinition("jwkViewResolver", viewResolver.getBeanDefinition());
076
077                }
078
079        }
080
081        /* (non-Javadoc)
082         * @see org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(org.springframework.beans.factory.support.BeanDefinitionRegistry)
083         */
084        @Override
085        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
086                this.registry = registry;
087        }
088
089        /**
090         * Return a view to publish all keys in JWK format. Only used if jwkPublishUrl is set.
091         * @return
092         */
093        public ModelAndView publishClientJwk() {
094
095                // map from key id to key
096                Map<String, JWK> keys = signingAndValidationService.getAllPublicKeys();
097
098                return new ModelAndView(jwkViewName, "keys", keys);
099        }
100
101        /**
102         * @return the jwkPublishUrl
103         */
104        public String getJwkPublishUrl() {
105                return jwkPublishUrl;
106        }
107
108        /**
109         * @param jwkPublishUrl the jwkPublishUrl to set
110         */
111        public void setJwkPublishUrl(String jwkPublishUrl) {
112                this.jwkPublishUrl = jwkPublishUrl;
113        }
114
115        /**
116         * @return the signingAndValidationService
117         */
118        public JWTSigningAndValidationService getSigningAndValidationService() {
119                return signingAndValidationService;
120        }
121
122        /**
123         * @param signingAndValidationService the signingAndValidationService to set
124         */
125        public void setSigningAndValidationService(JWTSigningAndValidationService signingAndValidationService) {
126                this.signingAndValidationService = signingAndValidationService;
127        }
128
129
130}