wellknown接口优化

This commit is contained in:
shimingxy 2024-10-31 18:14:17 +08:00
parent 6be5bc0d0f
commit 9896c141ef
3 changed files with 106 additions and 82 deletions

View File

@ -38,34 +38,46 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@Tag(name = "2-1-OAuth v2.0 API文档模块") @Tag(name = "2-1-OAuth v2.0 API文档模块")
@Controller @Controller
public class OauthJwksEndpoint extends AbstractEndpoint { public class OauthJwksEndpoint extends AbstractEndpoint {
static final Logger _logger = LoggerFactory.getLogger(OauthJwksEndpoint.class); static final Logger _logger = LoggerFactory.getLogger(OauthJwksEndpoint.class);
@Operation(summary = "OAuth JWk 元数据接口", description = "参数mxk_metadata_APPID",method="GET") @Operation(summary = "OAuth JWk 元数据接口", description = "参数inst_id , client_id",method="GET")
@RequestMapping( @RequestMapping(value = OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks",
value = OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks",
method={RequestMethod.POST, RequestMethod.GET}) method={RequestMethod.POST, RequestMethod.GET})
@ResponseBody @ResponseBody
public void keysMetadata(HttpServletRequest request , HttpServletResponse response, public String keysMetadataByParam(HttpServletRequest request , HttpServletResponse response,
@RequestParam(value = "client_id", required = false) String client_id) throws IOException { @RequestParam(required = false) String inst_id,
metadata(request,response,client_id,null); @RequestParam(required = false) String client_id) {
return buildMetadata(request,response,inst_id,client_id,ContentType.JSON);
} }
@Operation(summary = "OAuth JWk 元数据接口", description = "参数mxk_metadata_APPID",method="GET") @Operation(summary = "OAuth JWk 元数据接口", description = "参数instId , clientId",method="GET")
@RequestMapping( @RequestMapping(value = OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/{instId}/{clientId}/jwks",
value = "/metadata/oauth/v20/" + WebConstants.MXK_METADATA_PREFIX + "{appid}.{mediaType}",
method={RequestMethod.POST, RequestMethod.GET}) method={RequestMethod.POST, RequestMethod.GET})
@ResponseBody @ResponseBody
public void metadata(HttpServletRequest request , HttpServletResponse response, public String keysMetadatabyPath(HttpServletRequest request , HttpServletResponse response,
@PathVariable(value="appid", required = false) String appId, @PathVariable String instId,@PathVariable String clientId) {
@PathVariable(value="mediaType", required = false) String mediaType) throws IOException { return buildMetadata(request,response,instId,clientId,ContentType.JSON);
}
@Operation(summary = "OAuth JWk 元数据接口", description = "参数mxk_metadata_clientId",method="GET")
@RequestMapping(
value = "/metadata/oauth/v20/" + WebConstants.MXK_METADATA_PREFIX + "{clientId}.{mediaType}",
method={RequestMethod.POST, RequestMethod.GET})
@ResponseBody
public String metadata(HttpServletRequest request , HttpServletResponse response,
@PathVariable(value="clientId", required = false) String clientId,
@PathVariable(value="mediaType", required = false) String mediaType) {
return buildMetadata(request,response,null,clientId,mediaType);
}
public String buildMetadata(HttpServletRequest request , HttpServletResponse response,
String instId,String clientId,String mediaType){
ClientDetails clientDetails = null; ClientDetails clientDetails = null;
try { try {
clientDetails = getClientDetailsService().loadClientByClientId(appId,true); clientDetails = getClientDetailsService().loadClientByClientId(clientId,true);
}catch(Exception e) { }catch(Exception e) {
_logger.error("getClientDetailsService", e); _logger.error("getClientDetailsService", e);
} }
@ -83,18 +95,15 @@ public class OauthJwksEndpoint extends AbstractEndpoint {
} }
JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": [" + jwkSetString + "]}"); JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": [" + jwkSetString + "]}");
if(StringUtils.hasText(mediaType) if(StringUtils.hasText(mediaType) && mediaType.equalsIgnoreCase(ContentType.XML)) {
&& mediaType.equalsIgnoreCase(ContentType.XML)) {
response.setContentType(ContentType.APPLICATION_XML_UTF8); response.setContentType(ContentType.APPLICATION_XML_UTF8);
}else { }else {
response.setContentType(ContentType.APPLICATION_JSON_UTF8); response.setContentType(ContentType.APPLICATION_JSON_UTF8);
} }
response.getWriter().write(jwkSetKeyStore.toString(mediaType)); return jwkSetKeyStore.toString(mediaType);
} else { } else {
response.getWriter().write(appId + " not exist . \n" + WebContext.version()); return clientId + " not exist . \n" + WebContext.version();
} }
} }
} }

View File

@ -20,11 +20,11 @@ package org.dromara.maxkey.authz.oauth2.provider.wellknown.endpoint;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.dromara.maxkey.authz.oauth2.common.OAuth2Constants; import org.dromara.maxkey.authz.oauth2.common.OAuth2Constants;
import org.dromara.maxkey.authz.oauth2.provider.endpoint.AbstractEndpoint; import org.dromara.maxkey.authz.oauth2.provider.endpoint.AbstractEndpoint;
import org.dromara.maxkey.authz.oauth2.provider.wellknown.OauthServerConfiguration; import org.dromara.maxkey.authz.oauth2.provider.wellknown.OauthServerConfiguration;
import org.dromara.maxkey.entity.apps.oauth2.provider.ClientDetails; import org.dromara.maxkey.entity.apps.oauth2.provider.ClientDetails;
import org.dromara.maxkey.pretty.impl.JsonPretty;
import org.dromara.maxkey.web.WebContext; import org.dromara.maxkey.web.WebContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -35,52 +35,46 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.cloud.commons.lang.StringUtils;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Tag(name = "2-1-OAuth v2.0 API文档模块") @Tag(name = "2-1-OAuth v2.0 API文档模块")
@Controller @Controller
public class OauthAuthorizationServerEndpoint extends AbstractEndpoint { public class OauthAuthorizationServerEndpoint extends AbstractEndpoint {
static final Logger _logger = LoggerFactory.getLogger(OauthAuthorizationServerEndpoint.class); static final Logger _logger = LoggerFactory.getLogger(OauthAuthorizationServerEndpoint.class);
@Operation(summary = "OAuth v2 metadata 元数据接口", description = "参数client_id",method="GET,POST") @Operation(summary = "OAuth v2 metadata 元数据接口", description = "参数client_id",method="GET,POST")
@RequestMapping( @RequestMapping(value = {OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/.well-known/oauth-authorization-server"},
value = {
OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/.well-known/oauth-authorization-server"},
produces = "application/json", produces = "application/json",
method={RequestMethod.POST, RequestMethod.GET}) method={RequestMethod.POST, RequestMethod.GET})
@ResponseBody @ResponseBody
public String configuration( public OauthServerConfiguration configurationByParam(
HttpServletRequest request, @RequestParam(value = "inst_id", required = false) String inst_id,
HttpServletResponse response,
@RequestParam(value = "client_id", required = false) String client_id) { @RequestParam(value = "client_id", required = false) String client_id) {
return configurationMetadata(request,response, null,client_id); return configurationMetadata( inst_id,client_id,"RequestParam");
} }
@Operation(summary = "OAuth v2 metadata 元数据接口", description = "参数client_id",method="GET,POST") @Operation(summary = "OAuth v2 metadata 元数据接口", description = "参数instId,client_id",method="GET,POST")
@RequestMapping( @RequestMapping(value = {OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/{instId}/{clientId}/.well-known/oauth-authorization-server"},
value = {
OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/{instId}/.well-known/oauth-authorization-server"},
produces = "application/json", produces = "application/json",
method={RequestMethod.POST, RequestMethod.GET}) method={RequestMethod.POST, RequestMethod.GET})
@ResponseBody @ResponseBody
public String configurationMetadata( public OauthServerConfiguration configurationByPath(
HttpServletRequest request,
HttpServletResponse response,
@PathVariable("instId") String instId, @PathVariable("instId") String instId,
@RequestParam(value = "client_id", required = false) String client_id) { @PathVariable(value = "clientId", required = false) String clientId) {
_logger.debug("instId {} , client_id {}" , instId ,client_id); return configurationMetadata(instId,clientId,"PathVariable");
}
public OauthServerConfiguration configurationMetadata(String instId,String clientId,String param) {
_logger.debug("instId {} , client_id {}" , instId ,clientId);
String baseUrl = WebContext.getContextPath(true); String baseUrl = WebContext.getContextPath(true);
ClientDetails clientDetails = null; ClientDetails clientDetails = null;
if(StringUtils.isNotBlank(client_id)) { if(StringUtils.isNotBlank(clientId)) {
try { try {
clientDetails = getClientDetailsService().loadClientByClientId(client_id,true); clientDetails = getClientDetailsService().loadClientByClientId(clientId,true);
}catch(Exception e) { }catch(Exception e) {
_logger.error("getClientDetailsService", e); _logger.error("getClientDetailsService", e);
} }
@ -99,15 +93,29 @@ public class OauthAuthorizationServerEndpoint extends AbstractEndpoint {
oauthConfig.setCode_challenge_methods_supported(code_challenge_methods_supported); oauthConfig.setCode_challenge_methods_supported(code_challenge_methods_supported);
if(clientDetails != null) { if(clientDetails != null) {
oauthConfig.setClient_id(client_id); oauthConfig.setClient_id(clientId);
oauthConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks?client_id="+ clientDetails.getClientId()); if(param.equals("RequestParam")){
StringBuffer jwksUri = new StringBuffer(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks");
jwksUri.append("?");
jwksUri.append("client_id").append("=").append(clientDetails.getClientId());
if(StringUtils.isNotBlank(instId)) {
jwksUri.append("&").append("inst_id").append("=").append(clientDetails.getClientId());
}
oauthConfig.setJwks_uri(jwksUri.toString());
}else {
oauthConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/"+instId+"/"+clientId+"/jwks");
}
Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>(); Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>();
introspection_endpoint_auth_methods_supported.add("client_secret_basic"); introspection_endpoint_auth_methods_supported.add("client_secret_basic");
oauthConfig.setIntrospection_endpoint_auth_methods_supported(introspection_endpoint_auth_methods_supported); oauthConfig.setIntrospection_endpoint_auth_methods_supported(introspection_endpoint_auth_methods_supported);
oauthConfig.setIssuer(clientDetails.getIssuer()); oauthConfig.setIssuer(clientDetails.getIssuer());
oauthConfig.setResponse_types_supported(clientDetails.getAuthorizedGrantTypes()); Set<String> response_types_supported =clientDetails.getAuthorizedGrantTypes();
if(response_types_supported.contains("authorization_code")) {
response_types_supported.add("code");
}
oauthConfig.setResponse_types_supported(response_types_supported);
Set<String> response_modes_supported = new HashSet<String>(); Set<String> response_modes_supported = new HashSet<String>();
response_modes_supported.add("query"); response_modes_supported.add("query");
@ -175,7 +183,7 @@ public class OauthAuthorizationServerEndpoint extends AbstractEndpoint {
oauthConfig.setClaims_supported(claims_supported); oauthConfig.setClaims_supported(claims_supported);
}else { }else {
oauthConfig.setClient_id(client_id); oauthConfig.setClient_id(clientId);
oauthConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks"); oauthConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks");
Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>(); Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>();
@ -265,6 +273,6 @@ public class OauthAuthorizationServerEndpoint extends AbstractEndpoint {
oauthConfig.setClaims_supported(claims_supported); oauthConfig.setClaims_supported(claims_supported);
} }
return JsonPretty.getInstance().format(oauthConfig,true); return oauthConfig;
} }
} }

View File

@ -20,8 +20,6 @@ package org.dromara.maxkey.authz.oauth2.provider.wellknown.endpoint;
import com.alibaba.cloud.commons.lang.StringUtils; import com.alibaba.cloud.commons.lang.StringUtils;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.maxkey.authz.oauth2.common.OAuth2Constants; import org.dromara.maxkey.authz.oauth2.common.OAuth2Constants;
import org.dromara.maxkey.authz.oauth2.provider.endpoint.AbstractEndpoint; import org.dromara.maxkey.authz.oauth2.provider.endpoint.AbstractEndpoint;
import org.dromara.maxkey.authz.oauth2.provider.wellknown.OpenidConfiguration; import org.dromara.maxkey.authz.oauth2.provider.wellknown.OpenidConfiguration;
@ -41,41 +39,40 @@ public class OpenidConfigurationEndpoint extends AbstractEndpoint {
static final Logger _logger = LoggerFactory.getLogger(OpenidConfigurationEndpoint.class); static final Logger _logger = LoggerFactory.getLogger(OpenidConfigurationEndpoint.class);
@Operation(summary = "OpenID Connect metadata 元数据接口", description = "参数client_id",method="GET,POST") @Operation(summary = "OpenID Connect metadata 元数据接口", description = "参数inst_id,client_id",method="GET,POST")
@RequestMapping( @RequestMapping(value = {OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/.well-known/openid-configuration"},
value = {
OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/.well-known/openid-configuration"},
produces = "application/json", produces = "application/json",
method={RequestMethod.POST, RequestMethod.GET}) method={RequestMethod.POST, RequestMethod.GET})
@ResponseBody @ResponseBody
public OpenidConfiguration configuration( public OpenidConfiguration configurationByParam(
HttpServletRequest request, @RequestParam(value = "inst_id", required = false) String inst_id,
HttpServletResponse response,
@RequestParam(value = "client_id", required = false) String client_id) { @RequestParam(value = "client_id", required = false) String client_id) {
return configurationMetadata(request,response, null,client_id); _logger.debug("Configuration By Param");
return configurationMetadata(inst_id,client_id,"RequestParam");
} }
@Operation(summary = "OpenID Connect metadata 元数据接口", description = "参数client_id",method="GET,POST") @Operation(summary = "OpenID Connect metadata 元数据接口", description = "参数Path",method="GET,POST")
@RequestMapping( @RequestMapping(value = {OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/{instId}/{clientId}/.well-known/openid-configuration"},
value = {
OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/{instId}/.well-known/openid-configuration"},
produces = "application/json", produces = "application/json",
method={RequestMethod.POST, RequestMethod.GET}) method={RequestMethod.POST, RequestMethod.GET})
@ResponseBody @ResponseBody
public OpenidConfiguration configurationMetadata( public OpenidConfiguration configurationByPath(
HttpServletRequest request,
HttpServletResponse response,
@PathVariable("instId") String instId , @PathVariable("instId") String instId ,
@RequestParam(value = "client_id", required = false) String client_id) { @PathVariable(value = "clientId") String clientId) {
_logger.debug("instId {} , client_id {}" , instId ,client_id); _logger.debug("Configuration By Path");
return configurationMetadata(instId,clientId,"PathVariable");
}
public OpenidConfiguration configurationMetadata(String instId,String clientId,String param) {
_logger.debug("instId {} , client_id {}" , instId ,clientId);
String baseUrl = WebContext.getContextPath(true); String baseUrl = WebContext.getContextPath(true);
ClientDetails clientDetails = null; ClientDetails clientDetails = null;
if(StringUtils.isNotBlank(client_id)) { if(StringUtils.isNotBlank(clientId)) {
try { try {
clientDetails = getClientDetailsService().loadClientByClientId(client_id,true); clientDetails = getClientDetailsService().loadClientByClientId(clientId,true);
}catch(Exception e) { }catch(Exception e) {
_logger.error("getClientDetailsService", e); _logger.error("getClientDetailsService", e);
} }
@ -90,8 +87,18 @@ public class OpenidConfigurationEndpoint extends AbstractEndpoint {
openidConfig.setEnd_session_endpoint(baseUrl + "/force/logout"); openidConfig.setEnd_session_endpoint(baseUrl + "/force/logout");
if(clientDetails != null) { if(clientDetails != null) {
openidConfig.setClient_id(client_id); openidConfig.setClient_id(clientId);
openidConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks?client_id=" + clientDetails.getClientId()); if(param.equals("RequestParam")){
StringBuffer jwksUri = new StringBuffer(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks");
jwksUri.append("?");
jwksUri.append("client_id").append("=").append(clientDetails.getClientId());
if(StringUtils.isNotBlank(instId)) {
jwksUri.append("&").append("inst_id").append("=").append(clientDetails.getClientId());
}
openidConfig.setJwks_uri(jwksUri.toString());
}else {
openidConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/"+instId+"/"+clientId+"/jwks");
}
Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>(); Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>();
introspection_endpoint_auth_methods_supported.add("client_secret_basic"); introspection_endpoint_auth_methods_supported.add("client_secret_basic");
@ -170,7 +177,7 @@ public class OpenidConfigurationEndpoint extends AbstractEndpoint {
openidConfig.setClaims_supported(claims_supported); openidConfig.setClaims_supported(claims_supported);
}else { }else {
openidConfig.setClient_id(client_id); openidConfig.setClient_id(clientId);
openidConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks"); openidConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks");
Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>(); Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>();