You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2019/06/18 12:39:49 UTC
[servicecomb-fence] 04/09: [SCB-1293]1. add TokenStore to support
stateless or stateful session management 2. refactor test cases and change
developers guide
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-fence.git
commit 1d2e250c22aa1f09f87cdbb0b1e22833c5b0bed7
Author: liubao <bi...@qq.com>
AuthorDate: Tue May 28 15:09:55 2019 +0800
[SCB-1293]1. add TokenStore to support stateless or stateful session management 2. refactor test cases and change developers guide
---
.../server/PasswordTokenGranter.java | 51 ++++-----
.../server/RefreshTokenTokenGranter.java | 77 ++++++--------
.../authentication/server/TokenEndpoint.java | 6 +-
.../authentication/server/TokenGranter.java | 4 +-
api/authentication-server/service/pom.xml | 8 ++
.../server/{Token.java => TokenResponse.java} | 13 ++-
.../authentication/server/TokenService.java | 2 +-
.../token/AbstractSessionIDTokenStore.java} | 7 +-
.../token/InMemorySessionIDTokenStore.java} | 32 +++---
.../servicecomb/authentication/token/JWTToken.java | 85 +++++++++++++++
.../authentication/token/JWTTokenStore.java | 71 +++++++++++++
.../authentication/token/SessionIDToken.java | 76 +++++++++++++
.../servicecomb/authentication/token/Token.java} | 18 +++-
.../authentication/token/TokenStore.java} | 10 +-
.../servicecomb/authentication/util/Constants.java | 5 +-
.../authentication/edge/AuthHandler.java | 17 +--
.../authentication/edge/AuthenticationFilter.java | 0
.../edge/AuthenticationServerTokenEndpoint.java} | 27 ++---
.../edge/CustomVertxRestDispatcher.java | 1 +
.../authentication/edge/EdgeTokenStore.java} | 10 +-
.../edge/InMemoryEdgeTokenStore.java} | 28 +++--
.../authentication/edge/InternalAccessHandler.java | 0
.../authentication/edge/TokenEndpoint.java | 65 ++++++++++++
...servicecomb.common.rest.filter.HttpServerFilter | 0
...cecomb.transport.rest.vertx.VertxHttpDispatcher | 2 +-
.../src/main/resources/config/cse.handler.xml | 0
api/edge-service/service/pom.xml | 3 +-
.../authentication/edge}/TokenService.java | 8 +-
.../resource/ResourceAuthHandler.java | 24 ++---
docs/zh_CN/developersGuide.md | 97 ++++++++++++-----
.../AuthenticationConfiguration.java | 30 ++++--
.../authentication/AuthenticationTestCase.java | 117 ++++++++-------------
.../authentication/BootEventListener.java | 7 +-
.../authentication/GateRestTemplate.java | 9 ++
.../gateway/AuthenticationConfiguration.java | 10 +-
.../resource/AuthenticationConfiguration.java | 19 +++-
36 files changed, 652 insertions(+), 287 deletions(-)
diff --git a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/PasswordTokenGranter.java b/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/PasswordTokenGranter.java
index 7d16268..a1538ff 100644
--- a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/PasswordTokenGranter.java
+++ b/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/PasswordTokenGranter.java
@@ -18,18 +18,13 @@
package org.apache.servicecomb.authentication.server;
import java.util.Map;
-import java.util.UUID;
-import org.apache.servicecomb.authentication.jwt.JWTClaims;
-import org.apache.servicecomb.authentication.jwt.JsonParser;
+import org.apache.servicecomb.authentication.token.TokenStore;
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;
-import org.springframework.security.jwt.crypto.sign.Signer;
import org.springframework.stereotype.Component;
import com.netflix.config.DynamicPropertyFactory;
@@ -45,40 +40,34 @@ public class PasswordTokenGranter implements TokenGranter {
private PasswordEncoder passwordEncoder;
@Autowired
- @Qualifier("authSigner")
- private Signer signer;
+ @Qualifier("authAccessTokenStore")
+ private TokenStore accessTokenStore;
+
+ @Autowired
+ @Qualifier("authRefreshTokenStore")
+ private TokenStore refreshTokenStore;
+
+ @Autowired
+ @Qualifier("authIDTokenStore")
+ private TokenStore idTokenStore;
@Override
- public Token grant(Map<String, String> parameters) {
+ public TokenResponse grant(Map<String, String> parameters) {
String username = parameters.get(TokenConst.PARAM_USERNAME);
String password = parameters.get(TokenConst.PARAM_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()));
- }
- claims.setJti(UUID.randomUUID().toString());
- claims.setIat(System.currentTimeMillis());
- claims.setExp(5 * 60);
-
- String content = JsonParser.unparse(claims);
- Jwt accessToken = JwtHelper.encode(content, signer);
-
- Token token = new Token();
- token.setScope(claims.getScope());
+ TokenResponse token = new TokenResponse();
+ token.setAccess_token(accessTokenStore.createToken(userDetails).getValue());
+ token.setRefresh_token(refreshTokenStore.createToken(userDetails).getValue());
+ token.setId_token(idTokenStore.createToken(userDetails).getValue());
+
+ //TODO add parameters.
+ token.setScope(null);
token.setExpires_in(10 * 60);
token.setToken_type("bearer");
- token.setAccess_token(accessToken.getEncoded());
-
- JWTClaims accessTokenClaims = new JWTClaims();
- accessTokenClaims.setJti(UUID.randomUUID().toString());
- accessTokenClaims.setIat(System.currentTimeMillis());
- accessTokenClaims.setExp(60 * 60);
- Jwt refreshToken = JwtHelper.encode(JsonParser.unparse(claims), signer);
- token.setRefresh_token(refreshToken.getEncoded());
-
+
return token;
} else {
return null;
diff --git a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/RefreshTokenTokenGranter.java b/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/RefreshTokenTokenGranter.java
index 7a41e90..6980287 100644
--- a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/RefreshTokenTokenGranter.java
+++ b/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/RefreshTokenTokenGranter.java
@@ -19,14 +19,12 @@ package org.apache.servicecomb.authentication.server;
import java.util.Map;
-import org.apache.servicecomb.authentication.jwt.JWTClaims;
-import org.apache.servicecomb.authentication.jwt.JsonParser;
+import org.apache.servicecomb.authentication.token.Token;
+import org.apache.servicecomb.authentication.token.TokenStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.security.jwt.Jwt;
-import org.springframework.security.jwt.JwtHelper;
-import org.springframework.security.jwt.crypto.sign.SignatureVerifier;
-import org.springframework.security.jwt.crypto.sign.Signer;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import com.netflix.config.DynamicPropertyFactory;
@@ -34,12 +32,20 @@ import com.netflix.config.DynamicPropertyFactory;
@Component(value = "fefreshTokenTokenGranter")
public class RefreshTokenTokenGranter implements TokenGranter {
@Autowired
- @Qualifier("authSignatureVerifier")
- private SignatureVerifier signerVerifier;
+ @Qualifier("authUserDetailsService")
+ private UserDetailsService userDetailsService;
@Autowired
- @Qualifier("authSigner")
- private Signer signer;
+ @Qualifier("authAccessTokenStore")
+ private TokenStore accessTokenStore;
+
+ @Autowired
+ @Qualifier("authRefreshTokenStore")
+ private TokenStore refreshTokenStore;
+
+ @Autowired
+ @Qualifier("authIDTokenStore")
+ private TokenStore idTokenStore;
@Override
public boolean enabled() {
@@ -54,42 +60,27 @@ public class RefreshTokenTokenGranter implements TokenGranter {
}
@Override
- public Token grant(Map<String, String> parameters) {
- String refreshToken = parameters.get(TokenConst.PARAM_REFRESH_TOKEN);
- String accessToken = parameters.get(TokenConst.PARAM_ACCESS_TOKEN);
-
- // verify refresh tokens
- Jwt jwt = JwtHelper.decode(refreshToken);
- JWTClaims claims;
- try {
- jwt.verifySignature(signerVerifier);
- claims = JsonParser.parse(jwt.getClaims(), JWTClaims.class);
- // TODO: verify claims.
- } catch (Exception e) {
- return null;
- }
+ public TokenResponse grant(Map<String, String> parameters) {
+ String refreshTokenValue = parameters.get(TokenConst.PARAM_REFRESH_TOKEN);
- // verify access tokens
- jwt = JwtHelper.decode(accessToken);
- claims = null;
- try {
- jwt.verifySignature(signerVerifier);
- claims = JsonParser.parse(jwt.getClaims(), JWTClaims.class);
- // TODO: verify claims.
- } catch (Exception e) {
- return null;
- }
+ Token refreshToken = refreshTokenStore.readTokenByValue(refreshTokenValue);
- claims.setIat(System.currentTimeMillis());
- String content = JsonParser.unparse(claims);
- Jwt newAccessToken = JwtHelper.encode(content, signer);
+ if (refreshToken != null && !refreshToken.isExpired()) {
+ UserDetails userDetails = userDetailsService.loadUserByUsername(refreshToken.username());
- Token token = new Token();
- token.setScope(claims.getScope());
- token.setExpires_in(10 * 60);
- token.setToken_type("bearer");
- token.setAccess_token(newAccessToken.getEncoded());
- return token;
+ TokenResponse token = new TokenResponse();
+ token.setAccess_token(accessTokenStore.createToken(userDetails).getValue());
+ // refresh token is not generated
+ token.setRefresh_token(refreshTokenValue);
+ token.setId_token(idTokenStore.createToken(userDetails).getValue());
+
+ //TODO add parameters.
+ token.setScope(null);
+ token.setExpires_in(10 * 60);
+ token.setToken_type("bearer");
+ return token;
+ }
+ return null;
}
}
diff --git a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenEndpoint.java b/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenEndpoint.java
index 775d332..fa2ca32 100644
--- a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenEndpoint.java
+++ b/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenEndpoint.java
@@ -29,19 +29,19 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@RestSchema(schemaId = "TokenEndpoint")
-@RequestMapping(path = "/v1/oauth/token")
+@RequestMapping(path = "/v1/token")
public class TokenEndpoint implements TokenService {
@Autowired
private List<TokenGranter> granters;
@Override
@PostMapping(path = "/", consumes = MediaType.APPLICATION_FORM_URLENCODED)
- public Token getAccessToken(@RequestBody Map<String, String> parameters) {
+ public TokenResponse getToken(@RequestBody Map<String, String> parameters) {
String grantType = parameters.get(TokenConst.PARAM_GRANT_TYPE);
for (TokenGranter granter : granters) {
if (granter.enabled()) {
- Token token = granter.grant(grantType, parameters);
+ TokenResponse token = granter.grant(grantType, parameters);
if (token != null) {
return token;
}
diff --git a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java b/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java
index 9ba0861..e5f600b 100644
--- a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java
+++ b/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java
@@ -29,12 +29,12 @@ public interface TokenGranter {
String grantType();
- default Token grant(String grantType, Map<String, String> parameters) {
+ default TokenResponse grant(String grantType, Map<String, String> parameters) {
if (grantType().equals(grantType)) {
return grant(parameters);
}
return null;
}
- Token grant(Map<String, String> parameters);
+ TokenResponse grant(Map<String, String> parameters);
}
diff --git a/api/authentication-server/service/pom.xml b/api/authentication-server/service/pom.xml
index 4433ff6..8f9b5e2 100644
--- a/api/authentication-server/service/pom.xml
+++ b/api/authentication-server/service/pom.xml
@@ -28,4 +28,12 @@
<artifactId>authentication-server-api-service</artifactId>
<packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.servicecomb.authentication</groupId>
+ <artifactId>authentication-common-api-service</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ </dependencies>
+
</project>
diff --git a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/Token.java b/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenResponse.java
similarity index 88%
rename from api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/Token.java
rename to api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenResponse.java
index 8758bd1..9bdc6d7 100644
--- a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/Token.java
+++ b/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenResponse.java
@@ -20,7 +20,7 @@ package org.apache.servicecomb.authentication.server;
import java.util.Map;
import java.util.Set;
-public class Token {
+public class TokenResponse {
// Naming conventions https://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-00#section-3.1
private String token_type;
@@ -28,6 +28,9 @@ public class Token {
private String refresh_token;
+ // Naming conventions https://openid.net/specs/openid-connect-basic-1_0.html#ObtainingTokens
+ private String id_token;
+
private int expires_in;
private Set<String> scope;
@@ -69,6 +72,14 @@ public class Token {
this.expires_in = expires_in;
}
+ public String getId_token() {
+ return id_token;
+ }
+
+ public void setId_token(String id_token) {
+ this.id_token = id_token;
+ }
+
public Set<String> getScope() {
return scope;
}
diff --git a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java b/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
index b0cea22..8dbd197 100644
--- a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
+++ b/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
@@ -20,5 +20,5 @@ package org.apache.servicecomb.authentication.server;
import java.util.Map;
public interface TokenService {
- Token getAccessToken(Map<String, String> parameters);
+ TokenResponse getToken(Map<String, String> parameters);
}
diff --git a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/AbstractSessionIDTokenStore.java
similarity index 83%
copy from api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
copy to api/common/service/src/main/java/org/apache/servicecomb/authentication/token/AbstractSessionIDTokenStore.java
index b0cea22..cb507a3 100644
--- a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
+++ b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/AbstractSessionIDTokenStore.java
@@ -15,10 +15,7 @@
* limitations under the License.
*/
-package org.apache.servicecomb.authentication.server;
+package org.apache.servicecomb.authentication.token;
-import java.util.Map;
-
-public interface TokenService {
- Token getAccessToken(Map<String, String> parameters);
+public abstract class AbstractSessionIDTokenStore implements TokenStore {
}
diff --git a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/InMemorySessionIDTokenStore.java
similarity index 55%
copy from api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java
copy to api/common/service/src/main/java/org/apache/servicecomb/authentication/token/InMemorySessionIDTokenStore.java
index 9ba0861..5bac8f0 100644
--- a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java
+++ b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/InMemorySessionIDTokenStore.java
@@ -15,26 +15,28 @@
* limitations under the License.
*/
-package org.apache.servicecomb.authentication.server;
+package org.apache.servicecomb.authentication.token;
+import java.util.HashMap;
import java.util.Map;
-/**
- * Token granter is used to grant access tokens.
- * @author Administrator
- *
- */
-public interface TokenGranter {
- boolean enabled();
+import org.springframework.security.core.userdetails.UserDetails;
- String grantType();
+public class InMemorySessionIDTokenStore extends AbstractSessionIDTokenStore {
+ private Map<String, SessionIDToken> tokens = new HashMap<>();
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Token> T createToken(UserDetails userDetails) {
+ SessionIDToken token = new SessionIDToken(userDetails.getUsername());
+ tokens.put(token.getValue(), token);
+ return (T) token;
+ }
- default Token grant(String grantType, Map<String, String> parameters) {
- if (grantType().equals(grantType)) {
- return grant(parameters);
- }
- return null;
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Token> T readTokenByValue(String value) {
+ return (T) tokens.get(value);
}
- Token grant(Map<String, String> parameters);
}
diff --git a/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/JWTToken.java b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/JWTToken.java
new file mode 100644
index 0000000..e989ae5
--- /dev/null
+++ b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/JWTToken.java
@@ -0,0 +1,85 @@
+/*
+ * 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.token;
+
+import java.util.Map;
+
+import org.apache.servicecomb.authentication.jwt.JWTClaims;
+import org.apache.servicecomb.authentication.jwt.JsonParser;
+import org.springframework.security.jwt.Jwt;
+import org.springframework.security.jwt.JwtHelper;
+import org.springframework.security.jwt.crypto.sign.Signer;
+
+public class JWTToken implements Token {
+ private JWTClaims claims;
+
+ private boolean valueCalculated = false;
+
+ private String value;
+
+ private Signer signer;
+
+ public JWTToken(JWTClaims claims, Signer signer) {
+ this.claims = claims;
+ this.signer = signer;
+ }
+
+ @Override
+ public boolean isExpired() {
+ return System.currentTimeMillis() - this.getIssueAt() > this.getExpiration() * 1000;
+ }
+
+ @Override
+ public long getIssueAt() {
+ return this.claims.getIat();
+ }
+
+ @Override
+ public long getExpiration() {
+ return this.claims.getExp();
+ }
+
+ @Override
+ public long getNotBefore() {
+ return this.claims.getNbf();
+ }
+
+ @Override
+ public String getValue() {
+ if (!this.valueCalculated) {
+ String content = JsonParser.unparse(claims);
+ Jwt jwtToken = JwtHelper.encode(content, signer);
+ this.value = jwtToken.getEncoded();
+ }
+ return this.value;
+ }
+
+ @Override
+ public Map<String, Object> getAdditionalInformation() {
+ return this.claims.getAdditionalInformation();
+ }
+
+ @Override
+ public String username() {
+ return this.claims.getSub();
+ }
+
+ public JWTClaims getClaims() {
+ return this.claims;
+ }
+}
diff --git a/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/JWTTokenStore.java b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/JWTTokenStore.java
new file mode 100644
index 0000000..2f394e7
--- /dev/null
+++ b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/JWTTokenStore.java
@@ -0,0 +1,71 @@
+/*
+ * 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.token;
+
+import java.util.UUID;
+
+import org.apache.servicecomb.authentication.jwt.JWTClaims;
+import org.apache.servicecomb.authentication.jwt.JsonParser;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.jwt.Jwt;
+import org.springframework.security.jwt.JwtHelper;
+import org.springframework.security.jwt.crypto.sign.SignatureVerifier;
+import org.springframework.security.jwt.crypto.sign.Signer;
+
+public class JWTTokenStore implements TokenStore {
+ private Signer signer;
+
+ private SignatureVerifier signerVerifier;
+
+ public JWTTokenStore(Signer signer, SignatureVerifier signerVerifier) {
+ this.signer = signer;
+ this.signerVerifier = signerVerifier;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Token> T createToken(UserDetails userDetails) {
+ JWTClaims claims = new JWTClaims();
+ claims.setSub(userDetails.getUsername());
+ if (userDetails.getAuthorities() != null) {
+ userDetails.getAuthorities().forEach(authority -> claims.addAuthority(authority.getAuthority()));
+ }
+
+ // TODO : set other parameters.
+ claims.setJti(UUID.randomUUID().toString());
+ claims.setIat(System.currentTimeMillis());
+ claims.setExp(5 * 60);
+
+ return (T) new JWTToken(claims, signer);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Token> T readTokenByValue(String value) {
+ Jwt jwt = JwtHelper.decode(value);
+ JWTClaims claims;
+ try {
+ jwt.verifySignature(signerVerifier);
+ claims = JsonParser.parse(jwt.getClaims(), JWTClaims.class);
+ } catch (Exception e) {
+ return null;
+ }
+ return (T) new JWTToken(claims, signer);
+ }
+
+}
diff --git a/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/SessionIDToken.java b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/SessionIDToken.java
new file mode 100644
index 0000000..06a6f96
--- /dev/null
+++ b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/SessionIDToken.java
@@ -0,0 +1,76 @@
+/*
+ * 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.token;
+
+import java.util.Map;
+import java.util.UUID;
+
+public class SessionIDToken implements Token {
+ private String value;
+
+ private long issueAt;
+
+ // in seconds
+ private long expiration;
+
+ private String username;
+
+ public SessionIDToken(String username) {
+ this.value = UUID.randomUUID().toString();
+ this.issueAt = System.currentTimeMillis();
+ // TODO add a configuration
+ this.expiration = 600;
+ this.username = username;
+ }
+
+ @Override
+ public boolean isExpired() {
+ return System.currentTimeMillis() - this.issueAt > this.expiration * 1000;
+ }
+
+ @Override
+ public long getIssueAt() {
+ return this.issueAt;
+ }
+
+ @Override
+ public long getExpiration() {
+ return this.expiration;
+ }
+
+ @Override
+ public long getNotBefore() {
+ // TODO add a configuration
+ return 0;
+ }
+
+ @Override
+ public String getValue() {
+ return this.value;
+ }
+
+ @Override
+ public Map<String, Object> getAdditionalInformation() {
+ // TODO add a configuration
+ return null;
+ }
+
+ public String username() {
+ return this.username;
+ }
+}
diff --git a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/Token.java
similarity index 75%
copy from api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
copy to api/common/service/src/main/java/org/apache/servicecomb/authentication/token/Token.java
index b0cea22..21b06d5 100644
--- a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
+++ b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/Token.java
@@ -15,10 +15,22 @@
* limitations under the License.
*/
-package org.apache.servicecomb.authentication.server;
+package org.apache.servicecomb.authentication.token;
import java.util.Map;
-public interface TokenService {
- Token getAccessToken(Map<String, String> parameters);
+public interface Token {
+ String username();
+
+ boolean isExpired();
+
+ long getIssueAt();
+
+ long getExpiration();
+
+ long getNotBefore();
+
+ String getValue();
+
+ Map<String, Object> getAdditionalInformation();
}
diff --git a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/TokenStore.java
similarity index 75%
copy from api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
copy to api/common/service/src/main/java/org/apache/servicecomb/authentication/token/TokenStore.java
index b0cea22..1f26610 100644
--- a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
+++ b/api/common/service/src/main/java/org/apache/servicecomb/authentication/token/TokenStore.java
@@ -15,10 +15,12 @@
* limitations under the License.
*/
-package org.apache.servicecomb.authentication.server;
+package org.apache.servicecomb.authentication.token;
-import java.util.Map;
+import org.springframework.security.core.userdetails.UserDetails;
-public interface TokenService {
- Token getAccessToken(Map<String, String> parameters);
+public interface TokenStore {
+ <T extends Token> T createToken(UserDetails userDetails);
+
+ <T extends Token> T readTokenByValue(String value);
}
diff --git a/api/common/service/src/main/java/org/apache/servicecomb/authentication/util/Constants.java b/api/common/service/src/main/java/org/apache/servicecomb/authentication/util/Constants.java
index 96333aa..4dcc8e7 100644
--- a/api/common/service/src/main/java/org/apache/servicecomb/authentication/util/Constants.java
+++ b/api/common/service/src/main/java/org/apache/servicecomb/authentication/util/Constants.java
@@ -21,6 +21,9 @@ 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";
+
+ public static final String TOKEN_TYPE_BEARER = "Bearer";
+
}
diff --git a/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/AuthHandler.java b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthHandler.java
similarity index 78%
rename from api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/AuthHandler.java
rename to api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthHandler.java
index abf4587..d209be4 100644
--- a/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/AuthHandler.java
+++ b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthHandler.java
@@ -17,32 +17,35 @@
package org.apache.servicecomb.authentication.edge;
+import org.apache.servicecomb.authentication.server.TokenResponse;
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 {
+ EdgeTokenStore edgeTokenStore = BeanUtils.getBean("authEdgeTokenStore");
+
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("authSignatureVerifier"));
- } catch (InvalidSignatureException e) {
+
+ TokenResponse tokenResonse = edgeTokenStore.readTokenResponse(token);
+ if (tokenResonse == null) {
+ // TODO : check token validity by expiration time
asyncResponse.consumerFail(new InvocationException(403, "forbidden", "not authenticated"));
return;
}
+
+ // send id_token to services to apply state less validation
+ invocation.addContext(Constants.CONTEXT_HEADER_AUTHORIZATION, tokenResonse.getId_token());
invocation.next(asyncResponse);
}
}
diff --git a/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationFilter.java b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationFilter.java
similarity index 100%
rename from api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationFilter.java
rename to api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationFilter.java
diff --git a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationServerTokenEndpoint.java
similarity index 59%
copy from api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java
copy to api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationServerTokenEndpoint.java
index 9ba0861..50c29d3 100644
--- a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java
+++ b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/AuthenticationServerTokenEndpoint.java
@@ -15,26 +15,17 @@
* limitations under the License.
*/
-package org.apache.servicecomb.authentication.server;
+package org.apache.servicecomb.authentication.edge;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
-/**
- * Token granter is used to grant access tokens.
- * @author Administrator
- *
- */
-public interface TokenGranter {
- boolean enabled();
-
- String grantType();
-
- default Token grant(String grantType, Map<String, String> parameters) {
- if (grantType().equals(grantType)) {
- return grant(parameters);
- }
- return null;
- }
+import org.apache.servicecomb.authentication.server.TokenResponse;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
- Token grant(Map<String, String> parameters);
+public interface AuthenticationServerTokenEndpoint {
+ @PostMapping(path = "/", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+ public CompletableFuture<TokenResponse> getToken(@RequestBody Map<String, String> parameters);
}
diff --git a/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java
similarity index 99%
rename from api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java
rename to api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java
index 521b71c..a08873d 100644
--- a/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java
+++ b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/CustomVertxRestDispatcher.java
@@ -63,6 +63,7 @@ public class CustomVertxRestDispatcher extends AbstractVertxHttpDispatcher {
@Override
public void init(Router router) {
+ // TODO: regex configuration
String regex = "(/v1/log|/inspector|/v1/auth)/(.*)";
router.routeWithRegex(regex).handler(CookieHandler.create());
router.routeWithRegex(regex).handler(createBodyHandler());
diff --git a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/EdgeTokenStore.java
similarity index 73%
copy from api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
copy to api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/EdgeTokenStore.java
index b0cea22..92bbbaf 100644
--- a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
+++ b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/EdgeTokenStore.java
@@ -15,10 +15,12 @@
* limitations under the License.
*/
-package org.apache.servicecomb.authentication.server;
+package org.apache.servicecomb.authentication.edge;
-import java.util.Map;
+import org.apache.servicecomb.authentication.server.TokenResponse;
-public interface TokenService {
- Token getAccessToken(Map<String, String> parameters);
+public interface EdgeTokenStore {
+ TokenResponse readTokenResponse(String accessTokenValue);
+
+ void saveTokenResponse(String accessTokenValue, TokenResponse tokenResponse);
}
diff --git a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/InMemoryEdgeTokenStore.java
similarity index 60%
copy from api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java
copy to api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/InMemoryEdgeTokenStore.java
index 9ba0861..03a7baa 100644
--- a/api/authentication-server/endpoint/src/main/java/org/apache/servicecomb/authentication/server/TokenGranter.java
+++ b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/InMemoryEdgeTokenStore.java
@@ -15,26 +15,24 @@
* limitations under the License.
*/
-package org.apache.servicecomb.authentication.server;
+package org.apache.servicecomb.authentication.edge;
+import java.util.HashMap;
import java.util.Map;
-/**
- * Token granter is used to grant access tokens.
- * @author Administrator
- *
- */
-public interface TokenGranter {
- boolean enabled();
+import org.apache.servicecomb.authentication.server.TokenResponse;
- String grantType();
+public class InMemoryEdgeTokenStore implements EdgeTokenStore {
+ private Map<String, TokenResponse> tokens = new HashMap<>();
+
+ @Override
+ public TokenResponse readTokenResponse(String accessTokenValue) {
+ return tokens.get(accessTokenValue);
+ }
- default Token grant(String grantType, Map<String, String> parameters) {
- if (grantType().equals(grantType)) {
- return grant(parameters);
- }
- return null;
+ @Override
+ public void saveTokenResponse(String accessTokenValue, TokenResponse tokenResponse) {
+ tokens.put(accessTokenValue, tokenResponse);
}
- Token grant(Map<String, String> parameters);
}
diff --git a/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/InternalAccessHandler.java b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/InternalAccessHandler.java
similarity index 100%
rename from api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/InternalAccessHandler.java
rename to api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/InternalAccessHandler.java
diff --git a/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/TokenEndpoint.java b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/TokenEndpoint.java
new file mode 100644
index 0000000..87dcbb0
--- /dev/null
+++ b/api/edge-service/endpoint/src/main/java/org/apache/servicecomb/authentication/edge/TokenEndpoint.java
@@ -0,0 +1,65 @@
+/*
+ * 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 java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.authentication.server.TokenResponse;
+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.beans.factory.annotation.Qualifier;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@RestSchema(schemaId = "TokenEndpoint")
+@RequestMapping(path = "/v1/token")
+public class TokenEndpoint implements TokenService {
+ @RpcReference(microserviceName = "authentication-server", schemaId = "TokenEndpoint")
+ private AuthenticationServerTokenEndpoint authenticationSererTokenEndpoint;
+
+ @Autowired
+ @Qualifier("authEdgeTokenStore")
+ private EdgeTokenStore edgeTokenStore;
+
+
+ @Override
+ @PostMapping(path = "/", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+ public CompletableFuture<TokenResponse> getToken(@RequestBody Map<String, String> parameters) {
+ CompletableFuture<TokenResponse> result = new CompletableFuture<>();
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+
+ CompletableFuture<TokenResponse> response =
+ authenticationSererTokenEndpoint.getToken(parameters);
+ response.whenComplete((tokenResonse, ex) -> {
+ if (!response.isCompletedExceptionally()) {
+ result.complete(tokenResonse);
+ edgeTokenStore.saveTokenResponse(tokenResonse.getAccess_token(), tokenResonse);
+ } else {
+ result.completeExceptionally(ex);
+ }
+ });
+ return result;
+ }
+}
diff --git a/api/edge-service/service/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter b/api/edge-service/endpoint/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter
similarity index 100%
rename from api/edge-service/service/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter
rename to api/edge-service/endpoint/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter
diff --git a/api/edge-service/service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher b/api/edge-service/endpoint/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
similarity index 91%
rename from api/edge-service/service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
rename to api/edge-service/endpoint/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
index 32c1583..53481f1 100644
--- a/api/edge-service/service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
+++ b/api/edge-service/endpoint/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/api/edge-service/service/src/main/resources/config/cse.handler.xml b/api/edge-service/endpoint/src/main/resources/config/cse.handler.xml
similarity index 100%
rename from api/edge-service/service/src/main/resources/config/cse.handler.xml
rename to api/edge-service/endpoint/src/main/resources/config/cse.handler.xml
diff --git a/api/edge-service/service/pom.xml b/api/edge-service/service/pom.xml
index 8d86c00..487f146 100644
--- a/api/edge-service/service/pom.xml
+++ b/api/edge-service/service/pom.xml
@@ -36,7 +36,8 @@
<dependencies>
<dependency>
<groupId>org.apache.servicecomb.authentication</groupId>
- <artifactId>authentication-common-api-endpoint</artifactId>
+ <artifactId>authentication-server-api-service</artifactId>
+ <version>${project.parent.version}</version>
</dependency>
</dependencies>
</project>
diff --git a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java b/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/TokenService.java
similarity index 77%
copy from api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
copy to api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/TokenService.java
index b0cea22..5e12a45 100644
--- a/api/authentication-server/service/src/main/java/org/apache/servicecomb/authentication/server/TokenService.java
+++ b/api/edge-service/service/src/main/java/org/apache/servicecomb/authentication/edge/TokenService.java
@@ -15,10 +15,14 @@
* limitations under the License.
*/
-package org.apache.servicecomb.authentication.server;
+package org.apache.servicecomb.authentication.edge;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.authentication.server.TokenResponse;
+
public interface TokenService {
- Token getAccessToken(Map<String, String> parameters);
+ CompletableFuture<TokenResponse> getToken(Map<String, String> parameters);
}
diff --git a/api/resource-server/service/src/main/java/org/apache/servicecomb/authentication/resource/ResourceAuthHandler.java b/api/resource-server/service/src/main/java/org/apache/servicecomb/authentication/resource/ResourceAuthHandler.java
index 68c6960..5c81139 100644
--- a/api/resource-server/service/src/main/java/org/apache/servicecomb/authentication/resource/ResourceAuthHandler.java
+++ b/api/resource-server/service/src/main/java/org/apache/servicecomb/authentication/resource/ResourceAuthHandler.java
@@ -21,8 +21,8 @@ import java.util.HashSet;
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.token.JWTToken;
+import org.apache.servicecomb.authentication.token.JWTTokenStore;
import org.apache.servicecomb.authentication.util.Constants;
import org.apache.servicecomb.core.Handler;
import org.apache.servicecomb.core.Invocation;
@@ -35,8 +35,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
-import org.springframework.security.jwt.Jwt;
-import org.springframework.security.jwt.JwtHelper;
public class ResourceAuthHandler implements Handler {
@@ -56,23 +54,19 @@ public class ResourceAuthHandler implements Handler {
return;
}
// verify tokens
- Jwt jwt = JwtHelper.decode(token);
- JWTClaims claims;
- try {
- jwt.verifySignature(BeanUtils.getBean("authSignatureVerifier"));
- claims = JsonParser.parse(jwt.getClaims(), JWTClaims.class);
- // TODO: verify claims.
- } catch (Exception e) {
+ JWTTokenStore store = BeanUtils.getBean("authIDTokenStore");
+ JWTToken t = store.readTokenByValue(token);
+ if(t == null) {
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();
+ Set<String> authorities = t.getClaims().getAuthorities();
for (String role : roles) {
if (authorities.contains(role)) {
valid = true;
@@ -87,8 +81,8 @@ public class ResourceAuthHandler implements Handler {
}
// pre method authentiation
- Set<GrantedAuthority> grantedAuthorities = new HashSet<>(claims.getAuthorities().size());
- claims.getAuthorities().forEach(v -> grantedAuthorities.add(new SimpleGrantedAuthority(v)));
+ Set<GrantedAuthority> grantedAuthorities = new HashSet<>(t.getClaims().getAuthorities().size());
+ t.getClaims().getAuthorities().forEach(v -> grantedAuthorities.add(new SimpleGrantedAuthority(v)));
SecurityContext sc = new SecurityContextImpl();
Authentication authentication = new SimpleAuthentication(true, grantedAuthorities);
sc.setAuthentication(authentication);
diff --git a/docs/zh_CN/developersGuide.md b/docs/zh_CN/developersGuide.md
index 013f98f..3d67833 100644
--- a/docs/zh_CN/developersGuide.md
+++ b/docs/zh_CN/developersGuide.md
@@ -11,15 +11,37 @@
```
** HTTP Request **
-POST http://localhost:9090/api/authentication-server/v1/oauth/token HTTP/1.1
+POST http://localhost:9090/v1/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=admin&password=changeMyPassword
+
+** HTTP Response **
+
+{
+ "token_type": "bearer",
+ "access_token": "SlAV32hkKG",
+ "refresh_token": "8xLOxBtZp8",
+ "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
+ yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
+ NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
+ fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
+ AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
+ Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
+ NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
+ QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
+ K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
+ XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg",
+ "expires_in": 600,
+ "scope": null,
+ "jti": null,
+ "additionalInformation": null
+}
```
* Authentication Server 发送 Token 给 Client 。
- * Client 携带 Token 请求 Resource Server 。
+ * Client 携带 Access Token 请求 Edge Service 。
```
** HTTP Request **
@@ -29,6 +51,7 @@ Content-Type: application/x-www-form-urlencoded
Authorization: Bearer czZCaGRSa3F0MzpnWDFmQmF0M2JW
```
+ * Edge Service 将 Access Token 转换为对应的 ID Token , 然后将请求转发给Resource Server。
* Resource Server 返回对应的资源给 Client 。
## 开发 Authentication Server
@@ -48,31 +71,38 @@ Authentication Server 主要提供认证和授权等接口。
* 配置
-Authentication Server 需要配置 PasswordEncoder、Signer、SignerVerifier、UserDetailsService 等。这些对象和 Spring Security的概念一样。
+Authentication Server 需要配置 PasswordEncoder、Signer、SignerVerifier、TokenStore、UserDetailsService 等。
```
@Configuration
public class AuthenticationConfiguration {
- @Autowired
- @Qualifier("authPasswordEncoder")
- private PasswordEncoder passwordEncoder;
-
@Bean(name = "authPasswordEncoder")
public PasswordEncoder authPasswordEncoder() {
return new Pbkdf2PasswordEncoder();
}
- @Bean(name = "authSigner")
- public Signer authSigner() {
- return authSignerVerifier();
- }
-
- @Bean(name = "authSignerVerifier")
+ @Bean(name = {"authSigner", "authSignatureVerifier"})
public SignerVerifier authSignerVerifier() {
+ // If using RSA, need to configure authSigner and authSignatureVerifier separately.
+ // If using MacSigner, need to protect the shared key by properly encryption.
return new MacSigner("Please change this key.");
}
+ @Bean(name = {"authAccessTokenStore", "authRefreshTokenStore"})
+ public TokenStore sessionIDTokenStore() {
+ // Use in memory store for testing. Need to implement JDBC or Redis SessionIDTokenStore in product.
+ return new InMemorySessionIDTokenStore();
+ }
+
+ @Bean(name = "authIDTokenStore")
+ public TokenStore authIDTokenStore(@Autowired @Qualifier("authSigner") Signer signer,
+ @Autowired @Qualifier("authSignatureVerifier") SignatureVerifier signerVerifier) {
+ return new JWTTokenStore(signer, signerVerifier);
+ }
+
@Bean(name = "authUserDetailsService")
- public UserDetailsService authUserDetailsService() {
+ public UserDetailsService authUserDetailsService(
+ @Autowired @Qualifier("authPasswordEncoder") PasswordEncoder passwordEncoder) {
+ // Use in memory UserDetails, need to implement JDBC or others in product
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
UserDetails uAdmin = new User("admin", passwordEncoder.encode("changeMyPassword"),
Arrays.asList(new SimpleGrantedAuthority("ADMIN")));
@@ -93,6 +123,9 @@ public class AuthenticationConfiguration {
生成 Token 和对 Token 进行校验。Singer 和 SignatureVerifier 是配套使用的, 在 Authentication Server , 生成 Token 的时候,需要使用 Singer 。 验证 Token 的有效性 (比如查询 userDetails 等场景), 需要使用 SignatureVerifier 。 通常有两种方式进行签名和校验, 一种是基于对称秘钥的机制,比如MacSigner,即是 Singer, 也是 SignatureVerifier (SignerVerifier); 一种是基于非对称秘钥的机制, 比如 RsaSigner 和 RsaVerifier , 生成 Token 和校验 Token 的秘钥是不同的。
+* TokenStore
+在Authentication Server,TokenStore主要用来生成Access Token, Refresh Token和ID Token, 默认情况下, Access Token和Refresh Token都使用AbstractSessionIDTokenStore(本例子使用了InMemorySessionIDTokenStore,业务代码通常需要换为JDBC、Redis等实现), ID Token使用JWTTokenStore。 JWTTokenStore是一个无状态的会话机制,Authentication Server的任何一个实例都可以独立生成。
+
* PasswordEncoder
从 UserDetailsService 校验用户密码的时候需要使用。 开发者需要在加密性能和保密程度方面选择合适的算法。 常用的有 Pbkdf2PasswordEncoder , 它可以设置迭代次数,能够更好的保护密码不被暴力破解。
@@ -114,17 +147,30 @@ Resource Server 对 Client 的访问进行认证, 并进行权限控制。
* 配置
-Resource Server 需要配置 SignatureVerifier 等, 对用户会话进行认证。
+Resource Server 需要配置 Signer、SignatureVerifier、TokenStore 等, 对用户会话进行认证。
+
```
-@Configuration
-public class AuthenticationConfiguration {
- @Bean(name = "authSignatureVerifier")
- public SignerVerifier authSignatureVerifier() {
+ @Bean(name = {"authSigner", "authSignatureVerifier"})
+ public SignerVerifier authSignerVerifier() {
+ // If using RSA, need to configure authSigner and authSignatureVerifier separately.
+ // If using MacSigner, need to protect the shared key by properly encryption.
return new MacSigner("Please change this key.");
}
-}
+
+ @Bean(name = "authIDTokenStore")
+ public TokenStore authIDTokenStore(@Autowired @Qualifier("authSigner") Signer signer,
+ @Autowired @Qualifier("authSignatureVerifier") SignatureVerifier signerVerifier) {
+ return new JWTTokenStore(signer, signerVerifier);
+ }
```
+* Signer、SignatureVerifier
+对Token进行校验需要,实际上Resource Server只需要使用SignatureVerifier。
+
+* TokenStore
+默认情况下, Edge Service将ID Token传递给Resource Server,所以只需要配置authIDTokenStore。
+
+
* 权限配置
fence 提供了两种方式进行权限配置。 一种是基于配置文件的,一种是基于 Annotation 。
@@ -205,15 +251,14 @@ Edge Service 是微服务接入层。 在[单体应用微服务改造](https://b
* 配置
-Edge Service 需要配置 SignatureVerifier 等, 对用户会话进行认证。
-```
+Edge Service 需要配置 EdgeTokenStore 等, 对用户会话进行认证。Edge Service 从HTTP头里面读取Access Token, 然后通过 EdgeTokenStore比对是否Access Token有效,如果有效,将对应的 ID Token传递到 Resource Server。 这里使用了 InMemoryEdgeTokenStore, 产品代码会多实例部署 Edge Service, 需要将其替换为 JDBC 或者 Redis 等实现。
+```
@Configuration
public class AuthenticationConfiguration {
- @Bean(name = "authSignatureVerifier")
- public SignerVerifier authSignatureVerifier() {
- return new MacSigner("Please change this key.");
+ @Bean(name = "authEdgeTokenStore")
+ public EdgeTokenStore authEdgeTokenStore() {
+ return new InMemoryEdgeTokenStore();
}
}
-
```
diff --git a/samples/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java b/samples/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java
index b70273f..20e9f68 100644
--- a/samples/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java
+++ b/samples/AuthenticationServer/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java
@@ -19,6 +19,9 @@ package org.apache.servicecomb.authentication;
import java.util.Arrays;
+import org.apache.servicecomb.authentication.token.InMemorySessionIDTokenStore;
+import org.apache.servicecomb.authentication.token.JWTTokenStore;
+import org.apache.servicecomb.authentication.token.TokenStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
@@ -30,28 +33,41 @@ 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.SignatureVerifier;
+import org.springframework.security.jwt.crypto.sign.Signer;
import org.springframework.security.jwt.crypto.sign.SignerVerifier;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
public class AuthenticationConfiguration {
- @Autowired
- @Qualifier("authPasswordEncoder")
- private PasswordEncoder passwordEncoder;
-
@Bean(name = "authPasswordEncoder")
public PasswordEncoder authPasswordEncoder() {
return new Pbkdf2PasswordEncoder();
}
- // If using RSA, need to configure authSigner and authSignatureVerifier separately.
- @Bean(name = {"authSigner", "authSignatureVerifier" })
+ @Bean(name = {"authSigner", "authSignatureVerifier"})
public SignerVerifier authSignerVerifier() {
+ // If using RSA, need to configure authSigner and authSignatureVerifier separately.
+ // If using MacSigner, need to protect the shared key by properly encryption.
return new MacSigner("Please change this key.");
}
+ @Bean(name = {"authAccessTokenStore", "authRefreshTokenStore"})
+ public TokenStore sessionIDTokenStore() {
+ // Use in memory store for testing. Need to implement JDBC or Redis SessionIDTokenStore in product.
+ return new InMemorySessionIDTokenStore();
+ }
+
+ @Bean(name = "authIDTokenStore")
+ public TokenStore authIDTokenStore(@Autowired @Qualifier("authSigner") Signer signer,
+ @Autowired @Qualifier("authSignatureVerifier") SignatureVerifier signerVerifier) {
+ return new JWTTokenStore(signer, signerVerifier);
+ }
+
@Bean(name = "authUserDetailsService")
- public UserDetailsService authUserDetailsService() {
+ public UserDetailsService authUserDetailsService(
+ @Autowired @Qualifier("authPasswordEncoder") PasswordEncoder passwordEncoder) {
+ // Use in memory UserDetails, need to implement JDBC or others in product
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
UserDetails uAdmin = new User("admin", passwordEncoder.encode("changeMyPassword"),
Arrays.asList(new SimpleGrantedAuthority("ADMIN")));
diff --git a/samples/Client/src/main/java/org/apache/servicecomb/authentication/AuthenticationTestCase.java b/samples/Client/src/main/java/org/apache/servicecomb/authentication/AuthenticationTestCase.java
index 13bfaba..e05545f 100644
--- a/samples/Client/src/main/java/org/apache/servicecomb/authentication/AuthenticationTestCase.java
+++ b/samples/Client/src/main/java/org/apache/servicecomb/authentication/AuthenticationTestCase.java
@@ -17,13 +17,10 @@
package org.apache.servicecomb.authentication;
-import org.apache.servicecomb.authentication.jwt.JWTClaims;
-import org.apache.servicecomb.authentication.jwt.JsonParser;
-import org.apache.servicecomb.authentication.server.Token;
+import org.apache.servicecomb.authentication.server.TokenResponse;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
-import org.springframework.security.jwt.JwtHelper;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -33,12 +30,16 @@ import org.springframework.web.client.HttpClientErrorException;
public class AuthenticationTestCase implements TestCase {
@Override
public void run() {
- testHanlderAuth();
- testMethodAuth();
- }
+ String accessToken = accessToken();
+ testHanlderAuth(accessToken);
+ testMethodAuth(accessToken);
+ accessToken = accessTokenByRefreshToken();
+ testHanlderAuth(accessToken);
+ testMethodAuth(accessToken);
+ }
- private void testHanlderAuth() {
+ private String accessToken() {
// get token
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("grant_type", "password");
@@ -47,68 +48,55 @@ public class AuthenticationTestCase implements TestCase {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
- Token token =
- BootEventListener.authenticationServerTokenEndpoint.postForObject("/",
+ TokenResponse token =
+ BootEventListener.edgeServiceTokenEndpoint.postForObject("/",
new HttpEntity<>(map, headers),
- Token.class);
+ TokenResponse.class);
TestMgr.check("bearer", token.getToken_type());
TestMgr.check(true, token.getAccess_token().length() > 10);
+ return token.getAccess_token();
+ }
- // get resources
- headers = new HttpHeaders();
- headers.add("Authorization", "Bearer " + token.getAccess_token());
- headers.setContentType(MediaType.APPLICATION_JSON);
- String name;
- name = BootEventListener.resouceServerHandlerAuthEndpoint.postForObject("/everyoneSayHello?name=Hi",
- new HttpEntity<>(headers),
- String.class);
- TestMgr.check("Hi", name);
-
- name = BootEventListener.resouceServerHandlerAuthEndpoint.postForObject("/adminSayHello?name=Hi",
- new HttpEntity<>(headers),
- String.class);
- TestMgr.check("Hi", name);
+ private String accessTokenByRefreshToken() {
+ // get token
+ MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
+ map.add("grant_type", "password");
+ map.add("username", "admin");
+ map.add("password", "changeMyPassword");
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
- name = BootEventListener.resouceServerHandlerAuthEndpoint.postForObject("/guestOrAdminSayHello?name=Hi",
- new HttpEntity<>(headers),
- String.class);
- TestMgr.check("Hi", name);
+ TokenResponse token =
+ BootEventListener.edgeServiceTokenEndpoint.postForObject("/",
+ new HttpEntity<>(map, headers),
+ TokenResponse.class);
+ TestMgr.check("bearer", token.getToken_type());
+ TestMgr.check(true, token.getAccess_token().length() > 10);
- name = null;
- try {
- name = BootEventListener.resouceServerHandlerAuthEndpoint.postForObject("/guestSayHello?name=Hi",
- new HttpEntity<>(headers),
- String.class);
- } catch (HttpClientErrorException e) {
- TestMgr.check(403, e.getStatusCode().value());
- }
- TestMgr.check(null, name);
-
// refresh token
- // get token
map = new LinkedMultiValueMap<>();
map.add("grant_type", "refresh_token");
map.add("refresh_token", token.getRefresh_token());
- map.add("access_token", token.getAccess_token());
- headers = new HttpHeaders();
- headers.setContentType(MediaType.MULTIPART_FORM_DATA);
- Token tokenNew =
- BootEventListener.authenticationServerTokenEndpoint.postForObject("/",
+ TokenResponse tokenNew =
+ BootEventListener.edgeServiceTokenEndpoint.postForObject("/",
new HttpEntity<>(map, headers),
- Token.class);
+ TokenResponse.class);
TestMgr.check(token.getToken_type(), tokenNew.getToken_type());
-
- JWTClaims claims = JsonParser.parse(JwtHelper.decode(token.getAccess_token()).getClaims(), JWTClaims.class);
- JWTClaims newClaims = JsonParser.parse(JwtHelper.decode(tokenNew.getAccess_token()).getClaims(), JWTClaims.class);
- TestMgr.check(claims.getJti(), newClaims.getJti());
- TestMgr.check(claims.getIat() < newClaims.getIat(), true);
+ TestMgr.check(token.getRefresh_token(), tokenNew.getRefresh_token());
+ TestMgr.check(token.getAccess_token().equals(tokenNew.getAccess_token()), false);
+ TestMgr.check(token.getId_token().equals(tokenNew.getId_token()), false);
+
+ return tokenNew.getAccess_token();
+ }
+ private void testHanlderAuth(String accessToken) {
// get resources
+ HttpHeaders headers = new HttpHeaders();
headers = new HttpHeaders();
- headers.add("Authorization", "Bearer " + tokenNew.getAccess_token());
+ headers.add("Authorization", "Bearer " + accessToken);
headers.setContentType(MediaType.APPLICATION_JSON);
-
+ String name;
name = BootEventListener.resouceServerHandlerAuthEndpoint.postForObject("/everyoneSayHello?name=Hi",
new HttpEntity<>(headers),
String.class);
@@ -135,27 +123,10 @@ public class AuthenticationTestCase implements TestCase {
TestMgr.check(null, name);
}
-
- private void testMethodAuth() {
- // get token
- MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
- 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.authenticationServerTokenEndpoint.postForObject("/",
- new HttpEntity<>(map, headers),
- Token.class);
- TestMgr.check("bearer", token.getToken_type());
- TestMgr.check(true, token.getAccess_token().length() > 10);
- TestMgr.check(true, token.getRefresh_token().length() > 10);
-
+ private void testMethodAuth(String accessToken) {
// get resources
- headers = new HttpHeaders();
- headers.add("Authorization", "Bearer " + token.getAccess_token());
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("Authorization", "Bearer " + accessToken);
headers.setContentType(MediaType.APPLICATION_JSON);
String name;
name = BootEventListener.resouceServerMethodAuthEndpoint.postForObject("/everyoneSayHello?name=Hi",
diff --git a/samples/Client/src/main/java/org/apache/servicecomb/authentication/BootEventListener.java b/samples/Client/src/main/java/org/apache/servicecomb/authentication/BootEventListener.java
index 08d1bb3..74db45a 100644
--- a/samples/Client/src/main/java/org/apache/servicecomb/authentication/BootEventListener.java
+++ b/samples/Client/src/main/java/org/apache/servicecomb/authentication/BootEventListener.java
@@ -23,7 +23,8 @@ import org.springframework.stereotype.Component;
@Component
public class BootEventListener implements BootListener {
public static GateRestTemplate authenticationServerTokenEndpoint;
- public static GateRestTemplate gateEndpoint;
+ public static GateRestTemplate edgeService;
+ public static GateRestTemplate edgeServiceTokenEndpoint;
public static GateRestTemplate resouceServerHandlerAuthEndpoint;
public static GateRestTemplate resouceServerMethodAuthEndpoint;
@@ -32,8 +33,10 @@ public class BootEventListener implements BootListener {
if (EventType.AFTER_REGISTRY.equals(event.getEventType())) {
authenticationServerTokenEndpoint =
GateRestTemplate.createEdgeRestTemplate("edge-service", "authentication-server", "TokenEndpoint").init();
- gateEndpoint =
+ edgeService =
GateRestTemplate.createEdgeRestTemplate("edge-service", null, null).init();
+ edgeServiceTokenEndpoint =
+ GateRestTemplate.createEdgeRestTemplate("edge-service", "edge-service", "TokenEndpoint").init();
resouceServerHandlerAuthEndpoint =
GateRestTemplate.createEdgeRestTemplate("edge-service", "resource-server", "HandlerAuthEndpoint").init();
resouceServerMethodAuthEndpoint =
diff --git a/samples/Client/src/main/java/org/apache/servicecomb/authentication/GateRestTemplate.java b/samples/Client/src/main/java/org/apache/servicecomb/authentication/GateRestTemplate.java
index 7a6709f..df981e5 100644
--- a/samples/Client/src/main/java/org/apache/servicecomb/authentication/GateRestTemplate.java
+++ b/samples/Client/src/main/java/org/apache/servicecomb/authentication/GateRestTemplate.java
@@ -100,6 +100,15 @@ public class GateRestTemplate extends RestTemplate {
DefinitionConst.VERSION_RULE_ALL);
MicroserviceVersionMeta microserviceVersionMeta = microserviceVersionRule.getLatestMicroserviceVersion();
SchemaMeta schemaMeta = microserviceVersionMeta.getMicroserviceMeta().ensureFindSchemaMeta(schemaId);
+
+ if(producerName.equals(gateName)) {
+ return String
+ .format("%s://%s:%d/%s",
+ urlSchema,
+ edgeAddress.getHostOrIp(),
+ edgeAddress.getPort(),
+ schemaMeta.getSwagger().getBasePath());
+ }
return String
.format("%s://%s:%d/api/%s%s",
urlSchema,
diff --git a/samples/EdgeService/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationConfiguration.java b/samples/EdgeService/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationConfiguration.java
index 510d821..e9187b7 100644
--- a/samples/EdgeService/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationConfiguration.java
+++ b/samples/EdgeService/src/main/java/org/apache/servicecomb/authentication/gateway/AuthenticationConfiguration.java
@@ -17,15 +17,15 @@
package org.apache.servicecomb.authentication.gateway;
+import org.apache.servicecomb.authentication.edge.EdgeTokenStore;
+import org.apache.servicecomb.authentication.edge.InMemoryEdgeTokenStore;
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.SignerVerifier;
@Configuration
public class AuthenticationConfiguration {
- @Bean(name = "authSignatureVerifier")
- public SignerVerifier authSignatureVerifier() {
- return new MacSigner("Please change this key.");
+ @Bean(name = "authEdgeTokenStore")
+ public EdgeTokenStore authEdgeTokenStore() {
+ return new InMemoryEdgeTokenStore();
}
}
diff --git a/samples/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AuthenticationConfiguration.java b/samples/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AuthenticationConfiguration.java
index 2074321..e69217f 100644
--- a/samples/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AuthenticationConfiguration.java
+++ b/samples/ResourceServer/src/main/java/org/apache/servicecomb/authentication/resource/AuthenticationConfiguration.java
@@ -17,15 +17,30 @@
package org.apache.servicecomb.authentication.resource;
+import org.apache.servicecomb.authentication.token.JWTTokenStore;
+import org.apache.servicecomb.authentication.token.TokenStore;
+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.jwt.crypto.sign.MacSigner;
import org.springframework.security.jwt.crypto.sign.SignatureVerifier;
+import org.springframework.security.jwt.crypto.sign.Signer;
+import org.springframework.security.jwt.crypto.sign.SignerVerifier;
@Configuration
public class AuthenticationConfiguration {
- @Bean(name = "authSignatureVerifier")
- public SignatureVerifier authSignatureVerifier() {
+ @Bean(name = {"authSigner", "authSignatureVerifier"})
+ public SignerVerifier authSignerVerifier() {
+ // If using RSA, need to configure authSigner and authSignatureVerifier separately.
+ // If using MacSigner, need to protect the shared key by properly encryption.
return new MacSigner("Please change this key.");
}
+
+ @Bean(name = "authIDTokenStore")
+ public TokenStore authIDTokenStore(@Autowired @Qualifier("authSigner") Signer signer,
+ @Autowired @Qualifier("authSignatureVerifier") SignatureVerifier signerVerifier) {
+ return new JWTTokenStore(signer, signerVerifier);
+ }
+
}