You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ma...@apache.org on 2019/08/07 03:19:16 UTC

[servicecomb-samples] 16/32: authentication: add gateway & resource server logic

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 3a10a7b7503a3e73e5f292f0c447494bc27b3c41
Author: liubao <ba...@huawei.com>
AuthorDate: Thu May 9 19:15:26 2019 +0800

    authentication: add gateway & resource server logic
---
 .../AuthenticationConfiguration.java               | 48 ++++++++++-----
 .../service/AuthenticationServiceImpl.java         | 18 +++---
 .../main/resources/META-INF/spring/user.bean.xml   | 64 +++++---------------
 .../src/main/resources/config/SessionMapper.xml    | 57 ------------------
 .../src/main/resources/config/UserMapper.xml       | 46 --------------
 .../src/main/resources/config/create_db_user.sql   | 46 --------------
 .../src/main/resources/microservice.yaml           |  1 +
 authentication/Gateway/pom.xml                     | 50 +++++++++++-----
 .../gateway/ApiDispatcher.java                     |  2 +-
 .../gateway/AuthHandler.java                       | 21 ++++++-
 .../gateway/AuthenticationConfiguration.java       | 14 +++++
 .../gateway}/AuthenticationEndpoint.java           | 13 ++--
 .../gateway/AuthenticationFilter.java              | 30 ++++++++++
 .../gateway/CustomVertxRestDispatcher.java         |  6 +-
 .../gateway/EdgeSSLCustom.java                     |  2 +-
 .../gateway/GatewayMain.java                       |  2 +-
 .../gateway/InternalAccessHandler.java             |  2 +-
 .../gateway/StaticWebpageDispatcher.java           |  2 +-
 ...servicecomb.common.rest.filter.HttpServerFilter |  1 +
 ...cecomb.transport.rest.vertx.VertxHttpDispatcher |  6 +-
 .../src/main/resources/config/cse.handler.xml      |  4 +-
 .../Gateway/src/main/resources/microservice.yaml   |  3 +
 .../authentication/test/PatternTest.java           | 19 ++++++
 authentication/ResourceServer/pom.xml              | 18 ++++++
 .../resource/AccessConfiguration.java              | 20 +++++++
 .../resource/AccessConfigurationManager.java       | 19 ++++++
 .../resource/AuthenticationConfiguration.java      | 14 +++++
 .../resource/HandlerAuthEndpoint.java              | 29 +++++++++
 .../resource/PreMethodAuthEndpoint.java            | 33 ++++++++++
 .../resource/ResourceAuthHandler.java              | 70 ++++++++++++++++++++++
 .../spring/{user.bean.xml => resource.bean.xml}    | 26 --------
 .../src/main/resources/config/SessionMapper.xml    | 57 ------------------
 .../src/main/resources/config/UserMapper.xml       | 46 --------------
 .../src/main/resources/config/create_db_user.sql   | 46 --------------
 .../src/main/resources/config/cse.handler.xml}     | 14 ++---
 .../src/main/resources/config/mybatis-config.xml   | 27 ---------
 .../src/main/resources/microservice.yaml           | 18 +++++-
 .../authentication/api/AuthenticationEndpoint.java |  5 +-
 authentication/api/common/service/pom.xml          | 25 ++++++++
 .../servicecomb/authentication/jwt/JWTClaims.java  | 42 +++++++++----
 .../servicecomb/authentication/util/Constants.java |  9 +++
 41 files changed, 493 insertions(+), 482 deletions(-)

diff --git a/authentication/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java b/authentication/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java
index 77a6342..5840fc3 100644
--- a/authentication/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java
+++ b/authentication/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java
@@ -1,28 +1,46 @@
 package org.apache.servicecomb.authentication;
 
+import java.util.Arrays;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
+import org.springframework.security.jwt.crypto.sign.MacSigner;
+import org.springframework.security.jwt.crypto.sign.Signer;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager;
 
 @Configuration
 public class AuthenticationConfiguration {
+  @Autowired
+  @Qualifier("authPasswordEncoder")
+  private PasswordEncoder passwordEncoder;
+
   @Bean(name = "authPasswordEncoder")
-  private PasswordEncoder authPasswordEncoder() {
-    return new PasswordEncoder() {
+  public PasswordEncoder authPasswordEncoder() {
+    return new Pbkdf2PasswordEncoder();
+  }
 
-      @Override
-      public String encode(CharSequence rawPassword) {
-        // TODO Auto-generated method stub
-        return null;
-      }
+  @Bean(name = "authSigner")
+  public Signer authSigner() {
+    return new MacSigner("Please change this key.");
+  }
 
-      @Override
-      public boolean matches(CharSequence rawPassword, String encodedPassword) {
-        // TODO Auto-generated method stub
-        return false;
-      }
-      
-    };
+  @Bean(name = "authUserDetailsService")
+  public UserDetailsService authUserDetailsService() {
+    InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
+    UserDetails uAdmin = new User("admin", passwordEncoder.encode("changeMyPassword"),
+        Arrays.asList(new SimpleGrantedAuthority("ADMIN")));
+    UserDetails uGuest = new User("guest", passwordEncoder.encode("changeMyPassword"),
+        Arrays.asList(new SimpleGrantedAuthority("GUEST")));
+    manager.createUser(uAdmin);
+    manager.createUser(uGuest);
+    return manager;
   }
-  
 }
diff --git a/authentication/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/service/AuthenticationServiceImpl.java b/authentication/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/service/AuthenticationServiceImpl.java
index a6e856a..cfbe22b 100644
--- a/authentication/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/service/AuthenticationServiceImpl.java
+++ b/authentication/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/service/AuthenticationServiceImpl.java
@@ -21,10 +21,10 @@ import org.apache.servicecomb.authentication.api.AuthenticationService;
 import org.apache.servicecomb.authentication.api.Token;
 import org.apache.servicecomb.authentication.jwt.JWTClaims;
 import org.apache.servicecomb.authentication.jwt.JsonParser;
-import org.apache.servicecomb.authentication.user.User;
-import org.apache.servicecomb.authentication.user.UserStore;
 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.crypto.password.PasswordEncoder;
 import org.springframework.security.jwt.Jwt;
 import org.springframework.security.jwt.JwtHelper;
@@ -34,8 +34,8 @@ import org.springframework.stereotype.Service;
 @Service
 public class AuthenticationServiceImpl implements AuthenticationService {
   @Autowired
-  @Qualifier("authUserStore")
-  private UserStore userStore;
+  @Qualifier("authUserDetailsService")
+  private UserDetailsService userDetailsService;
 
   @Autowired
   @Qualifier("authPasswordEncoder")
@@ -47,17 +47,17 @@ public class AuthenticationServiceImpl implements AuthenticationService {
 
   @Override
   public Token login(String userName, String password) {
-    User user = userStore.loadUserByUsername(userName);
-    if (passwordEncoder.matches(password, user.getPassword())) {
+    UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
+    if (passwordEncoder.matches(password, userDetails.getPassword())) {
       JWTClaims claims = new JWTClaims();
-      if (user.getRoles() != null) {
-        user.getRoles().forEach(role -> claims.addRole(role.getRoleName()));
+      if (userDetails.getAuthorities() != null) {
+        userDetails.getAuthorities().forEach(authority -> claims.addAuthority(authority.getAuthority()));
       }
-      claims.setScope("read");
       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());
diff --git a/authentication/AuthenticationServer/src/main/resources/META-INF/spring/user.bean.xml b/authentication/AuthenticationServer/src/main/resources/META-INF/spring/user.bean.xml
index 661608f..b33e5c9 100644
--- a/authentication/AuthenticationServer/src/main/resources/META-INF/spring/user.bean.xml
+++ b/authentication/AuthenticationServer/src/main/resources/META-INF/spring/user.bean.xml
@@ -1,56 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ 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.
-  -->
+<!-- ~ 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. -->
 
 <beans xmlns="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
-    xmlns:util="http://www.springframework.org/schema/util"
-    xmlns:context="http://www.springframework.org/schema/context"
-    xmlns:tx="http://www.springframework.org/schema/tx"
-    xsi:schemaLocation="
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+  xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
+  xmlns:tx="http://www.springframework.org/schema/tx"
+  xsi:schemaLocation="
 		http://www.springframework.org/schema/beans classpath:org/springframework/beans/factory/xml/spring-beans-3.0.xsd
         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
 		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
   <bean id="servicecomb.samples.executor.groupThreadPool" class="org.apache.servicecomb.core.executor.GroupExecutor"
-    init-method="init"/>
-    
-    <bean id="dataSource"
-        class="org.apache.commons.dbcp2.BasicDataSource"
-        destroy-method="close">
-        <property name="driverClassName" value="${db.driverClassName:com.mysql.jdbc.Driver}" />
-        <property name="url"
-            value="${db.url:jdbc:mysql://localhost/porter_user_db}" />
-        <property name="username" value="${db.username:root}" />
-        <property name="password" value="${db.password:}" />
-    </bean>
-
-    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
-        <property name="dataSource" ref="dataSource" />
-        <property name="configLocation" value="classpath:/config/mybatis-config.xml"></property>
-    </bean>
-
-    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
-        <property name="mapperInterface"
-            value="org.apache.servicecomb.samples.porter.user.dao.UserMapper" />
-        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
-    </bean>
-    <bean id="sessionMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
-        <property name="mapperInterface"
-            value="org.apache.servicecomb.samples.porter.user.dao.SessionMapper" />
-        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
-    </bean>
+    init-method="init" />
 </beans>
\ No newline at end of file
diff --git a/authentication/AuthenticationServer/src/main/resources/config/SessionMapper.xml b/authentication/AuthenticationServer/src/main/resources/config/SessionMapper.xml
deleted file mode 100644
index 989e786..0000000
--- a/authentication/AuthenticationServer/src/main/resources/config/SessionMapper.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="org.apache.servicecomb.samples.porter.user.dao.SessionMapper">
-    <resultMap id="sessionInfo" type="org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel">
-        <result column="ID" jdbcType="INTEGER" property="id" />
-        <result column="SESSION_ID" jdbcType="VARCHAR" property="sessiondId" />
-        <result column="USER_NAME" jdbcType="VARCHAR" property="userName" />
-        <result column="ROLE_NAME" jdbcType="VARCHAR" property="roleName" />
-        <result column="CREATION_TIME" jdbcType="TIMESTAMP" property="creationTime" />
-        <result column="ACTIVE_TIME" jdbcType="TIMESTAMP" property="activeTime" />
-    </resultMap>
-
-    <sql id="all_column">
-        ID, SESSION_ID, USER_NAME, ROLE_NAME, CREATION_TIME, ACTIVE_TIME
-    </sql>
-
-    <sql id="all_column_auto">
-        SESSION_ID, USER_NAME, ROLE_NAME
-    </sql>
-
-    <insert id="createSession" parameterType="org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel">
-        insert into T_SESSION (
-        <include refid="all_column_auto" />
-        )
-        values (#{sessiondId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR},
-        #{roleName,jdbcType=VARCHAR})
-    </insert>
-
-    <select id="getSessioinInfo" parameterType="java.lang.String"
-        resultMap="sessionInfo">
-        select
-        <include refid="all_column" />
-        from T_SESSION where SESSION_ID = #{0,jdbcType=VARCHAR}
-    </select>
-    
-    <update id="updateSessionInfo" parameterType="java.lang.String">
-        update T_SESSION
-        set CREATION_TIME = CREATION_TIME where SESSION_ID = #{0,jdbcType=VARCHAR};
-    </update>
-</mapper>
\ No newline at end of file
diff --git a/authentication/AuthenticationServer/src/main/resources/config/UserMapper.xml b/authentication/AuthenticationServer/src/main/resources/config/UserMapper.xml
deleted file mode 100644
index c02e60d..0000000
--- a/authentication/AuthenticationServer/src/main/resources/config/UserMapper.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="org.apache.servicecomb.samples.porter.user.dao.UserMapper">
-    <resultMap id="userInfo" type="org.apache.servicecomb.samples.porter.user.dao.UserInfo">
-        <result column="ID" jdbcType="INTEGER" property="id" />
-        <result column="USER_NAME" jdbcType="VARCHAR" property="userName" />
-        <result column="PASSWORD" jdbcType="VARCHAR" property="password" />
-        <result column="ROLE_NAME" jdbcType="VARCHAR" property="roleName" />
-    </resultMap>
-
-    <sql id="all_column">
-        ID, USER_NAME, PASSWORD, ROLE_NAME
-    </sql>
-
-    <insert id="createUser" parameterType="org.apache.servicecomb.samples.porter.user.dao.UserInfo">
-        insert into T_USER (
-        <include refid="all_column" />
-        )
-        values (#{id,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR},
-        #{password,jdbcType=VARCHAR},#{roleName,jdbcType=VARCHAR})
-    </insert>
-
-    <select id="getUserInfo" parameterType="java.lang.String"
-        resultMap="userInfo">
-        select
-        <include refid="all_column" />
-        from T_USER where USER_NAME = #{0,jdbcType=VARCHAR}
-    </select>
-</mapper>
\ No newline at end of file
diff --git a/authentication/AuthenticationServer/src/main/resources/config/create_db_user.sql b/authentication/AuthenticationServer/src/main/resources/config/create_db_user.sql
deleted file mode 100644
index a07c5d9..0000000
--- a/authentication/AuthenticationServer/src/main/resources/config/create_db_user.sql
+++ /dev/null
@@ -1,46 +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.
- */
-
-CREATE DATABASE IF NOT EXISTS porter_user_db;
-
-USE porter_user_db;
-
-DROP TABLE IF EXISTS T_USER;
-
-CREATE TABLE `T_USER` (
-  `ID`  INTEGER(8) NOT NULL AUTO_INCREMENT COMMENT 'user id',
-  `USER_NAME`  VARCHAR(64) NOT NULL COMMENT 'user name',
-  `PASSWORD`  VARCHAR(64) NOT NULL COMMENT 'user password',
-  `ROLE_NAME`  VARCHAR(64) NOT NULL COMMENT 'user role',
-  PRIMARY KEY (`ID`)
-);
-
-#### password is encrypted for test
-insert into T_USER(USER_NAME, PASSWORD, ROLE_NAME) values("admin", "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "admin");
-insert into T_USER(USER_NAME, PASSWORD, ROLE_NAME) values("guest", "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "guest");
-
-DROP TABLE IF EXISTS T_SESSION;
-
-CREATE TABLE `T_SESSION` (
-  `ID`  INTEGER(8) NOT NULL AUTO_INCREMENT COMMENT 'id',
-  `SESSION_ID`  VARCHAR(64) NOT NULL COMMENT 'session id',
-  `USER_NAME`  VARCHAR(64) NOT NULL COMMENT 'user name',
-  `ROLE_NAME`  VARCHAR(64) NOT NULL COMMENT 'user role',
-  `CREATION_TIME`  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'creation time',
-  `ACTIVE_TIME`  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'last active time',
-  PRIMARY KEY (`ID`)
-);
diff --git a/authentication/AuthenticationServer/src/main/resources/microservice.yaml b/authentication/AuthenticationServer/src/main/resources/microservice.yaml
index 1e6b0af..dfedc0f 100644
--- a/authentication/AuthenticationServer/src/main/resources/microservice.yaml
+++ b/authentication/AuthenticationServer/src/main/resources/microservice.yaml
@@ -23,6 +23,7 @@ APPLICATION_ID: authentication-application
 service_description:
   version: 0.0.1
   name: authentication-server
+  environment: development
 
 servicecomb:
   service:
diff --git a/authentication/Gateway/pom.xml b/authentication/Gateway/pom.xml
index 9223b6b..932669e 100644
--- a/authentication/Gateway/pom.xml
+++ b/authentication/Gateway/pom.xml
@@ -1,19 +1,14 @@
-<!--
-  ~ 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.
-  -->
+<!-- ~ 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. -->
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
@@ -37,11 +32,29 @@
         <type>pom</type>
         <scope>import</scope>
       </dependency>
+      <dependency>
+        <groupId>org.apache.servicecomb.authentication</groupId>
+        <artifactId>authentication-common-api-endpoint</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.servicecomb.authentication</groupId>
+        <artifactId>authentication-server-api-service</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
   <dependencies>
     <dependency>
+      <groupId>org.apache.servicecomb.authentication</groupId>
+      <artifactId>authentication-common-api-endpoint</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.authentication</groupId>
+      <artifactId>authentication-server-api-service</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>solution-basic</artifactId>
     </dependency>
@@ -53,6 +66,11 @@
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>edge-core</artifactId>
     </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/ApiDispatcher.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/ApiDispatcher.java
similarity index 97%
rename from authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/ApiDispatcher.java
rename to authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/ApiDispatcher.java
index e801ebd..9f45550 100644
--- a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/ApiDispatcher.java
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/ApiDispatcher.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.samples.porter.gateway;
+package org.apache.servicecomb.authentication.gateway;
 
 import java.util.Map;
 
diff --git a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/AuthHandler.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthHandler.java
similarity index 55%
rename from authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/AuthHandler.java
rename to authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthHandler.java
index 7119753..d6b879a 100644
--- a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/AuthHandler.java
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthHandler.java
@@ -15,17 +15,34 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.samples.porter.gateway;
+package org.apache.servicecomb.authentication.gateway;
 
+import org.apache.servicecomb.authentication.util.Constants;
 import org.apache.servicecomb.core.Handler;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.springframework.security.jwt.Jwt;
+import org.springframework.security.jwt.JwtHelper;
+import org.springframework.security.jwt.crypto.sign.InvalidSignatureException;
 
 
 public class AuthHandler implements Handler {
   @Override
   public void handle(Invocation invocation, AsyncResponse asyncResponse) throws Exception {
-    // TODO check session
+    String token = invocation.getContext(Constants.CONTEXT_HEADER_AUTHORIZATION);
+    if (token == null) {
+      asyncResponse.consumerFail(new InvocationException(403, "forbidden", "not authenticated"));
+      return;
+    }
+    Jwt jwt = JwtHelper.decode(token);
+    try {
+      jwt.verifySignature(BeanUtils.getBean("authSigner"));
+    } catch (InvalidSignatureException e) {
+      asyncResponse.consumerFail(new InvocationException(403, "forbidden", "not authenticated"));
+      return;
+    }
     invocation.next(asyncResponse);
   }
 }
diff --git a/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationConfiguration.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationConfiguration.java
new file mode 100644
index 0000000..b188402
--- /dev/null
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationConfiguration.java
@@ -0,0 +1,14 @@
+package org.apache.servicecomb.authentication.gateway;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.jwt.crypto.sign.MacSigner;
+import org.springframework.security.jwt.crypto.sign.Signer;
+
+@Configuration
+public class AuthenticationConfiguration {
+  @Bean(name = "authSigner")
+  public Signer authSigner() {
+    return new MacSigner("Please change this key.");
+  }
+}
diff --git a/authentication/api/AuthenticationServer/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationEndpoint.java
similarity index 74%
copy from authentication/api/AuthenticationServer/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java
copy to authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationEndpoint.java
index dfc9c51..021b337 100644
--- a/authentication/api/AuthenticationServer/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationEndpoint.java
@@ -15,24 +15,29 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.authentication.api;
+package org.apache.servicecomb.authentication.gateway;
 
+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.beans.factory.annotation.Autowired;
+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/login")
+@RequestMapping(path = "/v1/auth")
 public class AuthenticationEndpoint {
-  @Autowired
+  @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/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationFilter.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationFilter.java
new file mode 100644
index 0000000..a6817bf
--- /dev/null
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationFilter.java
@@ -0,0 +1,30 @@
+package org.apache.servicecomb.authentication.gateway;
+
+import org.apache.servicecomb.authentication.util.Constants;
+import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.swagger.invocation.Response;
+
+public class AuthenticationFilter implements HttpServerFilter {
+
+  @Override
+  public int getOrder() {
+    return 0;
+  }
+
+  @Override
+  public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+    String authentication = requestEx.getHeader(Constants.HTTP_HEADER_AUTHORIZATION);
+    if (authentication != null) {
+      String[] tokens = authentication.split(" ");
+      if (tokens.length == 2) {
+        if (tokens[0].equals("Bearer")) {
+          invocation.addContext(Constants.CONTEXT_HEADER_AUTHORIZATION, tokens[1]);
+        }
+      }
+    }
+    return null;
+  }
+
+}
diff --git a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/CustomVertxRestDispatcher.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/CustomVertxRestDispatcher.java
similarity index 98%
rename from authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/CustomVertxRestDispatcher.java
rename to authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/CustomVertxRestDispatcher.java
index a2941be..8d7472f 100644
--- a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/CustomVertxRestDispatcher.java
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/CustomVertxRestDispatcher.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.samples.porter.gateway;
+package org.apache.servicecomb.authentication.gateway;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
@@ -44,7 +44,7 @@ import io.vertx.ext.web.Router;
 import io.vertx.ext.web.RoutingContext;
 import io.vertx.ext.web.handler.CookieHandler;
 
-// copied from org.apache.servicecomb.transport.rest.vertx.VertxRestDispatcher
+// copied from org.apache.servicecomb.transport.rest.vertx.VertxRestDispatcher 1.2.0
 public class CustomVertxRestDispatcher extends AbstractVertxHttpDispatcher {
   private static final Logger LOGGER = LoggerFactory.getLogger(VertxRestDispatcher.class);
 
@@ -62,7 +62,7 @@ public class CustomVertxRestDispatcher extends AbstractVertxHttpDispatcher {
 
   @Override
   public void init(Router router) {
-    String regex = "[/v1/log/|/inspector|/v1/auth](.*)";
+    String regex = "(/v1/log|/inspector|/v1/auth)/(.*)";
     router.routeWithRegex(regex).handler(CookieHandler.create());
     router.routeWithRegex(regex).handler(createBodyHandler());
     router.routeWithRegex(regex).failureHandler(this::failureHandler).handler(this::onRequest);
diff --git a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/EdgeSSLCustom.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/EdgeSSLCustom.java
similarity index 95%
rename from authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/EdgeSSLCustom.java
rename to authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/EdgeSSLCustom.java
index 159c10d..0fb1268 100644
--- a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/EdgeSSLCustom.java
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/EdgeSSLCustom.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.samples.porter.gateway;
+package org.apache.servicecomb.authentication.gateway;
 
 import java.io.File;
 
diff --git a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/GatewayMain.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/GatewayMain.java
similarity index 94%
rename from authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/GatewayMain.java
rename to authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/GatewayMain.java
index a219d2d..862e6c3 100644
--- a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/GatewayMain.java
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/GatewayMain.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.samples.porter.gateway;
+package org.apache.servicecomb.authentication.gateway;
 
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 
diff --git a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/InternalAccessHandler.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/InternalAccessHandler.java
similarity index 96%
rename from authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/InternalAccessHandler.java
rename to authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/InternalAccessHandler.java
index 0b181d8..e05f867 100644
--- a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/InternalAccessHandler.java
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/InternalAccessHandler.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.samples.porter.gateway;
+package org.apache.servicecomb.authentication.gateway;
 
 import org.apache.servicecomb.core.Handler;
 import org.apache.servicecomb.core.Invocation;
diff --git a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/StaticWebpageDispatcher.java b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/StaticWebpageDispatcher.java
similarity index 97%
rename from authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/StaticWebpageDispatcher.java
rename to authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/StaticWebpageDispatcher.java
index 791c512..555ddc4 100644
--- a/authentication/Gateway/src/main/java/org/apache/servicecomb/samples/porter/gateway/StaticWebpageDispatcher.java
+++ b/authentication/Gateway/src/main/java/org/apache/servicecomb/authentication/gateway/StaticWebpageDispatcher.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.samples.porter.gateway;
+package org.apache.servicecomb.authentication.gateway;
 
 import org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher;
 import org.slf4j.Logger;
diff --git a/authentication/Gateway/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter b/authentication/Gateway/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter
new file mode 100644
index 0000000..57adadd
--- /dev/null
+++ b/authentication/Gateway/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter
@@ -0,0 +1 @@
+org.apache.servicecomb.authentication.gateway.AuthenticationFilter
\ No newline at end of file
diff --git a/authentication/Gateway/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher b/authentication/Gateway/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
index bada1de..cb82ded 100644
--- a/authentication/Gateway/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
+++ b/authentication/Gateway/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
@@ -15,6 +15,6 @@
 # limitations under the License.
 #
 
-org.apache.servicecomb.samples.porter.gateway.ApiDispatcher
-org.apache.servicecomb.samples.porter.gateway.StaticWebpageDispatcher
-org.apache.servicecomb.samples.porter.gateway.CustomVertxRestDispatcher
\ No newline at end of file
+org.apache.servicecomb.authentication.gateway.ApiDispatcher
+org.apache.servicecomb.authentication.gateway.StaticWebpageDispatcher
+org.apache.servicecomb.authentication.gateway.CustomVertxRestDispatcher
\ No newline at end of file
diff --git a/authentication/Gateway/src/main/resources/config/cse.handler.xml b/authentication/Gateway/src/main/resources/config/cse.handler.xml
index e9dd306..b39da71 100644
--- a/authentication/Gateway/src/main/resources/config/cse.handler.xml
+++ b/authentication/Gateway/src/main/resources/config/cse.handler.xml
@@ -17,7 +17,7 @@
 
 <config>
   <handler id="auth"
-    class="org.apache.servicecomb.samples.porter.gateway.AuthHandler" />
+    class="org.apache.servicecomb.authentication.gateway.AuthHandler" />
   <handler id="internalAccess"
-    class="org.apache.servicecomb.samples.porter.gateway.InternalAccessHandler" />
+    class="org.apache.servicecomb.authentication.gateway.InternalAccessHandler" />
 </config>
diff --git a/authentication/Gateway/src/main/resources/microservice.yaml b/authentication/Gateway/src/main/resources/microservice.yaml
index 5b1cd91..8d926ee 100644
--- a/authentication/Gateway/src/main/resources/microservice.yaml
+++ b/authentication/Gateway/src/main/resources/microservice.yaml
@@ -23,6 +23,7 @@ APPLICATION_ID: authentication-application
 service_description:
   version: 0.0.1
   name: gateway
+  environment: development
 
 servicecomb:
   service:
@@ -38,6 +39,8 @@ servicecomb:
     chain:
       Consumer:
         default: internalAccess,auth,qps-flowcontrol-consumer,loadbalance
+        service:
+          authentication-server: internalAccess,qps-flowcontrol-consumer,loadbalance
 
   uploads:
     directory: tmp_for_upload_gateway
diff --git a/authentication/Gateway/test/org/apache/servicecomb/authentication/test/PatternTest.java b/authentication/Gateway/test/org/apache/servicecomb/authentication/test/PatternTest.java
new file mode 100644
index 0000000..bb737ba
--- /dev/null
+++ b/authentication/Gateway/test/org/apache/servicecomb/authentication/test/PatternTest.java
@@ -0,0 +1,19 @@
+package org.apache.servicecomb.authentication.test;
+
+import java.util.regex.Pattern;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+
+public class PatternTest {
+  @Test
+  public void testPattern() {
+    String regex = "(/v1/log|/inspector|/v1/auth)/(.*)";
+    Pattern p = Pattern.compile(regex);
+    Assert.assertTrue(p.matcher("/v1/log/login").matches());
+    Assert.assertTrue(p.matcher("/inspector/login").matches());
+    Assert.assertTrue(p.matcher("/v1/auth/login").matches());
+    Assert.assertTrue(!p.matcher("/api/v1/auth/login").matches());
+  }
+}
diff --git a/authentication/ResourceServer/pom.xml b/authentication/ResourceServer/pom.xml
index 52aea79..baeb56a 100644
--- a/authentication/ResourceServer/pom.xml
+++ b/authentication/ResourceServer/pom.xml
@@ -27,6 +27,16 @@
   <dependencyManagement>
     <dependencies>
       <dependency>
+        <groupId>org.apache.servicecomb.authentication</groupId>
+        <artifactId>authentication-common-api-endpoint</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.servicecomb.authentication</groupId>
+        <artifactId>authentication-server-api-service</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
         <groupId>org.mybatis</groupId>
         <artifactId>mybatis</artifactId>
         <version>3.4.5</version>
@@ -53,6 +63,14 @@
 
   <dependencies>
     <dependency>
+      <groupId>org.apache.servicecomb.authentication</groupId>
+      <artifactId>authentication-common-api-endpoint</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.authentication</groupId>
+      <artifactId>authentication-server-api-service</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>solution-basic</artifactId>
     </dependency>
diff --git a/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AccessConfiguration.java b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AccessConfiguration.java
new file mode 100644
index 0000000..136a11a
--- /dev/null
+++ b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AccessConfiguration.java
@@ -0,0 +1,20 @@
+package org.apache.servicecomb.authentication.resource;
+
+import org.apache.servicecomb.config.inject.InjectProperties;
+import org.apache.servicecomb.config.inject.InjectProperty;
+
+@InjectProperties(prefix = "servicecomb.authencation.access")
+public class AccessConfiguration {
+  @InjectProperty(keys = {
+      "needAuth.${schemaId}.${operationId}",
+      "needAuth.${schemaId}",
+      "needAuth"},
+      defaultValue = "true")
+  public boolean needAuth;
+
+  @InjectProperty(keys = {
+      "roles.${schemaId}.${operationId}",
+      "roles.${schemaId}",
+      "roles"})
+  public String roles;
+}
diff --git a/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AccessConfigurationManager.java b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AccessConfigurationManager.java
new file mode 100644
index 0000000..c4cbd1e
--- /dev/null
+++ b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AccessConfigurationManager.java
@@ -0,0 +1,19 @@
+package org.apache.servicecomb.authentication.resource;
+
+import java.util.Map;
+
+import org.apache.servicecomb.config.inject.ConfigObjectFactory;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+
+public class AccessConfigurationManager {
+  private static final Map<String, AccessConfiguration> CONFIGURATIONS = new ConcurrentHashMapEx<>();
+
+  private static final ConfigObjectFactory FACTORY = new ConfigObjectFactory();
+
+  public static AccessConfiguration getAccessConfiguration(Invocation invocation) {
+    return CONFIGURATIONS.computeIfAbsent(invocation.getOperationMeta().getSchemaQualifiedName(), key -> {
+      return FACTORY.create(AccessConfiguration.class, "schemaId", invocation.getSchemaId(), "operationId", invocation.getOperationName());
+    });
+  }
+}
diff --git a/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AuthenticationConfiguration.java b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AuthenticationConfiguration.java
new file mode 100644
index 0000000..847550f
--- /dev/null
+++ b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AuthenticationConfiguration.java
@@ -0,0 +1,14 @@
+package org.apache.servicecomb.authentication.resource;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.jwt.crypto.sign.MacSigner;
+import org.springframework.security.jwt.crypto.sign.Signer;
+
+@Configuration
+public class AuthenticationConfiguration {
+  @Bean(name = "authSigner")
+  public Signer authSigner() {
+    return new MacSigner("Please change this key.");
+  }
+}
diff --git a/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/HandlerAuthEndpoint.java b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/HandlerAuthEndpoint.java
new file mode 100644
index 0000000..32256ad
--- /dev/null
+++ b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/HandlerAuthEndpoint.java
@@ -0,0 +1,29 @@
+package org.apache.servicecomb.authentication.resource;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@RestSchema(schemaId = "HandlerAuthEndpoint")
+@RequestMapping(path = "/v1/auth/handler")
+public class HandlerAuthEndpoint {
+  @PostMapping(path = "/adminSayHello")
+  public String adminSayHello(String name) {
+    return name;
+  }
+
+  @PostMapping(path = "/guestSayHello")
+  public String guestSayHello(String name) {
+    return name;
+  }
+
+  @PostMapping(path = "/guestOrAdminSayHello")
+  public String guestOrAdminSayHello(String name) {
+    return name;
+  }
+
+  @PostMapping(path = "/everyoneSayHello")
+  public String everyoneSayHello(String name) {
+    return name;
+  }
+}
diff --git a/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/PreMethodAuthEndpoint.java b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/PreMethodAuthEndpoint.java
new file mode 100644
index 0000000..eea0968
--- /dev/null
+++ b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/PreMethodAuthEndpoint.java
@@ -0,0 +1,33 @@
+package org.apache.servicecomb.authentication.resource;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@RestSchema(schemaId = "PreMethodAuthEndpoint")
+@RequestMapping(path = "/v1/auth/method")
+public class PreMethodAuthEndpoint {
+  @PostMapping(path = "/adminSayHello")
+  @PreAuthorize("hasRole('ADMIN')")
+  public String adminSayHello(String name) {
+    return name;
+  }
+
+  @PostMapping(path = "/guestSayHello")
+  @PreAuthorize("hasRole('USER')")
+  public String guestSayHello(String name) {
+    return name;
+  }
+
+  @PostMapping(path = "/guestOrAdminSayHello")
+  @PreAuthorize("hasRole('USER,ADMIN')")
+  public String guestOrAdminSayHello(String name) {
+    return name;
+  }
+
+  @PostMapping(path = "/everyoneSayHello")
+  public String everyoneSayHello(String name) {
+    return name;
+  }
+}
diff --git a/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/ResourceAuthHandler.java b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/ResourceAuthHandler.java
new file mode 100644
index 0000000..fdfb3ad
--- /dev/null
+++ b/authentication/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/ResourceAuthHandler.java
@@ -0,0 +1,70 @@
+package org.apache.servicecomb.authentication.resource;
+
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.authentication.jwt.JWTClaims;
+import org.apache.servicecomb.authentication.jwt.JsonParser;
+import org.apache.servicecomb.authentication.util.Constants;
+import org.apache.servicecomb.core.Handler;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.springframework.security.jwt.Jwt;
+import org.springframework.security.jwt.JwtHelper;
+
+public class ResourceAuthHandler implements Handler {
+
+  @Override
+  public void handle(Invocation invocation, AsyncResponse asyncResponse) throws Exception {
+    AccessConfiguration config = AccessConfigurationManager.getAccessConfiguration(invocation);
+
+    // by pass authentication
+    if (!config.needAuth) {
+      invocation.next(asyncResponse);
+      return;
+    }
+
+    String token = invocation.getContext(Constants.CONTEXT_HEADER_AUTHORIZATION);
+    if (token == null) {
+      asyncResponse.consumerFail(new InvocationException(403, "forbidden", "not authenticated"));
+      return;
+    }
+    // verify tokens
+    Jwt jwt = JwtHelper.decode(token);
+    JWTClaims claims;
+    try {
+      jwt.verifySignature(BeanUtils.getBean("authSigner"));
+      claims = JsonParser.parse(jwt.getClaims(), JWTClaims.class);
+      // TODO: verify claims.
+    } catch (Exception e) {
+      asyncResponse.consumerFail(new InvocationException(403, "forbidden", "not authenticated"));
+      return;
+    }
+
+    // check roles
+    if (!StringUtils.isEmpty(config.roles)) {
+      String[] roles = config.roles.split(",");
+      if (roles.length > 0) {
+        boolean valid = false;
+        Set<String> authorities = claims.getAuthorities();
+        for (String role : roles) {
+          if (authorities.contains(role)) {
+            valid = true;
+            break;
+          }
+        }
+        if (!valid) {
+          asyncResponse.consumerFail(new InvocationException(403, "forbidden", "not authenticated"));
+          return;
+        }
+      }
+    }
+
+    // pre method authentiation
+    invocation.addLocalContext(Constants.CONTEXT_HEADER_CLAIMS, jwt.getClaims());
+    invocation.next(asyncResponse);
+  }
+
+}
diff --git a/authentication/ResourceServer/src/main/resources/META-INF/spring/user.bean.xml b/authentication/ResourceServer/src/main/resources/META-INF/spring/resource.bean.xml
similarity index 58%
rename from authentication/ResourceServer/src/main/resources/META-INF/spring/user.bean.xml
rename to authentication/ResourceServer/src/main/resources/META-INF/spring/resource.bean.xml
index 661608f..fd84e44 100644
--- a/authentication/ResourceServer/src/main/resources/META-INF/spring/user.bean.xml
+++ b/authentication/ResourceServer/src/main/resources/META-INF/spring/resource.bean.xml
@@ -27,30 +27,4 @@
 		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
   <bean id="servicecomb.samples.executor.groupThreadPool" class="org.apache.servicecomb.core.executor.GroupExecutor"
     init-method="init"/>
-    
-    <bean id="dataSource"
-        class="org.apache.commons.dbcp2.BasicDataSource"
-        destroy-method="close">
-        <property name="driverClassName" value="${db.driverClassName:com.mysql.jdbc.Driver}" />
-        <property name="url"
-            value="${db.url:jdbc:mysql://localhost/porter_user_db}" />
-        <property name="username" value="${db.username:root}" />
-        <property name="password" value="${db.password:}" />
-    </bean>
-
-    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
-        <property name="dataSource" ref="dataSource" />
-        <property name="configLocation" value="classpath:/config/mybatis-config.xml"></property>
-    </bean>
-
-    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
-        <property name="mapperInterface"
-            value="org.apache.servicecomb.samples.porter.user.dao.UserMapper" />
-        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
-    </bean>
-    <bean id="sessionMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
-        <property name="mapperInterface"
-            value="org.apache.servicecomb.samples.porter.user.dao.SessionMapper" />
-        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
-    </bean>
 </beans>
\ No newline at end of file
diff --git a/authentication/ResourceServer/src/main/resources/config/SessionMapper.xml b/authentication/ResourceServer/src/main/resources/config/SessionMapper.xml
deleted file mode 100644
index 989e786..0000000
--- a/authentication/ResourceServer/src/main/resources/config/SessionMapper.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="org.apache.servicecomb.samples.porter.user.dao.SessionMapper">
-    <resultMap id="sessionInfo" type="org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel">
-        <result column="ID" jdbcType="INTEGER" property="id" />
-        <result column="SESSION_ID" jdbcType="VARCHAR" property="sessiondId" />
-        <result column="USER_NAME" jdbcType="VARCHAR" property="userName" />
-        <result column="ROLE_NAME" jdbcType="VARCHAR" property="roleName" />
-        <result column="CREATION_TIME" jdbcType="TIMESTAMP" property="creationTime" />
-        <result column="ACTIVE_TIME" jdbcType="TIMESTAMP" property="activeTime" />
-    </resultMap>
-
-    <sql id="all_column">
-        ID, SESSION_ID, USER_NAME, ROLE_NAME, CREATION_TIME, ACTIVE_TIME
-    </sql>
-
-    <sql id="all_column_auto">
-        SESSION_ID, USER_NAME, ROLE_NAME
-    </sql>
-
-    <insert id="createSession" parameterType="org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel">
-        insert into T_SESSION (
-        <include refid="all_column_auto" />
-        )
-        values (#{sessiondId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR},
-        #{roleName,jdbcType=VARCHAR})
-    </insert>
-
-    <select id="getSessioinInfo" parameterType="java.lang.String"
-        resultMap="sessionInfo">
-        select
-        <include refid="all_column" />
-        from T_SESSION where SESSION_ID = #{0,jdbcType=VARCHAR}
-    </select>
-    
-    <update id="updateSessionInfo" parameterType="java.lang.String">
-        update T_SESSION
-        set CREATION_TIME = CREATION_TIME where SESSION_ID = #{0,jdbcType=VARCHAR};
-    </update>
-</mapper>
\ No newline at end of file
diff --git a/authentication/ResourceServer/src/main/resources/config/UserMapper.xml b/authentication/ResourceServer/src/main/resources/config/UserMapper.xml
deleted file mode 100644
index c02e60d..0000000
--- a/authentication/ResourceServer/src/main/resources/config/UserMapper.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="org.apache.servicecomb.samples.porter.user.dao.UserMapper">
-    <resultMap id="userInfo" type="org.apache.servicecomb.samples.porter.user.dao.UserInfo">
-        <result column="ID" jdbcType="INTEGER" property="id" />
-        <result column="USER_NAME" jdbcType="VARCHAR" property="userName" />
-        <result column="PASSWORD" jdbcType="VARCHAR" property="password" />
-        <result column="ROLE_NAME" jdbcType="VARCHAR" property="roleName" />
-    </resultMap>
-
-    <sql id="all_column">
-        ID, USER_NAME, PASSWORD, ROLE_NAME
-    </sql>
-
-    <insert id="createUser" parameterType="org.apache.servicecomb.samples.porter.user.dao.UserInfo">
-        insert into T_USER (
-        <include refid="all_column" />
-        )
-        values (#{id,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR},
-        #{password,jdbcType=VARCHAR},#{roleName,jdbcType=VARCHAR})
-    </insert>
-
-    <select id="getUserInfo" parameterType="java.lang.String"
-        resultMap="userInfo">
-        select
-        <include refid="all_column" />
-        from T_USER where USER_NAME = #{0,jdbcType=VARCHAR}
-    </select>
-</mapper>
\ No newline at end of file
diff --git a/authentication/ResourceServer/src/main/resources/config/create_db_user.sql b/authentication/ResourceServer/src/main/resources/config/create_db_user.sql
deleted file mode 100644
index a07c5d9..0000000
--- a/authentication/ResourceServer/src/main/resources/config/create_db_user.sql
+++ /dev/null
@@ -1,46 +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.
- */
-
-CREATE DATABASE IF NOT EXISTS porter_user_db;
-
-USE porter_user_db;
-
-DROP TABLE IF EXISTS T_USER;
-
-CREATE TABLE `T_USER` (
-  `ID`  INTEGER(8) NOT NULL AUTO_INCREMENT COMMENT 'user id',
-  `USER_NAME`  VARCHAR(64) NOT NULL COMMENT 'user name',
-  `PASSWORD`  VARCHAR(64) NOT NULL COMMENT 'user password',
-  `ROLE_NAME`  VARCHAR(64) NOT NULL COMMENT 'user role',
-  PRIMARY KEY (`ID`)
-);
-
-#### password is encrypted for test
-insert into T_USER(USER_NAME, PASSWORD, ROLE_NAME) values("admin", "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "admin");
-insert into T_USER(USER_NAME, PASSWORD, ROLE_NAME) values("guest", "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "guest");
-
-DROP TABLE IF EXISTS T_SESSION;
-
-CREATE TABLE `T_SESSION` (
-  `ID`  INTEGER(8) NOT NULL AUTO_INCREMENT COMMENT 'id',
-  `SESSION_ID`  VARCHAR(64) NOT NULL COMMENT 'session id',
-  `USER_NAME`  VARCHAR(64) NOT NULL COMMENT 'user name',
-  `ROLE_NAME`  VARCHAR(64) NOT NULL COMMENT 'user role',
-  `CREATION_TIME`  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'creation time',
-  `ACTIVE_TIME`  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'last active time',
-  PRIMARY KEY (`ID`)
-);
diff --git a/authentication/AuthenticationServer/src/main/resources/config/mybatis-config.xml b/authentication/ResourceServer/src/main/resources/config/cse.handler.xml
similarity index 71%
rename from authentication/AuthenticationServer/src/main/resources/config/mybatis-config.xml
rename to authentication/ResourceServer/src/main/resources/config/cse.handler.xml
index 894caac..0efe6d1 100644
--- a/authentication/AuthenticationServer/src/main/resources/config/mybatis-config.xml
+++ b/authentication/ResourceServer/src/main/resources/config/cse.handler.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8" ?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one or more
   ~ contributor license agreements.  See the NOTICE file distributed with
@@ -16,12 +15,7 @@
   ~ limitations under the License.
   -->
 
-<!DOCTYPE configuration
-  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
-  "http://mybatis.org/dtd/mybatis-3-config.dtd">
-<configuration>
-    <mappers>
-        <mapper resource="config/UserMapper.xml"/>
-        <mapper resource="config/SessionMapper.xml"/>
-    </mappers>
-</configuration>
\ No newline at end of file
+<config>
+  <handler id="resource-auth-provider"
+    class="org.apache.servicecomb.authentication.resource.ResourceAuthHandler" />
+</config>
diff --git a/authentication/ResourceServer/src/main/resources/config/mybatis-config.xml b/authentication/ResourceServer/src/main/resources/config/mybatis-config.xml
deleted file mode 100644
index 894caac..0000000
--- a/authentication/ResourceServer/src/main/resources/config/mybatis-config.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE configuration
-  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
-  "http://mybatis.org/dtd/mybatis-3-config.dtd">
-<configuration>
-    <mappers>
-        <mapper resource="config/UserMapper.xml"/>
-        <mapper resource="config/SessionMapper.xml"/>
-    </mappers>
-</configuration>
\ No newline at end of file
diff --git a/authentication/ResourceServer/src/main/resources/microservice.yaml b/authentication/ResourceServer/src/main/resources/microservice.yaml
index 47b05c1..69b0ffc 100644
--- a/authentication/ResourceServer/src/main/resources/microservice.yaml
+++ b/authentication/ResourceServer/src/main/resources/microservice.yaml
@@ -23,7 +23,8 @@ APPLICATION_ID: authentication-application
 service_description:
   version: 0.0.1
   name: resource-server
-
+  environment: development
+  
 servicecomb:
   service:
     registry:
@@ -33,3 +34,18 @@ servicecomb:
 
   rest:
     address: 0.0.0.0:9092
+
+  authencation:
+    access:
+      needAuth: true
+      roles:
+        HandlerAuthEndpoint:
+          adminSayHello: ADMIN
+          guestSayHello: GUEST
+          guestOrAdminSayHello: ADMIN,GUEST
+          # everyoneSayHello: all can
+
+  handler:
+    chain:
+      Provider:
+        default: qps-flowcontrol-provider,resource-auth-provider
\ No newline at end of file
diff --git a/authentication/api/AuthenticationServer/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java b/authentication/api/AuthenticationServer/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java
index dfc9c51..5177aeb 100644
--- a/authentication/api/AuthenticationServer/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java
+++ b/authentication/api/AuthenticationServer/endpoint/src/main/java/org/apache/servicecomb/authentication/api/AuthenticationEndpoint.java
@@ -19,20 +19,23 @@ package org.apache.servicecomb.authentication.api;
 
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.springframework.beans.factory.annotation.Autowired;
+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/login")
+@RequestMapping(path = "/v1/auth")
 public class AuthenticationEndpoint {
   @Autowired
   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/common/service/pom.xml b/authentication/api/common/service/pom.xml
index 538be70..66c5f90 100644
--- a/authentication/api/common/service/pom.xml
+++ b/authentication/api/common/service/pom.xml
@@ -28,4 +28,29 @@
   <artifactId>authentication-common-api-service</artifactId>
   <packaging>jar</packaging>
 
+ <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.springframework.security.oauth</groupId>
+        <artifactId>spring-security-oauth2</artifactId>
+        <version>2.3.2.RELEASE</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework.security</groupId>
+        <artifactId>spring-security-jwt</artifactId>
+        <version>1.0.7.RELEASE</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.springframework.security.oauth</groupId>
+      <artifactId>spring-security-oauth2</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-jwt</artifactId>
+    </dependency>
+  </dependencies>
 </project>
diff --git a/authentication/api/common/service/src/main/java/org/apache/servicecomb/authentication/jwt/JWTClaims.java b/authentication/api/common/service/src/main/java/org/apache/servicecomb/authentication/jwt/JWTClaims.java
index 569b4da..a5db2c2 100644
--- a/authentication/api/common/service/src/main/java/org/apache/servicecomb/authentication/jwt/JWTClaims.java
+++ b/authentication/api/common/service/src/main/java/org/apache/servicecomb/authentication/jwt/JWTClaims.java
@@ -1,26 +1,27 @@
 package org.apache.servicecomb.authentication.jwt;
 
-import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
 public class JWTClaims extends JWTClaimsCommon {
-  protected Set<String> roles = Collections.emptySet();
+  protected Set<String> authorities;
 
-  protected Map<String, Object> additionalInformation = Collections.emptyMap();
+  protected Map<String, Object> additionalInformation;
 
   /**
    * The scope of the access token as described by <a
    * href="http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.3">Section 3.3</a>
    */
-  protected String scope;
+  protected Set<String> scope;
 
-  public Set<String> getRoles() {
-    return roles;
+  public Set<String> getAuthorities() {
+    return authorities;
   }
 
-  public void setRoles(Set<String> roles) {
-    this.roles = roles;
+  public void setAuthorities(Set<String> authorities) {
+    this.authorities = authorities;
   }
 
   public Map<String, Object> getAdditionalInformation() {
@@ -31,15 +32,32 @@ public class JWTClaims extends JWTClaimsCommon {
     this.additionalInformation = additionalInformation;
   }
 
-  public String getScope() {
+  public Set<String> getScope() {
     return scope;
   }
 
-  public void setScope(String scope) {
+  public void setScope(Set<String> scope) {
     this.scope = scope;
   }
 
-  public void addRole(String role) {
-    this.roles.add(role);
+  public void addAdditionalInformation(String key, Object value) {
+    if (this.additionalInformation == null) {
+      this.additionalInformation = new HashMap<>();
+    }
+    this.additionalInformation.put(key, value);
+  }
+
+  public void addScope(String operation) {
+    if (this.scope == null) {
+      this.scope = new HashSet<>();
+    }
+    this.scope.add(operation);
+  }
+
+  public void addAuthority(String authority) {
+    if (this.authorities == null) {
+      this.authorities = new HashSet<>();
+    }
+    this.authorities.add(authority);
   }
 }
diff --git a/authentication/api/common/service/src/main/java/org/apache/servicecomb/authentication/util/Constants.java b/authentication/api/common/service/src/main/java/org/apache/servicecomb/authentication/util/Constants.java
new file mode 100644
index 0000000..a7427fa
--- /dev/null
+++ b/authentication/api/common/service/src/main/java/org/apache/servicecomb/authentication/util/Constants.java
@@ -0,0 +1,9 @@
+package org.apache.servicecomb.authentication.util;
+
+public final class Constants {
+  public static final String HTTP_HEADER_AUTHORIZATION = "Authorization";
+
+  public static final String CONTEXT_HEADER_AUTHORIZATION = "Authorization";
+  
+  public static final String CONTEXT_HEADER_CLAIMS = "Claims";
+}