KJB 소스 정리
This commit is contained in:
@@ -1,200 +0,0 @@
|
||||
package com.eactive.eai.authserver.custom;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException;
|
||||
import com.eactive.eai.authserver.config.RequestContextData;
|
||||
import com.eactive.eai.authserver.dao.TokenIssuanceLogDAO;
|
||||
import com.eactive.eai.authserver.service.BearerTokenService;
|
||||
import com.eactive.eai.authserver.service.OAuth2Manager;
|
||||
import com.eactive.eai.authserver.vo.ClientVO;
|
||||
import com.eactive.eai.common.logger.EAIDBLogControl;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.eactive.eai.common.util.MessageUtil;
|
||||
import com.eactive.eai.data.entity.onl.authserver.TokenIssuanceLog;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/auth/oauth/v2")
|
||||
public class BearerTokenController {
|
||||
|
||||
public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
private final BearerTokenService tokenService;
|
||||
|
||||
@Autowired
|
||||
private TokenIssuanceLogDAO tokenIssuanceLogDAO;
|
||||
|
||||
public BearerTokenController(BearerTokenService tokenService) {
|
||||
this.tokenService = tokenService;
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
value = "/token",
|
||||
method = {RequestMethod.POST, RequestMethod.GET}
|
||||
)
|
||||
public ResponseEntity<?> issueCAToken(HttpServletRequest request, @RequestParam MultiValueMap<String, String> req) throws JwtAuthException {
|
||||
JSONObject resObject = new JSONObject();
|
||||
String clientId = req.getFirst("client_id");
|
||||
String grantType = req.getFirst("grant_type");
|
||||
String clientSecret = req.getFirst("client_secret");
|
||||
String scopes = req.getFirst("scope");
|
||||
|
||||
try {
|
||||
|
||||
|
||||
RequestContextData data = new RequestContextData();
|
||||
data.setClientId(request.getParameter("client_id"));
|
||||
data.setIpAddress(extractIpAddress(request));
|
||||
data.setGrantType(request.getParameter("grant_type"));
|
||||
data.setScope(request.getParameter("scope"));
|
||||
data.setUsername(request.getParameter("username"));
|
||||
data.setResource(request.getParameter("resource"));
|
||||
|
||||
RequestContextData.ThreadLocalRequestContext.set(data);
|
||||
|
||||
|
||||
|
||||
if (!StringUtils.equals(grantType, "client_credentials") ) {
|
||||
throw new JwtAuthException("unsupported_grant_type", "Unsupported grant type");
|
||||
}
|
||||
|
||||
ClientDetails clientDetails = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId);
|
||||
if (clientDetails == null) {
|
||||
throw new JwtAuthException("invalid_client", "Bad client credentials(not found)");
|
||||
}
|
||||
|
||||
String tokenType = "Bearer";
|
||||
|
||||
|
||||
|
||||
|
||||
Long expiresIn = Long.valueOf(clientDetails.getAccessTokenValiditySeconds());
|
||||
|
||||
String[] reqScopeArr = org.springframework.util.StringUtils.tokenizeToStringArray(scopes, " ");
|
||||
Set<String> scopeSet = new HashSet<String>();
|
||||
for (String scope : reqScopeArr) {
|
||||
scopeSet.add(scope);
|
||||
}
|
||||
veryfyClient(clientDetails, clientSecret, scopeSet);
|
||||
|
||||
String token = tokenService.generateCAToken(clientId, expiresIn, scopeSet);
|
||||
|
||||
Map<String, Object> tokenMap = new HashMap<>();
|
||||
tokenMap.put("token_type", tokenType);
|
||||
tokenMap.put("access_token", token);
|
||||
tokenMap.put("expires_in", expiresIn);
|
||||
tokenMap.put("scope", scopes);
|
||||
// ... and so on for all key-value pairs
|
||||
resObject.putAll(tokenMap);
|
||||
|
||||
logTokenIssuance(true,false, resObject.toJSONString(), token);
|
||||
|
||||
return ResponseEntity.ok(resObject);
|
||||
} catch (JwtAuthException e) {
|
||||
logger.error("Token request[/auth/oauth/v2/token] => clientId: {}, grantType: {}, scope: {}",
|
||||
clientId, grantType, scopes);
|
||||
logger.error(e);
|
||||
String errorJson = MessageUtil.makeJsonErrorMessage(MessageUtil.ERROR_CODE_AUTH_FAIL, e.getMessage());
|
||||
logTokenIssuance(false ,false, e.getMessage(), null);
|
||||
return ResponseEntity.status(401).body(errorJson);
|
||||
} catch (Exception e) {
|
||||
logger.error("Token request[/auth/oauth/v2/token] => clientId: {}, grantType: {}, scope: {}",
|
||||
clientId, grantType, scopes);
|
||||
logger.error(e);
|
||||
String errorJson = MessageUtil.makeJsonErrorMessage(MessageUtil.ERROR_CODE_AP_ERROR, e.getMessage());
|
||||
logTokenIssuance(false ,false, e.getMessage(), null);
|
||||
return ResponseEntity.status(500).body(errorJson);
|
||||
}finally {
|
||||
RequestContextData.ThreadLocalRequestContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private String extractIpAddress(HttpServletRequest request) {
|
||||
String ipAddress = request.getHeader("X-Forwarded-For");
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("HTTP_CLIENT_IP");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getRemoteAddr();
|
||||
}
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
private void logTokenIssuance(boolean isSuccess, boolean isRestrictionExempt, String resultMessage, String accessToken) {
|
||||
try {
|
||||
if (!EAIDBLogControl.isEnable()) {
|
||||
logger.warn("DB logging is disabled. Skipping token issuance logging.");
|
||||
return;
|
||||
}
|
||||
RequestContextData data = RequestContextData.ThreadLocalRequestContext.get();
|
||||
OAuth2Manager.getInstance();
|
||||
|
||||
TokenIssuanceLog log = new TokenIssuanceLog();
|
||||
String clientId = data.getClientId();
|
||||
log.setClientId(clientId);
|
||||
|
||||
if(StringUtils.isNotBlank(clientId)) {
|
||||
ClientVO clientVO = OAuth2Manager.getInstance().getClientInfo(clientId);
|
||||
log.setAppName(clientVO.getClientName());
|
||||
log.setOrgId(clientVO.getOrgId());
|
||||
log.setOrgName(clientVO.getOrgName());
|
||||
}
|
||||
|
||||
log.setGrantType(data.getGrantType());
|
||||
log.setScope(data.getScope());
|
||||
log.setIpAddress(data.getIpAddress());
|
||||
log.setSuccessYn(isSuccess ? "Y" : "N");
|
||||
log.setIssuanceDateTime(LocalDateTime.now());
|
||||
log.setRestrictionExemptYn(isRestrictionExempt ? "Y" : "N");
|
||||
log.setResultMessage(resultMessage);
|
||||
log.setAccessToken(accessToken); // Add access token value to the log
|
||||
|
||||
tokenIssuanceLogDAO.saveTokenIssuanceLog(log);
|
||||
} catch (Throwable th) {
|
||||
logger.error("Error while logging token issuance: " + th.getMessage(), th);
|
||||
}
|
||||
}
|
||||
|
||||
private void veryfyClient(ClientDetails clientDetails, String clientSecret, Set<String> scopeSet) throws JwtAuthException {
|
||||
if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
|
||||
throw new JwtAuthException("invalid_client", "Bad client credentials(client_secret is empty or not match)");
|
||||
}
|
||||
|
||||
if (scopeSet.isEmpty()) {
|
||||
throw new JwtAuthException("invalid_client", "Bad client credentials(Scope is empty)");
|
||||
}
|
||||
|
||||
if (!clientDetails.getScope().containsAll(scopeSet)) {
|
||||
throw new JwtAuthException("invalid_client", "Bad client credentials(Include unacceptable scope)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import java.io.Serializable;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class DJErpOAuth2AccessTokenRequest implements Serializable {
|
||||
public class DJBOAuth2AccessTokenRequest implements Serializable {
|
||||
|
||||
@JsonProperty("grant_type")
|
||||
private String grantType;
|
||||
+1
-1
@@ -10,7 +10,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
@SuppressWarnings("serial")
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonPropertyOrder({ "access_token", "token_type", "expires_in", "scope", "jti", "client_id" })
|
||||
public class DJErpOAuth2AccessTokenResponse implements Serializable {
|
||||
public class DJBOAuth2AccessTokenResponse implements Serializable {
|
||||
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
+6
-6
@@ -46,7 +46,7 @@ import com.eactive.eai.data.entity.onl.authserver.TokenIssuanceLog;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@Controller
|
||||
public class DJErpOAuth2Controller {
|
||||
public class DJBOAuth2Controller {
|
||||
public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
private static final String HEADER_TRACEID = "traceId";
|
||||
@@ -58,7 +58,7 @@ public class DJErpOAuth2Controller {
|
||||
@RequestMapping(value = { "/dj/oauth/token", "/dj/oauth2/token" }, method = RequestMethod.POST,
|
||||
consumes = "application/json", produces = "application/json; charset=UTF-8")
|
||||
@ResponseBody
|
||||
public ResponseEntity<?> tokenJson(@RequestBody DJErpOAuth2AccessTokenRequest tokenRequest,
|
||||
public ResponseEntity<?> tokenJson(@RequestBody DJBOAuth2AccessTokenRequest tokenRequest,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
return issueToken(tokenRequest, request, response);
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public class DJErpOAuth2Controller {
|
||||
@ResponseBody
|
||||
public ResponseEntity<?> tokenForm(@RequestParam Map<String, String> params,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
DJErpOAuth2AccessTokenRequest tokenRequest = new DJErpOAuth2AccessTokenRequest();
|
||||
DJBOAuth2AccessTokenRequest tokenRequest = new DJBOAuth2AccessTokenRequest();
|
||||
tokenRequest.setGrantType(params.get("grant_type"));
|
||||
tokenRequest.setClientId(params.get("client_id"));
|
||||
tokenRequest.setClientSecret(params.get("client_secret"));
|
||||
@@ -80,7 +80,7 @@ public class DJErpOAuth2Controller {
|
||||
@ResponseBody
|
||||
public ResponseEntity<?> tokenGet(@RequestParam Map<String, String> params,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
DJErpOAuth2AccessTokenRequest tokenRequest = new DJErpOAuth2AccessTokenRequest();
|
||||
DJBOAuth2AccessTokenRequest tokenRequest = new DJBOAuth2AccessTokenRequest();
|
||||
tokenRequest.setGrantType(params.get("grant_type"));
|
||||
tokenRequest.setClientId(params.get("client_id"));
|
||||
tokenRequest.setClientSecret(params.get("client_secret"));
|
||||
@@ -88,7 +88,7 @@ public class DJErpOAuth2Controller {
|
||||
return issueToken(tokenRequest, request, response);
|
||||
}
|
||||
|
||||
private ResponseEntity<?> issueToken(DJErpOAuth2AccessTokenRequest tokenRequest,
|
||||
private ResponseEntity<?> issueToken(DJBOAuth2AccessTokenRequest tokenRequest,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
|
||||
if (logger.isDebug()) {
|
||||
@@ -143,7 +143,7 @@ public class DJErpOAuth2Controller {
|
||||
ResponseEntity<OAuth2AccessToken> result = tokenEndpoint().postAccessToken(principal, authorizationParameters);
|
||||
OAuth2AccessToken token = result.getBody();
|
||||
|
||||
DJErpOAuth2AccessTokenResponse responseToken = new DJErpOAuth2AccessTokenResponse();
|
||||
DJBOAuth2AccessTokenResponse responseToken = new DJBOAuth2AccessTokenResponse();
|
||||
responseToken.setAccessToken(token.getValue());
|
||||
responseToken.setTokenType(token.getTokenType());
|
||||
responseToken.setExpiresIn(Long.valueOf(token.getExpiresIn()));
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.eactive.eai.authserver.custom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class KjbMGOAuth2AccessTokenRequest implements Serializable {
|
||||
@JsonProperty("grant_type")
|
||||
private String grantType;
|
||||
@JsonProperty("client_id")
|
||||
private String clientId;
|
||||
@JsonProperty("client_secret")
|
||||
private String clientSecret;
|
||||
private String resource;
|
||||
private String scope;
|
||||
|
||||
public String getGrantType() {
|
||||
return grantType;
|
||||
}
|
||||
|
||||
public void setGrantType(String grantType) {
|
||||
this.grantType = grantType;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
public void setClientSecret(String clientSecret) {
|
||||
this.clientSecret = clientSecret;
|
||||
}
|
||||
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KjbMGOAuth2AccessTokenRequest [grantType=" + grantType + ", clientId=" + clientId + ", clientSecret="
|
||||
+ clientSecret + ", resource=" + resource + ", scope=" + scope + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package com.eactive.eai.authserver.custom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
public class KjbMGOAuth2AccessTokenResponse implements Serializable {
|
||||
private String responseCode;
|
||||
private String responseMessage;
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
@JsonProperty("refresh_token")
|
||||
private String refreshToken;
|
||||
@JsonProperty("token_type")
|
||||
private String tokenType;
|
||||
@JsonProperty("expires_in")
|
||||
private Long expiresIn;
|
||||
@JsonProperty("expires_on")
|
||||
private Long expiresOn;
|
||||
private String resource;
|
||||
private String scope;
|
||||
|
||||
public String getResponseCode() {
|
||||
return responseCode;
|
||||
}
|
||||
|
||||
public void setResponseCode(String responseCode) {
|
||||
this.responseCode = responseCode;
|
||||
}
|
||||
|
||||
public String getResponseMessage() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
public void setResponseMessage(String responseMessage) {
|
||||
this.responseMessage = responseMessage;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getrefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void setrefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
public Long getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
public void setExpiresIn(Long expiresIn) {
|
||||
this.expiresIn = expiresIn;
|
||||
}
|
||||
|
||||
public Long getExpiresOn() {
|
||||
return expiresOn;
|
||||
}
|
||||
|
||||
public void setExpiresOn(Long expiresOn) {
|
||||
this.expiresOn = expiresOn;
|
||||
}
|
||||
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KjbMGOAuth2AccessTokenResponse [responseCode=" + responseCode + ", responseMessage=" + responseMessage
|
||||
+ ", accessToken=" + accessToken + ", tokenType=" + tokenType + ", expiresIn=" + expiresIn
|
||||
+ ", refreshToken=" + refreshToken+ ", expiresOn=" + expiresOn+ ", resource=" + resource+ ", scope=" + scope + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,360 +0,0 @@
|
||||
package com.eactive.eai.authserver.custom;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.Principal;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Signature;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Request;
|
||||
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException;
|
||||
import com.eactive.eai.authserver.config.IssueLimitOAuth2Exception;
|
||||
import com.eactive.eai.authserver.config.RequestContextData;
|
||||
import com.eactive.eai.authserver.dao.TokenIssuanceLogDAO;
|
||||
import com.eactive.eai.authserver.service.OAuth2Manager;
|
||||
import com.eactive.eai.authserver.util.BeanUtils;
|
||||
import com.eactive.eai.authserver.vo.ClientVO;
|
||||
import com.eactive.eai.common.dao.DAOException;
|
||||
import com.eactive.eai.common.logger.EAIDBLogControl;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.eactive.eai.common.util.MessageUtil;
|
||||
import com.eactive.eai.common.util.UUID;
|
||||
import com.eactive.eai.data.entity.onl.authserver.TokenIssuanceLog;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@Controller
|
||||
public class KjbMGOAuth2Controller {
|
||||
public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
private static final String HEADER_TRACEID = "traceId";
|
||||
|
||||
private static final String SERVICE_CODE_ACCESS_TOKEN = "00"; // 임시설정
|
||||
@Autowired
|
||||
private TokenIssuanceLogDAO tokenIssuanceLogDAO;
|
||||
|
||||
|
||||
@RequestMapping(value = "/mapi/oauth2/token", method = RequestMethod.POST, consumes = "application/json", produces = "application/json; charset=UTF-8")
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> tokenJson(@RequestBody KjbMGOAuth2AccessTokenRequest tokenRequest,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
|
||||
return issueToken(tokenRequest, request, response);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/mapi/oauth2/token", method = RequestMethod.POST, consumes = "application/x-www-form-urlencoded", produces = "application/json; charset=UTF-8")
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> tokenForm(@RequestParam Map<String, String> params, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
|
||||
KjbMGOAuth2AccessTokenRequest tokenRequest = new KjbMGOAuth2AccessTokenRequest();
|
||||
|
||||
tokenRequest.setGrantType(params.get("grant_type"));
|
||||
tokenRequest.setClientId(params.get("client_id"));
|
||||
tokenRequest.setClientSecret(params.get("client_secret"));
|
||||
tokenRequest.setScope(params.get("scope"));
|
||||
tokenRequest.setResource(params.get("resource"));
|
||||
|
||||
return issueToken(tokenRequest, request, response);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/mapi/oauth2/token", produces = "application/json; charset=UTF-8")
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> tokenGet(@RequestParam Map<String, String> params, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
|
||||
KjbMGOAuth2AccessTokenRequest tokenRequest = new KjbMGOAuth2AccessTokenRequest();
|
||||
|
||||
tokenRequest.setGrantType(params.get("grant_type"));
|
||||
tokenRequest.setClientId(params.get("client_id"));
|
||||
tokenRequest.setClientSecret(params.get("client_secret"));
|
||||
tokenRequest.setScope(params.get("scope"));
|
||||
tokenRequest.setResource(params.get("resource"));
|
||||
|
||||
return issueToken(tokenRequest, request, response);
|
||||
}
|
||||
|
||||
private ResponseEntity<String> issueToken(
|
||||
KjbMGOAuth2AccessTokenRequest tokenRequest,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(tokenRequest.toString());
|
||||
}
|
||||
|
||||
RequestContextData data = new RequestContextData();
|
||||
data.setClientId(tokenRequest.getClientId());
|
||||
data.setIpAddress(extractIpAddress(request));
|
||||
data.setGrantType(tokenRequest.getGrantType());
|
||||
data.setScope(tokenRequest.getScope());
|
||||
data.setUsername("none");
|
||||
data.setResource("none");
|
||||
|
||||
RequestContextData.ThreadLocalRequestContext.set(data);
|
||||
|
||||
|
||||
KjbMGOAuth2AccessTokenResponse responseToken = new KjbMGOAuth2AccessTokenResponse();
|
||||
|
||||
String grantType = tokenRequest.getGrantType();
|
||||
String clientId = tokenRequest.getClientId();
|
||||
String clientSecret = tokenRequest.getClientSecret();
|
||||
String scopes = tokenRequest.getScope();
|
||||
|
||||
try {
|
||||
if (!StringUtils.equals(tokenRequest.getGrantType(), "client_credentials")) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {grantType}");
|
||||
}
|
||||
|
||||
String[] scopeArr = org.springframework.util.StringUtils.tokenizeToStringArray(scopes, " ");
|
||||
Set<String> scopeSet = new HashSet<String>();
|
||||
for (String scope : scopeArr) {
|
||||
scopeSet.add(scope);
|
||||
}
|
||||
|
||||
String[] resourceArr = org.springframework.util.StringUtils.tokenizeToStringArray(tokenRequest.getResource(), ",");
|
||||
Set<String> resourceSet = new HashSet<String>();
|
||||
for (String resource : resourceArr) {
|
||||
resourceSet.add(resource);
|
||||
}
|
||||
|
||||
ClientDetails clientDetails = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId);
|
||||
verifyClient(clientDetails, clientId, clientSecret, scopeSet);
|
||||
|
||||
String traceId = UUID.randomUUID().toString().replace("-", "");
|
||||
response.setHeader(HEADER_TRACEID, traceId);
|
||||
|
||||
HashMap<String, String> authorizationParameters = new HashMap<String, String>();
|
||||
authorizationParameters.put(OAuth2Utils.GRANT_TYPE, grantType);
|
||||
authorizationParameters.put(OAuth2Utils.CLIENT_ID, clientId);
|
||||
authorizationParameters.put("client_secret", clientSecret);
|
||||
|
||||
Set<String> responseType = new HashSet<String>();
|
||||
responseType.add(tokenRequest.getGrantType());
|
||||
|
||||
OAuth2Request authorizationRequest = new OAuth2Request(authorizationParameters, clientId, null, true, scopeSet,
|
||||
resourceSet, "", responseType, null);
|
||||
|
||||
Principal principal = new OAuth2Authentication(authorizationRequest, null);
|
||||
ResponseEntity<OAuth2AccessToken> result = tokenEndpoint().postAccessToken(principal,
|
||||
authorizationParameters);
|
||||
OAuth2AccessToken token = result.getBody();
|
||||
if(StringUtils.isNotBlank(token.getTokenType()) && StringUtils.equalsIgnoreCase(token.getTokenType(), "bearer")) {
|
||||
responseToken.setTokenType("Bearer");
|
||||
} else { responseToken.setTokenType(token.getTokenType()); }
|
||||
responseToken.setAccessToken(token.getValue());
|
||||
responseToken.setExpiresIn(Long.valueOf(token.getExpiresIn()));
|
||||
responseToken.setrefreshToken("");
|
||||
responseToken.setExpiresOn(System.currentTimeMillis() + (token.getExpiresIn() * 1000));
|
||||
responseToken.setScope(tokenRequest.getScope());
|
||||
responseToken.setResource(tokenRequest.getResource());
|
||||
|
||||
// 성공 시 JSON 문자열로 변환하여 반환
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String successJson = mapper.writeValueAsString(responseToken);
|
||||
|
||||
return ResponseEntity.ok(successJson);
|
||||
|
||||
} catch (JwtAuthException e) {
|
||||
logger.info("Token request[/mapi/oauth2/token] => clientId: {}, grantType: {}, scope: {}",
|
||||
clientId, grantType, scopes);
|
||||
logger.error(e.getMessage());
|
||||
String errorJson = MessageUtil.makeJsonErrorMessage(MessageUtil.ERROR_CODE_AUTH_FAIL, e.getMessage());
|
||||
int statusCode = NumberUtils.toInt(StringUtils.left(e.getCode(), 3), HttpStatus.UNAUTHORIZED.value());
|
||||
logTokenIssuance(false ,false, e.getMessage(), null);
|
||||
return ResponseEntity.status(statusCode).body(errorJson);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.info("Token request[/mapi/oauth2/token] => clientId: {}, grantType: {}, scope: {}",
|
||||
clientId, grantType, scopes);
|
||||
logger.error(e.getMessage());
|
||||
String errorJson = MessageUtil.makeJsonErrorMessage(MessageUtil.ERROR_CODE_AUTH_FAIL, "Unauthorized. [Unknown]");
|
||||
logTokenIssuance(false ,false, e.getMessage(), null);
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorJson);
|
||||
}finally {
|
||||
RequestContextData.ThreadLocalRequestContext.clear();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private String extractIpAddress(HttpServletRequest request) {
|
||||
String ipAddress = request.getHeader("X-Forwarded-For");
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("HTTP_CLIENT_IP");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getRemoteAddr();
|
||||
}
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
private void verifyClient(ClientDetails clientDetails, String clientId, String clientSecret, Set<String> scopeSet)
|
||||
throws JwtAuthException {
|
||||
|
||||
if (StringUtils.isBlank(clientId)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {client_id}");
|
||||
}
|
||||
|
||||
if (clientDetails == null) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [client not found]");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(clientSecret)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {client_secret}");
|
||||
}
|
||||
|
||||
if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [Bad client credentials(Client Secret is not match)]");
|
||||
}
|
||||
|
||||
if (scopeSet.isEmpty()) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {scope}");
|
||||
}
|
||||
|
||||
if (!clientDetails.getScope().containsAll(scopeSet)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [Bad client credentials(Include unacceptable scope)]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private TokenEndpoint tokenEndpoint() {
|
||||
return BeanUtils.getBean("tokenEndpoint", TokenEndpoint.class);
|
||||
}
|
||||
|
||||
private void logTokenIssuance(boolean isSuccess, boolean isRestrictionExempt, String resultMessage, String accessToken) {
|
||||
try {
|
||||
if (!EAIDBLogControl.isEnable()) {
|
||||
logger.warn("DB logging is disabled. Skipping token issuance logging.");
|
||||
return;
|
||||
}
|
||||
RequestContextData data = RequestContextData.ThreadLocalRequestContext.get();
|
||||
OAuth2Manager.getInstance();
|
||||
|
||||
TokenIssuanceLog log = new TokenIssuanceLog();
|
||||
String clientId = data.getClientId();
|
||||
log.setClientId(clientId);
|
||||
|
||||
if(StringUtils.isNotBlank(clientId)) {
|
||||
ClientVO clientVO = OAuth2Manager.getInstance().getClientInfo(clientId);
|
||||
log.setAppName(clientVO.getClientName());
|
||||
log.setOrgId(clientVO.getOrgId());
|
||||
log.setOrgName(clientVO.getOrgName());
|
||||
}
|
||||
|
||||
log.setGrantType(data.getGrantType());
|
||||
log.setScope(data.getScope());
|
||||
log.setIpAddress(data.getIpAddress());
|
||||
log.setSuccessYn(isSuccess ? "Y" : "N");
|
||||
log.setIssuanceDateTime(LocalDateTime.now());
|
||||
log.setRestrictionExemptYn(isRestrictionExempt ? "Y" : "N");
|
||||
log.setResultMessage(resultMessage);
|
||||
log.setAccessToken(accessToken); // Add access token value to the log
|
||||
|
||||
tokenIssuanceLogDAO.saveTokenIssuanceLog(log);
|
||||
} catch (Throwable th) {
|
||||
logger.error("Error while logging token issuance: " + th.getMessage(), th);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// First generate a public/private key pair
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
|
||||
// generator.initialize(512, new SecureRandom());
|
||||
//generator.initialize(1024, new SecureRandom());
|
||||
generator.initialize(2048, new SecureRandom());
|
||||
KeyPair pair = generator.generateKeyPair();
|
||||
|
||||
// The private key can be used to sign (not encrypt!) a message. The public key
|
||||
// holder can then verify the message.
|
||||
|
||||
String message = "sSGJDwlJsel5WeXodzd3J3MQ20KYCZpL|2022-12-21T14:36:19+07:00";
|
||||
|
||||
// Let's sign our message
|
||||
Signature privateSignature = Signature.getInstance("SHA256withRSA");
|
||||
privateSignature.initSign(pair.getPrivate());
|
||||
privateSignature.update(message.getBytes(StandardCharsets.UTF_8));
|
||||
// System.out.println("private key=" + Base64.getEncoder().encodeToString(pair.getPrivate().getEncoded()));
|
||||
byte[] signature = privateSignature.sign();
|
||||
//System.out.println("signature=" + new String(signature, StandardCharsets.UTF_8));
|
||||
// System.out.println("signature=" + Base64.getEncoder().encodeToString(signature));
|
||||
|
||||
// Let's check the signature
|
||||
Signature publicSignature = Signature.getInstance("SHA256withRSA");
|
||||
publicSignature.initVerify(pair.getPublic());
|
||||
publicSignature.update(message.getBytes(StandardCharsets.UTF_8));
|
||||
boolean isCorrect = publicSignature.verify(signature);
|
||||
// System.out.println("public key=" + Base64.getEncoder().encodeToString(pair.getPublic().getEncoded()));
|
||||
|
||||
// System.out.println("Signature correct: " + isCorrect);
|
||||
|
||||
// The public key can be used to encrypt a message, the private key can be used
|
||||
// to decrypt it.
|
||||
// Encrypt the message
|
||||
Cipher encryptCipher = Cipher.getInstance("RSA");
|
||||
encryptCipher.init(Cipher.ENCRYPT_MODE, pair.getPublic());
|
||||
|
||||
byte[] cipherText = encryptCipher.doFinal(message.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// Now decrypt it
|
||||
Cipher decriptCipher = Cipher.getInstance("RSA");
|
||||
decriptCipher.init(Cipher.DECRYPT_MODE, pair.getPrivate());
|
||||
|
||||
String decipheredMessage = new String(decriptCipher.doFinal(cipherText), StandardCharsets.UTF_8);
|
||||
|
||||
// System.out.println(decipheredMessage);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.eactive.eai.authserver.custom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class SnapOAuth2AccessTokenRequest implements Serializable {
|
||||
private String grantType;
|
||||
private String authCode;
|
||||
private String refreshToken;
|
||||
private Object additionalInfo;
|
||||
|
||||
public String getGrantType() {
|
||||
return grantType;
|
||||
}
|
||||
|
||||
public void setGrantType(String grantType) {
|
||||
this.grantType = grantType;
|
||||
}
|
||||
|
||||
public String getAuthCode() {
|
||||
return authCode;
|
||||
}
|
||||
|
||||
public void setAuthCode(String authCode) {
|
||||
this.authCode = authCode;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public Object getAdditionalInfo() {
|
||||
return additionalInfo;
|
||||
}
|
||||
|
||||
public void setAdditionalInfo(Object additionalInfo) {
|
||||
this.additionalInfo = additionalInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SnapOAuth2AccessTokenRequest [grantType=" + grantType + ", authCode=" + authCode + ", refreshToken="
|
||||
+ refreshToken + ", additionalInfo=" + additionalInfo + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package com.eactive.eai.authserver.custom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
public class SnapOAuth2AccessTokenResponse implements Serializable {
|
||||
private String responseCode;
|
||||
private String responseMessage;
|
||||
private String accessToken;
|
||||
private String tokenType;
|
||||
private String expiresIn;
|
||||
private Object additionalInfo;
|
||||
|
||||
public String getResponseCode() {
|
||||
return responseCode;
|
||||
}
|
||||
|
||||
public void setResponseCode(String responseCode) {
|
||||
this.responseCode = responseCode;
|
||||
}
|
||||
|
||||
public String getResponseMessage() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
public void setResponseMessage(String responseMessage) {
|
||||
this.responseMessage = responseMessage;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
public String getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
public void setExpiresIn(String expiresIn) {
|
||||
this.expiresIn = expiresIn;
|
||||
}
|
||||
|
||||
public Object getAdditionalInfo() {
|
||||
return additionalInfo;
|
||||
}
|
||||
|
||||
public void setAdditionalInfo(Object additionalInfo) {
|
||||
this.additionalInfo = additionalInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SnapOAuth2AccessTokenResponse [responseCode=" + responseCode + ", responseMessage=" + responseMessage
|
||||
+ ", accessToken=" + accessToken + ", tokenType=" + tokenType + ", expiresIn=" + expiresIn
|
||||
+ ", additionalInfo=" + additionalInfo + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
package com.eactive.eai.authserver.custom;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.Principal;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Signature;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Request;
|
||||
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException;
|
||||
import com.eactive.eai.authserver.service.OAuth2Manager;
|
||||
import com.eactive.eai.authserver.util.BeanUtils;
|
||||
import com.eactive.eai.authserver.vo.ClientVO;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
|
||||
@Controller
|
||||
public class SnapOAuth2Controller {
|
||||
public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
private static final String HEADER_TIMESTAMP = "X-TIMESTAMP";
|
||||
private static final String HEADER_CLIENT_ID = "X-CLIENT-KEY";
|
||||
private static final String HEADER_SIGNATURE = "X-SIGNATURE";
|
||||
|
||||
private static final String SERVICE_CODE_ACCESS_TOKEN = "00"; // 임시설정
|
||||
|
||||
@RequestMapping(value = "/bukopin_snap_api/v1.0/access-token/b2b", method = RequestMethod.POST, produces = "application/json; charset=\"UTF-8\"")
|
||||
@ResponseBody
|
||||
public SnapOAuth2AccessTokenResponse token(@RequestBody SnapOAuth2AccessTokenRequest tokenRequest,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(tokenRequest.toString());
|
||||
}
|
||||
|
||||
SnapOAuth2AccessTokenResponse responseToken = new SnapOAuth2AccessTokenResponse();
|
||||
try {
|
||||
if (!StringUtils.equals(tokenRequest.getGrantType(), "client_credentials")) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {grantType}");
|
||||
}
|
||||
|
||||
String timeStamp = request.getHeader(HEADER_TIMESTAMP);
|
||||
String clientId = request.getHeader(HEADER_CLIENT_ID);
|
||||
String signature = request.getHeader(HEADER_SIGNATURE);
|
||||
|
||||
ClientDetails clientDetails = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId);
|
||||
verifyClient(clientDetails, timeStamp, clientId, signature);
|
||||
|
||||
response.setHeader(HEADER_TIMESTAMP, timeStamp);
|
||||
response.setHeader(HEADER_CLIENT_ID, clientId);
|
||||
|
||||
HashMap<String, String> authorizationParameters = new HashMap<String, String>();
|
||||
authorizationParameters.put(OAuth2Utils.GRANT_TYPE, tokenRequest.getGrantType());
|
||||
authorizationParameters.put(OAuth2Utils.CLIENT_ID, clientId);
|
||||
authorizationParameters.put("client_secret", clientDetails.getClientSecret());
|
||||
|
||||
Set<String> responseType = new HashSet<String>();
|
||||
responseType.add(tokenRequest.getGrantType());
|
||||
|
||||
OAuth2Request authorizationRequest = new OAuth2Request(authorizationParameters, clientId, null, true, null,
|
||||
null, "", responseType, null);
|
||||
|
||||
Principal principal = new OAuth2Authentication(authorizationRequest, null);
|
||||
ResponseEntity<OAuth2AccessToken> result = tokenEndpoint().postAccessToken(principal,
|
||||
authorizationParameters);
|
||||
OAuth2AccessToken token = result.getBody();
|
||||
responseToken.setAccessToken(token.getValue());
|
||||
responseToken.setExpiresIn(String.valueOf(token.getExpiresIn()));
|
||||
responseToken.setTokenType(token.getTokenType());
|
||||
} catch (JwtAuthException e) {
|
||||
response.setStatus(NumberUtils.toInt(StringUtils.left(e.getCode(), 3), HttpStatus.UNAUTHORIZED.value()));
|
||||
responseToken.setResponseCode(e.getCode());
|
||||
responseToken.setResponseMessage(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
responseToken.setResponseCode(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"));
|
||||
responseToken.setResponseMessage("Unauthorized. [Unknown]");
|
||||
}
|
||||
|
||||
return responseToken;
|
||||
}
|
||||
|
||||
private void verifyClient(ClientDetails clientDetails, String timeStamp, String clientId, String signatureStr)
|
||||
throws JwtAuthException {
|
||||
if (StringUtils.isBlank(timeStamp)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {" + HEADER_TIMESTAMP + "}");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(clientId)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {" + HEADER_CLIENT_ID + "}");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(signatureStr)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {" + HEADER_SIGNATURE + "}");
|
||||
}
|
||||
|
||||
if (clientDetails == null) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [client not found]");
|
||||
}
|
||||
|
||||
String publicKeyStr = ((ClientVO) clientDetails).getSecurityKey();
|
||||
if (StringUtils.isBlank(publicKeyStr)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [public key not found]");
|
||||
}
|
||||
|
||||
try {
|
||||
String message = clientId + "|" + timeStamp;
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr));
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
PublicKey publicKey = keyFactory.generatePublic(keySpec);
|
||||
|
||||
Signature signature = Signature.getInstance("SHA256withRSA");
|
||||
signature.initVerify(publicKey);
|
||||
signature.update(message.getBytes(StandardCharsets.UTF_8));
|
||||
if (!signature.verify(Base64.getDecoder().decode(signatureStr))) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [Signature not matched]");
|
||||
}
|
||||
} catch (JwtAuthException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [Signature fail]");
|
||||
}
|
||||
}
|
||||
|
||||
private TokenEndpoint tokenEndpoint() {
|
||||
return BeanUtils.getBean("tokenEndpoint", TokenEndpoint.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// First generate a public/private key pair
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
|
||||
// generator.initialize(512, new SecureRandom());
|
||||
//generator.initialize(1024, new SecureRandom());
|
||||
generator.initialize(2048, new SecureRandom());
|
||||
KeyPair pair = generator.generateKeyPair();
|
||||
|
||||
// The private key can be used to sign (not encrypt!) a message. The public key
|
||||
// holder can then verify the message.
|
||||
|
||||
String message = "sSGJDwlJsel5WeXodzd3J3MQ20KYCZpL|2022-12-21T14:36:19+07:00";
|
||||
|
||||
// Let's sign our message
|
||||
Signature privateSignature = Signature.getInstance("SHA256withRSA");
|
||||
privateSignature.initSign(pair.getPrivate());
|
||||
privateSignature.update(message.getBytes(StandardCharsets.UTF_8));
|
||||
System.out.println(
|
||||
"private key=" + Base64.getEncoder().encodeToString(pair.getPrivate().getEncoded()));
|
||||
|
||||
byte[] signature = privateSignature.sign();
|
||||
//System.out.println("signature=" + new String(signature, StandardCharsets.UTF_8));
|
||||
System.out.println("signature=" + Base64.getEncoder().encodeToString(signature));
|
||||
|
||||
// Let's check the signature
|
||||
Signature publicSignature = Signature.getInstance("SHA256withRSA");
|
||||
publicSignature.initVerify(pair.getPublic());
|
||||
publicSignature.update(message.getBytes(StandardCharsets.UTF_8));
|
||||
boolean isCorrect = publicSignature.verify(signature);
|
||||
System.out.println("public key=" + Base64.getEncoder().encodeToString(pair.getPublic().getEncoded()));
|
||||
|
||||
System.out.println("Signature correct: " + isCorrect);
|
||||
|
||||
// The public key can be used to encrypt a message, the private key can be used
|
||||
// to decrypt it.
|
||||
// Encrypt the message
|
||||
Cipher encryptCipher = Cipher.getInstance("RSA");
|
||||
encryptCipher.init(Cipher.ENCRYPT_MODE, pair.getPublic());
|
||||
|
||||
byte[] cipherText = encryptCipher.doFinal(message.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// Now decrypt it
|
||||
Cipher decriptCipher = Cipher.getInstance("RSA");
|
||||
decriptCipher.init(Cipher.DECRYPT_MODE, pair.getPrivate());
|
||||
|
||||
String decipheredMessage = new String(decriptCipher.doFinal(cipherText), StandardCharsets.UTF_8);
|
||||
|
||||
System.out.println(decipheredMessage);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user