This is an automated email from the ASF dual-hosted git repository.

mabin pushed a commit to branch houserush-sample
in repository https://gitbox.apache.org/repos/asf/servicecomb-samples.git

commit db8821565eb92ad727d0cc0076d231fa7c87d4ce
Author: liubao <[email protected]>
AuthorDate: Fri May 17 17:12:32 2019 +0800

    using oauth 2 password mode to grant tokens
---
 authentication/README.md                           |  4 +-
 .../TokenEndpoint.java}                            | 68 +++++++++++++---------
 .../authentication/{api => server}/Token.java      |  2 +-
 .../TokenConst.java}                               | 23 +++-----
 .../TokenService.java}                             | 19 ++----
 .../edge/AuthenticationEndpoint.java               | 44 --------------
 .../edge/CustomVertxRestDispatcher.java            |  1 +
 ...cecomb.transport.rest.vertx.VertxHttpDispatcher |  2 +-
 .../authentication/AuthenticationTestCase.java     | 12 ++--
 .../authentication/BootEventListener.java          | 12 ++--
 .../authentication/gateway/ApiDispatcher.java      |  1 +
 .../src/main/resources/microservice.yaml           |  2 +-
 12 files changed, 74 insertions(+), 116 deletions(-)

diff --git a/authentication/README.md b/authentication/README.md
index 2274bb4..6d477bb 100644
--- a/authentication/README.md
+++ b/authentication/README.md
@@ -87,4 +87,6 @@ http://localhost:9093/v1/test/start
 
 测试项目同时展示了这个项目的功能,比如: AuthenticationTestCase 的测试逻辑展示了基本的认证功能,从登陆,到接口的权限检查。 
 
-
+# TODO LIST
+1. provide TLS for authentication server & edge service
+2. grant scope for INTERNAL access & EXTERNAL access 
diff --git 
a/authentication/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java
 
b/authentication/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenEndpoint.java
similarity index 51%
rename from 
authentication/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java
rename to 
authentication/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenEndpoint.java
index c777bc5..67c7ba4 100644
--- 
a/authentication/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java
+++ 
b/authentication/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenEndpoint.java
@@ -15,26 +15,32 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.authentication.api;
+package org.apache.servicecomb.authentication.server;
+
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
 
 import org.apache.servicecomb.authentication.jwt.JWTClaims;
 import org.apache.servicecomb.authentication.jwt.JsonParser;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.jwt.Jwt;
 import org.springframework.security.jwt.JwtHelper;
 import org.springframework.security.jwt.crypto.sign.Signer;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
 
-@RestSchema(schemaId = "AuthenticationEndpoint")
-@RequestMapping(path = "/v1/auth")
-public class AuthenticationEndpoint implements AuthenticationService {
+@RestSchema(schemaId = "TokenEndpoint")
+@RequestMapping(path = "/v1/oauth/token")
+public class TokenEndpoint implements TokenService {
   @Autowired
   @Qualifier("authUserDetailsService")
   private UserDetailsService userDetailsService;
@@ -48,33 +54,41 @@ public class AuthenticationEndpoint implements 
AuthenticationService {
   private Signer signer;
 
   @Override
-  @PostMapping(path = "login")
-  public Token login(@RequestParam(name = "userName") String userName,
-      @RequestParam(name = "password") String password) {
-    UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
-    if (passwordEncoder.matches(password, userDetails.getPassword())) {
-      JWTClaims claims = new JWTClaims();
-      if (userDetails.getAuthorities() != null) {
-        userDetails.getAuthorities().forEach(authority -> 
claims.addAuthority(authority.getAuthority()));
-      }
-      String content = JsonParser.unparse(claims);
-      Jwt accessToken = JwtHelper.encode(content, signer);
+  @PostMapping(path = "/", consumes = MediaType.APPLICATION_FORM_URLENCODED)
+  public Token getAccessToken(@RequestBody Map<String, String> parameters) {
+    String grantType = parameters.get(TokenConst.PARAM_GRANT_TYPE);
+
+    if (TokenConst.GRANT_TYPE_PASSWORD.equals(grantType)) {
+
+      String username = parameters.get(TokenConst.PARAM_USERNAME);
+      String password = parameters.get(TokenConst.PARAM_PASSWORD);
 
-      Token token = new Token();
-      token.setScope(claims.getScope());
-      token.setExpires_in(10 * 60);
-      token.setToken_type("bearer");
-      token.setAccess_token(accessToken.getEncoded());
-      return token;
+      try {
+        UserDetails userDetails = 
userDetailsService.loadUserByUsername(username);
+        if (passwordEncoder.matches(password, userDetails.getPassword())) {
+          JWTClaims claims = new JWTClaims();
+          if (userDetails.getAuthorities() != null) {
+            userDetails.getAuthorities().forEach(authority -> 
claims.addAuthority(authority.getAuthority()));
+          }
+          String content = JsonParser.unparse(claims);
+          Jwt accessToken = JwtHelper.encode(content, signer);
+
+          Token token = new Token();
+          token.setScope(claims.getScope());
+          token.setExpires_in(10 * 60);
+          token.setToken_type("bearer");
+          token.setAccess_token(accessToken.getEncoded());
+          return token;
+        } else {
+          return null;
+        }
+      } catch (UsernameNotFoundException e) {
+        throw new InvocationException(403, "", "forbidden");
+      }
     } else {
       return null;
     }
-  }
 
-  @Override
-  @PostMapping(path = "refresh")
-  public Token refresh(@RequestParam(name = "refreshToken") String 
refreshToken) {
-    return null;
   }
 
 }
diff --git 
a/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/api/Token.java
 
b/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/Token.java
similarity index 97%
rename from 
authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/api/Token.java
rename to 
authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/Token.java
index 94ce237..8758bd1 100644
--- 
a/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/api/Token.java
+++ 
b/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/Token.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.authentication.api;
+package org.apache.servicecomb.authentication.server;
 
 import java.util.Map;
 import java.util.Set;
diff --git 
a/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationService.java
 
b/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenConst.java
similarity index 59%
copy from 
authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationService.java
copy to 
authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenConst.java
index 77635ad..a46a7b9 100644
--- 
a/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationService.java
+++ 
b/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenConst.java
@@ -15,21 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.authentication.api;
+package org.apache.servicecomb.authentication.server;
 
-public interface AuthenticationService {
-  /**
-   * login using user name and password.
-   * @param userName user name
-   * @param password password
-   * @return After successfully login, token is created. Or null is returned. 
-   */
-  Token login(String userName, String password);
+public class TokenConst {
+  public static final String PARAM_GRANT_TYPE = "grant_type";
 
-  /**
-   * acquired new token using refresh token.
-   * @param refreshToken refresh token
-   * @return After successfully authenticated, token is created. Or null is 
returned. 
-   */
-  Token refresh(String refreshToken);
+  public static final String PARAM_USERNAME = "username";
+
+  public static final String PARAM_PASSWORD = "password";
+  
+  public static final String GRANT_TYPE_PASSWORD = "password";
 }
diff --git 
a/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationService.java
 
b/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
similarity index 59%
rename from 
authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationService.java
rename to 
authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
index 77635ad..b0cea22 100644
--- 
a/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationService.java
+++ 
b/authentication/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
@@ -15,21 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.authentication.api;
+package org.apache.servicecomb.authentication.server;
 
-public interface AuthenticationService {
-  /**
-   * login using user name and password.
-   * @param userName user name
-   * @param password password
-   * @return After successfully login, token is created. Or null is returned. 
-   */
-  Token login(String userName, String password);
+import java.util.Map;
 
-  /**
-   * acquired new token using refresh token.
-   * @param refreshToken refresh token
-   * @return After successfully authenticated, token is created. Or null is 
returned. 
-   */
-  Token refresh(String refreshToken);
+public interface TokenService {
+  Token getAccessToken(Map<String, String> parameters);
 }
diff --git 
a/authentication/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationEndpoint.java
 
b/authentication/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationEndpoint.java
deleted file mode 100644
index 68fe5d7..0000000
--- 
a/authentication/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationEndpoint.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.servicecomb.authentication.edge;
-
-import org.apache.servicecomb.authentication.api.AuthenticationService;
-import org.apache.servicecomb.authentication.api.Token;
-import org.apache.servicecomb.provider.pojo.RpcReference;
-import org.apache.servicecomb.provider.rest.common.RestSchema;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-
-@RestSchema(schemaId = "AuthenticationEndpoint")
-@RequestMapping(path = "/v1/auth")
-public class AuthenticationEndpoint {
-  @RpcReference(microserviceName = "authentication-server", schemaId = 
"AuthenticationEndpoint")
-  private AuthenticationService authenticationService;
-
-  @PostMapping(path = "login")
-  public Token login(@RequestParam(name = "userName") String userName,
-      @RequestParam(name = "password") String password) {
-    return authenticationService.login(userName, password);
-  }
-
-  @PostMapping(path = "refresh")
-  public Token refresh(@RequestParam(name = "refreshToken") String 
refreshToken) {
-    return authenticationService.refresh(refreshToken);
-  }
-}
diff --git 
a/authentication/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java
 
b/authentication/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java
index d1c6ef4..521b71c 100644
--- 
a/authentication/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java
+++ 
b/authentication/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java
@@ -45,6 +45,7 @@ import io.vertx.ext.web.RoutingContext;
 import io.vertx.ext.web.handler.CookieHandler;
 
 // copied from org.apache.servicecomb.transport.rest.vertx.VertxRestDispatcher 
1.2.0
+// TODO: using 1.2.2+ to make it simpler
 public class CustomVertxRestDispatcher extends AbstractVertxHttpDispatcher {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(VertxRestDispatcher.class);
 
diff --git 
a/authentication/api/edge-service/service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
 
b/authentication/api/edge-service/service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
index 53481f1..32c1583 100644
--- 
a/authentication/api/edge-service/service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
+++ 
b/authentication/api/edge-service/service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
@@ -15,4 +15,4 @@
 # limitations under the License.
 #
 
-org.apache.servicecomb.authentication.edge.CustomVertxRestDispatcher
\ No newline at end of file
+# org.apache.servicecomb.authentication.edge.CustomVertxRestDispatcher
\ No newline at end of file
diff --git 
a/authentication/samples/Client/src/main/java/org/apache/servicecomb/authentication/AuthenticationTestCase.java
 
b/authentication/samples/Client/src/main/java/org/apache/servicecomb/authentication/AuthenticationTestCase.java
index 61ba97f..50a4519 100644
--- 
a/authentication/samples/Client/src/main/java/org/apache/servicecomb/authentication/AuthenticationTestCase.java
+++ 
b/authentication/samples/Client/src/main/java/org/apache/servicecomb/authentication/AuthenticationTestCase.java
@@ -17,7 +17,7 @@
 
 package org.apache.servicecomb.authentication;
 
-import org.apache.servicecomb.authentication.api.Token;
+import org.apache.servicecomb.authentication.server.Token;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
@@ -38,13 +38,14 @@ public class AuthenticationTestCase implements TestCase {
   private void testHanlderAuth() {
     // get token
     MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
-    map.add("userName", "admin");
+    map.add("grant_type", "password");
+    map.add("username", "admin");
     map.add("password", "changeMyPassword");
     HttpHeaders headers = new HttpHeaders();
     headers.setContentType(MediaType.MULTIPART_FORM_DATA);
 
     Token token =
-        BootEventListener.gateEndpoint.postForObject("/v1/auth/login",
+        BootEventListener.authenticationServerTokenEndpoint.postForObject("/",
             new HttpEntity<>(map, headers),
             Token.class);
     TestMgr.check("bearer", token.getToken_type());
@@ -85,13 +86,14 @@ public class AuthenticationTestCase implements TestCase {
   private void testMethodAuth() {
     // get token
     MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
-    map.add("userName", "admin");
+    map.add("grant_type", "password");
+    map.add("username", "admin");
     map.add("password", "changeMyPassword");
     HttpHeaders headers = new HttpHeaders();
     headers.setContentType(MediaType.MULTIPART_FORM_DATA);
 
     Token token =
-        BootEventListener.gateEndpoint.postForObject("/v1/auth/login",
+        BootEventListener.authenticationServerTokenEndpoint.postForObject("/",
             new HttpEntity<>(map, headers),
             Token.class);
     TestMgr.check("bearer", token.getToken_type());
diff --git 
a/authentication/samples/Client/src/main/java/org/apache/servicecomb/authentication/BootEventListener.java
 
b/authentication/samples/Client/src/main/java/org/apache/servicecomb/authentication/BootEventListener.java
index 5512f8c..08d1bb3 100644
--- 
a/authentication/samples/Client/src/main/java/org/apache/servicecomb/authentication/BootEventListener.java
+++ 
b/authentication/samples/Client/src/main/java/org/apache/servicecomb/authentication/BootEventListener.java
@@ -22,7 +22,7 @@ import org.springframework.stereotype.Component;
 
 @Component
 public class BootEventListener implements BootListener {
-  public static GateRestTemplate authenticationServerAuthenticationEndpoint;
+  public static GateRestTemplate authenticationServerTokenEndpoint;
   public static GateRestTemplate gateEndpoint;
   public static GateRestTemplate resouceServerHandlerAuthEndpoint;
   public static GateRestTemplate resouceServerMethodAuthEndpoint;
@@ -30,14 +30,14 @@ public class BootEventListener implements BootListener {
   @Override
   public void onBootEvent(BootEvent event) {
     if (EventType.AFTER_REGISTRY.equals(event.getEventType())) {
-      authenticationServerAuthenticationEndpoint =
-          GateRestTemplate.createEdgeRestTemplate("gateway", 
"authentication-server", "AuthenticationEndpoint").init();
+      authenticationServerTokenEndpoint =
+          GateRestTemplate.createEdgeRestTemplate("edge-service", 
"authentication-server", "TokenEndpoint").init();
       gateEndpoint =
-          GateRestTemplate.createEdgeRestTemplate("gateway", null, 
null).init();
+          GateRestTemplate.createEdgeRestTemplate("edge-service", null, 
null).init();
       resouceServerHandlerAuthEndpoint =
-          GateRestTemplate.createEdgeRestTemplate("gateway", 
"resource-server", "HandlerAuthEndpoint").init();
+          GateRestTemplate.createEdgeRestTemplate("edge-service", 
"resource-server", "HandlerAuthEndpoint").init();
       resouceServerMethodAuthEndpoint =
-          GateRestTemplate.createEdgeRestTemplate("gateway", 
"resource-server", "PreMethodAuthEndpoint").init();
+          GateRestTemplate.createEdgeRestTemplate("edge-service", 
"resource-server", "PreMethodAuthEndpoint").init();
     }
 
   }
diff --git 
a/authentication/samples/EdgeService/src/main/java/org/apache/servicecomb/authentication/gateway/ApiDispatcher.java
 
b/authentication/samples/EdgeService/src/main/java/org/apache/servicecomb/authentication/gateway/ApiDispatcher.java
index 9f45550..7642268 100644
--- 
a/authentication/samples/EdgeService/src/main/java/org/apache/servicecomb/authentication/gateway/ApiDispatcher.java
+++ 
b/authentication/samples/EdgeService/src/main/java/org/apache/servicecomb/authentication/gateway/ApiDispatcher.java
@@ -27,6 +27,7 @@ import io.vertx.ext.web.Router;
 import io.vertx.ext.web.RoutingContext;
 import io.vertx.ext.web.handler.CookieHandler;
 
+//TODO: using 1.2.2+ to make it simpler
 public class ApiDispatcher extends AbstractEdgeDispatcher {
   @Override
   public int getOrder() {
diff --git 
a/authentication/samples/EdgeService/src/main/resources/microservice.yaml 
b/authentication/samples/EdgeService/src/main/resources/microservice.yaml
index 2eda242..7531d52 100644
--- a/authentication/samples/EdgeService/src/main/resources/microservice.yaml
+++ b/authentication/samples/EdgeService/src/main/resources/microservice.yaml
@@ -22,7 +22,7 @@ servicecomb-config-order: 100
 APPLICATION_ID: authentication-application
 service_description:
   version: 0.0.1
-  name: gateway
+  name: edge-service
   environment: development
 
 servicecomb:

Reply via email to