ref #6118 OAuth2 AuthorizationServer implemented
authorAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Fri, 7 Oct 2016 10:47:43 +0000 (12:47 +0200)
committerAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Tue, 11 Oct 2016 08:01:48 +0000 (10:01 +0200)
cdmlib-remote-webapp/src/main/webapp/WEB-INF/applicationContext.xml
cdmlib-remote/.springBeans
cdmlib-remote/pom.xml
cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/config/AuthorizationServerConfiguration.java [new file with mode: 0644]
cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/oauth2/CdmUserApprovalHandler.java [new file with mode: 0644]
pom.xml

index 7193dd938dab7d415e249ac7b6abf5b3afe2219b..0dd6fa17273e449c87f90d93a7a4abd181bae864 100644 (file)
   <!-- CONFIGURE WEB APPLICATION HERE -->
   <import resource="datasources/configurable.xml" />
   
-  <!-- bootstrap the WebSecurityConfiguration -->
-  <bean class="eu.etaxonomy.cdm.remote.config.MultiWebSecurityConfiguration"></bean>
 
   <bean class="eu.etaxonomy.cdm.remote.config.LoggingConfigurer">
   </bean>
 
+  <!-- bootstrap the WebSecurityConfiguration -->
+  <bean class="eu.etaxonomy.cdm.remote.config.MultiWebSecurityConfiguration">
+  </bean>
+  <bean class="eu.etaxonomy.cdm.remote.config.AuthorizationServerConfiguration">
+  </bean>
+
   <!-- OAI-PMH TODO externalize? -->
   <bean name="taxonOaiPmhController"
     class="eu.etaxonomy.cdm.remote.controller.oaipmh.TaxonOaiPmhController">
index c3586dc9636c18e9c6f6a9ccafa80626642e5dfb..20a9f05deb4c7246094f4dc21ee22a903c03f4fe 100644 (file)
@@ -1,14 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beansProjectDescription>
        <version>1</version>
-       <pluginVersion><![CDATA[3.4.0.201310051539-RELEASE]]></pluginVersion>
+       <pluginVersion><![CDATA[3.6.3.201411271034-RELEASE]]></pluginVersion>
        <configSuffixes>
                <configSuffix><![CDATA[xml]]></configSuffix>
        </configSuffixes>
        <enableImports><![CDATA[false]]></enableImports>
        <configs>
-               <config>src/main/resources/eu/etaxonomy/cdm/remote-security.xml</config>
        </configs>
+       <autoconfigs>
+       </autoconfigs>
        <configSets>
        </configSets>
 </beansProjectDescription>
index 761ac5867beb8c26315f7d1bebc513aa1b70a278..938a615aaffdd247d28fc1de9a39b28d992fd228 100644 (file)
@@ -60,7 +60,6 @@
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
     </dependency>
-    
     <dependency>
       <groupId>org.springmodules</groupId>
       <artifactId>spring-modules-cache</artifactId>
     <dependency>
       <groupId>org.springframework.security</groupId>
       <artifactId>spring-security-core</artifactId>
-      <version>${spring-security.version}</version>
     </dependency>
     <dependency>
       <groupId>org.springframework.security</groupId>
       <artifactId>spring-security-config</artifactId>
-      <version>${spring-security.version}</version>
     </dependency>
     <dependency>
       <groupId>org.springframework.security</groupId>
       <artifactId>spring-security-web</artifactId>
-      <version>${spring-security.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.security.oauth</groupId>
+      <artifactId>spring-security-oauth2</artifactId>
     </dependency>
 <!--     <dependency> -->
 <!--       <groupId>org.unitils</groupId> -->
diff --git a/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/config/AuthorizationServerConfiguration.java b/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/config/AuthorizationServerConfiguration.java
new file mode 100644 (file)
index 0000000..8c2a3d1
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.remote.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
+import org.springframework.security.oauth2.provider.ClientDetailsService;
+import org.springframework.security.oauth2.provider.approval.ApprovalStore;
+import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore;
+import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
+import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
+
+import eu.etaxonomy.cdm.remote.oauth2.CdmUserApprovalHandler;
+
+/**
+ * @author a.kohlbecker
+ * @date Oct 6, 2016
+ *
+ */
+@Configuration
+@EnableAuthorizationServer
+public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
+
+    /**
+     *
+     */
+    private static final String RESOURCE_ID = "all-services";
+    /**
+     *
+     */
+    private static final String CLIENT_ID = "any-client";
+
+    @Autowired
+    private ClientDetailsService clientDetailsService;
+
+    @Autowired
+    private UserApprovalHandler userApprovalHandler;
+
+    @Autowired
+    private AuthenticationManager authenticationManager;
+
+
+    @Override
+    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
+        clients.inMemory().withClient(CLIENT_ID)
+            .resourceIds(RESOURCE_ID)
+            .authorizedGrantTypes("implicit")
+            .authorities("ROLE_USER")
+            .scopes("read", "write")
+            .autoApprove("read");
+    }
+
+    @Bean
+    public ApprovalStore approvalStore() {
+        return new InMemoryApprovalStore();
+    }
+
+    @Bean
+    public TokenStore tokenStore() {
+        return new InMemoryTokenStore();
+    }
+
+    @Override
+    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
+        endpoints.tokenStore(tokenStore()).userApprovalHandler(userApprovalHandler)
+        .authenticationManager(authenticationManager);
+    }
+
+    @Bean
+    @Lazy
+    @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
+    public CdmUserApprovalHandler userApprovalHandler() throws Exception {
+        CdmUserApprovalHandler handler = new CdmUserApprovalHandler();
+        handler.setApprovalStore(approvalStore());
+        handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
+        handler.setClientDetailsService(clientDetailsService);
+        handler.setUseApprovalStore(false);
+        return handler;
+    }
+}
+
diff --git a/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/oauth2/CdmUserApprovalHandler.java b/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/oauth2/CdmUserApprovalHandler.java
new file mode 100644 (file)
index 0000000..a1eedcd
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * This class has been taken from org.springframework.security.oauth.examples.sparklr
+ *
+ * ----------------------------------------------------------------------------------
+ *
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package eu.etaxonomy.cdm.remote.oauth2;
+
+import java.util.Collection;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.provider.AuthorizationRequest;
+import org.springframework.security.oauth2.provider.ClientDetails;
+import org.springframework.security.oauth2.provider.ClientDetailsService;
+import org.springframework.security.oauth2.provider.ClientRegistrationException;
+import org.springframework.security.oauth2.provider.approval.ApprovalStoreUserApprovalHandler;
+
+/**
+ * @author a.kohlbecker
+ * @date Oct 6, 2016
+ *
+ */
+public class CdmUserApprovalHandler extends ApprovalStoreUserApprovalHandler {
+
+    private boolean useApprovalStore = true;
+
+    private ClientDetailsService clientDetailsService;
+
+    /**
+     * Service to load client details (optional) for auto approval checks.
+     *
+     * @param clientDetailsService a client details service
+     */
+    @Override
+    public void setClientDetailsService(ClientDetailsService clientDetailsService) {
+        this.clientDetailsService = clientDetailsService;
+        super.setClientDetailsService(clientDetailsService);
+    }
+
+    /**
+     * @param useApprovalStore the useTokenServices to set
+     */
+    public void setUseApprovalStore(boolean useApprovalStore) {
+        this.useApprovalStore = useApprovalStore;
+    }
+
+    /**
+     * Allows automatic approval for a white list of clients in the implicit grant case.
+     *
+     * @param authorizationRequest The authorization request.
+     * @param userAuthentication the current user authentication
+     *
+     * @return An updated request if it has already been approved by the current user.
+     */
+    @Override
+    public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest,
+            Authentication userAuthentication) {
+
+        boolean approved = false;
+        // If we are allowed to check existing approvals this will short circuit the decision
+        if (useApprovalStore) {
+            authorizationRequest = super.checkForPreApproval(authorizationRequest, userAuthentication);
+            approved = authorizationRequest.isApproved();
+        }
+        else {
+            if (clientDetailsService != null) {
+                Collection<String> requestedScopes = authorizationRequest.getScope();
+                try {
+                    ClientDetails client = clientDetailsService
+                            .loadClientByClientId(authorizationRequest.getClientId());
+                    for (String scope : requestedScopes) {
+                        if (client.isAutoApprove(scope)) {
+                            approved = true;
+                            break;
+                        }
+                    }
+                }
+                catch (ClientRegistrationException e) {
+                }
+            }
+        }
+        authorizationRequest.setApproved(approved);
+
+        return authorizationRequest;
+
+    }
+
+}
diff --git a/pom.xml b/pom.xml
index 0d0105fe119593e9cc24ed47d990624d11f1457d..a9a969d7f271e131c2e82d821d1ffe0ae080e9bf 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -27,6 +27,8 @@
     <java.codelevel>1.7</java.codelevel>
     <spring.version>4.2.4.RELEASE</spring.version>
     <spring-security.version>4.0.3.RELEASE</spring-security.version>
+    <spring-security-oauth2.version>2.0.11.RELEASE</spring-security-oauth2.version>
+    <spring-cloud.version>1.1.3.RELEASE</spring-cloud.version>
        <hibernate.version>5.0.7.Final</hibernate.version>
        <hibernate-validator.version>5.2.2.Final</hibernate-validator.version>
     <hibernate-search.version>5.5.2.Final</hibernate-search.version>
         <artifactId>spring-security-web</artifactId>
         <version>${spring-security.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.springframework.security.oauth</groupId>
+      <artifactId>spring-security-oauth2</artifactId>
+        <version>${spring-security-oauth2.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework.cloud</groupId>
+        <artifactId>spring-cloud-security</artifactId>
+        <version>${spring-security.version}</version>
+      </dependency>
 
       <!-- ******* SERVLET/JSP/JSF ******* -->
       <dependency>