OpenID Connect metadata
This commit is contained in:
@@ -23,7 +23,6 @@ import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.mybatis.jpa.util.JpaWebContext;
|
||||
import org.maxkey.authn.annotation.CurrentUser;
|
||||
import org.maxkey.authn.web.AuthorizationUtils;
|
||||
import org.maxkey.authz.oauth2.common.OAuth2AccessToken;
|
||||
@@ -46,8 +45,6 @@ import org.maxkey.authz.oauth2.provider.approval.UserApprovalHandler;
|
||||
import org.maxkey.authz.oauth2.provider.code.AuthorizationCodeServices;
|
||||
import org.maxkey.authz.oauth2.provider.implicit.ImplicitTokenRequest;
|
||||
import org.maxkey.authz.oauth2.provider.request.DefaultOAuth2RequestValidator;
|
||||
import org.maxkey.constants.ContentType;
|
||||
import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
|
||||
import org.maxkey.util.HttpEncoder;
|
||||
import org.maxkey.entity.Message;
|
||||
import org.maxkey.entity.UserInfo;
|
||||
@@ -67,11 +64,8 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
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.support.SessionStatus;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
@@ -297,42 +291,6 @@ public class AuthorizationEndpoint extends AbstractEndpoint {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Operation(summary = "OAuth JWk 元数据接口", description = "参数mxk_metadata_APPID",method="GET")
|
||||
@RequestMapping(
|
||||
value = "/metadata/oauth/v20/" + WebConstants.MXK_METADATA_PREFIX + "{appid}.{mediaType}",
|
||||
method={RequestMethod.POST, RequestMethod.GET})
|
||||
@ResponseBody
|
||||
public String metadata(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@PathVariable("appid") String appId,
|
||||
@PathVariable("mediaType") String mediaType) {
|
||||
ClientDetails clientDetails = getClientDetailsService().loadClientByClientId(appId,true);
|
||||
if(clientDetails != null) {
|
||||
String jwkSetString = "";
|
||||
if(!clientDetails.getSignature().equalsIgnoreCase("none")) {
|
||||
jwkSetString = clientDetails.getSignatureKey();
|
||||
}
|
||||
if(!clientDetails.getAlgorithm().equalsIgnoreCase("none")) {
|
||||
if(!StringUtils.hasText(jwkSetString)) {
|
||||
jwkSetString = clientDetails.getAlgorithmKey();
|
||||
}else {
|
||||
jwkSetString = jwkSetString + "," +clientDetails.getAlgorithmKey();
|
||||
}
|
||||
}
|
||||
JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": [" + jwkSetString + "]}");
|
||||
|
||||
if(StringUtils.hasText(mediaType)
|
||||
&& mediaType.equalsIgnoreCase("xml")) {
|
||||
response.setContentType(ContentType.APPLICATION_XML_UTF8);
|
||||
}else {
|
||||
response.setContentType(ContentType.APPLICATION_JSON_UTF8);
|
||||
}
|
||||
return jwkSetKeyStore.toString(mediaType);
|
||||
}
|
||||
|
||||
return appId + " not exist . \n" + JpaWebContext.version();
|
||||
}
|
||||
|
||||
// We need explicit approval from the user.
|
||||
private ModelAndView getUserApprovalPageResponse(Map<String, Object> model,
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed 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.maxkey.authz.oauth2.provider.endpoint;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.maxkey.authn.SignPrincipal;
|
||||
import org.maxkey.authz.oauth2.common.OAuth2Constants;
|
||||
import org.maxkey.authz.oauth2.common.exceptions.OAuth2Exception;
|
||||
import org.maxkey.authz.oauth2.provider.ClientDetailsService;
|
||||
import org.maxkey.authz.oauth2.provider.OAuth2Authentication;
|
||||
import org.maxkey.authz.oauth2.provider.token.DefaultTokenServices;
|
||||
import org.maxkey.util.AuthorizationHeaderCredential;
|
||||
import org.maxkey.util.AuthorizationHeaderUtils;
|
||||
import org.maxkey.util.JsonUtils;
|
||||
import org.maxkey.web.HttpResponseAdapter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
@Tag(name = "2-1-OAuth v2.0 API文档模块")
|
||||
@Controller
|
||||
public class IntrospectEndpoint {
|
||||
final static Logger _logger = LoggerFactory.getLogger(IntrospectEndpoint.class);
|
||||
@Autowired
|
||||
@Qualifier("oauth20JdbcClientDetailsService")
|
||||
private ClientDetailsService clientDetailsService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("oauth20TokenServices")
|
||||
private DefaultTokenServices oauth20tokenServices;
|
||||
|
||||
@Autowired
|
||||
ProviderManager oauth20ClientAuthenticationManager;
|
||||
|
||||
@Autowired
|
||||
protected HttpResponseAdapter httpResponseAdapter;
|
||||
|
||||
@Operation(summary = "OAuth 2.0 令牌验证接口", description = "传递参数token or access_token",method="POST,GET")
|
||||
@RequestMapping(value=OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/introspect", method = {RequestMethod.POST, RequestMethod.GET})
|
||||
public void introspect(
|
||||
@RequestParam(value = "token", required = false) String token,
|
||||
@RequestParam(value = "access_token", required = false) String access_token,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
String authorization = request.getHeader(AuthorizationHeaderUtils.HEADER_Authorization);
|
||||
AuthorizationHeaderCredential headerCredential = AuthorizationHeaderUtils.resolve(authorization);
|
||||
_logger.debug("Credential {}" , headerCredential);
|
||||
if(StringUtils.isNotBlank(token)) {
|
||||
access_token = token;
|
||||
}
|
||||
if(StringUtils.isBlank(access_token)) {
|
||||
_logger.error("access_token is null .");
|
||||
}
|
||||
_logger.debug("access_token {}" , access_token);
|
||||
|
||||
OAuth2Authentication oAuth2Authentication =null;
|
||||
Introspection introspection = new Introspection(access_token);
|
||||
try{
|
||||
oAuth2Authentication = oauth20tokenServices.loadAuthentication(access_token);
|
||||
if(oAuth2Authentication != null && clientAuthenticate(headerCredential)) {
|
||||
String client_id = oAuth2Authentication.getOAuth2Request().getClientId();
|
||||
if(headerCredential.getUsername().equals(client_id)) {
|
||||
String sub = client_id;
|
||||
//if userAuthentication not null , is password or code , else client_credentials
|
||||
if(oAuth2Authentication.getUserAuthentication() != null) {
|
||||
sub = ((SignPrincipal)oAuth2Authentication.getUserAuthentication().getPrincipal()).getUsername();
|
||||
}
|
||||
introspection.setSub(sub,true);
|
||||
}
|
||||
}
|
||||
}catch(OAuth2Exception e){
|
||||
_logger.error("OAuth2Exception ", e);
|
||||
}
|
||||
|
||||
httpResponseAdapter.write(response,JsonUtils.gsonToString(introspection),"json");
|
||||
}
|
||||
|
||||
public boolean clientAuthenticate(AuthorizationHeaderCredential headerCredential) {
|
||||
if(headerCredential != null){
|
||||
UsernamePasswordAuthenticationToken authenticationToken = null;
|
||||
if(headerCredential.getCredentialType().equals(AuthorizationHeaderCredential.Credential.BASIC)) {
|
||||
if(StringUtils.isNotBlank(headerCredential.getUsername())&&
|
||||
StringUtils.isNotBlank(headerCredential.getCredential())
|
||||
) {
|
||||
UsernamePasswordAuthenticationToken authRequest =
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
headerCredential.getUsername(),
|
||||
headerCredential.getCredential());
|
||||
authenticationToken = (UsernamePasswordAuthenticationToken)oauth20ClientAuthenticationManager.authenticate(authRequest);
|
||||
}
|
||||
}
|
||||
if(authenticationToken != null && authenticationToken.isAuthenticated()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setOauth20tokenServices(DefaultTokenServices oauth20tokenServices) {
|
||||
this.oauth20tokenServices = oauth20tokenServices;
|
||||
}
|
||||
|
||||
public class Introspection {
|
||||
|
||||
String token;
|
||||
boolean active;
|
||||
String sub;
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public String getSub() {
|
||||
return sub;
|
||||
}
|
||||
|
||||
public void setSub(String sub,boolean active) {
|
||||
this.sub = sub;
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public Introspection(String token) {
|
||||
this.token = token;
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
public Introspection(String token, boolean active, String sub) {
|
||||
this.token = token;
|
||||
this.active = active;
|
||||
this.sub = sub;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed 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.maxkey.authz.oauth2.provider.endpoint;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.mybatis.jpa.util.JpaWebContext;
|
||||
import org.maxkey.authz.oauth2.common.OAuth2Constants;
|
||||
import org.maxkey.constants.ContentType;
|
||||
import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
|
||||
import org.maxkey.entity.apps.oauth2.provider.ClientDetails;
|
||||
import org.maxkey.web.WebConstants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
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 io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
@Tag(name = "2-1-OAuth v2.0 API文档模块")
|
||||
@Controller
|
||||
public class OauthJwksEndpoint extends AbstractEndpoint {
|
||||
final static Logger _logger = LoggerFactory.getLogger(OauthJwksEndpoint.class);
|
||||
|
||||
@Operation(summary = "OAuth JWk 元数据接口", description = "参数mxk_metadata_APPID",method="GET")
|
||||
@RequestMapping(
|
||||
value = OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks",
|
||||
method={RequestMethod.POST, RequestMethod.GET})
|
||||
@ResponseBody
|
||||
public String keysMetadata(HttpServletRequest request , HttpServletResponse response,
|
||||
@RequestParam(value = "client_id", required = false) String client_id) {
|
||||
return metadata(request,response,client_id,null);
|
||||
}
|
||||
|
||||
@Operation(summary = "OAuth JWk 元数据接口", description = "参数mxk_metadata_APPID",method="GET")
|
||||
@RequestMapping(
|
||||
value = "/metadata/oauth/v20/" + WebConstants.MXK_METADATA_PREFIX + "{appid}.{mediaType}",
|
||||
method={RequestMethod.POST, RequestMethod.GET})
|
||||
@ResponseBody
|
||||
public String metadata(HttpServletRequest request , HttpServletResponse response,
|
||||
@PathVariable(value="appid", required = false) String appId,
|
||||
@PathVariable(value="mediaType", required = false) String mediaType) {
|
||||
ClientDetails clientDetails = null;
|
||||
try {
|
||||
clientDetails = getClientDetailsService().loadClientByClientId(appId,true);
|
||||
}catch(Exception e) {
|
||||
_logger.error("getClientDetailsService", e);
|
||||
}
|
||||
if(clientDetails != null) {
|
||||
String jwkSetString = "";
|
||||
if(!clientDetails.getSignature().equalsIgnoreCase("none")) {
|
||||
jwkSetString = clientDetails.getSignatureKey();
|
||||
}
|
||||
if(!clientDetails.getAlgorithm().equalsIgnoreCase("none")) {
|
||||
if(!StringUtils.hasText(jwkSetString)) {
|
||||
jwkSetString = clientDetails.getAlgorithmKey();
|
||||
}else {
|
||||
jwkSetString = jwkSetString + "," +clientDetails.getAlgorithmKey();
|
||||
}
|
||||
}
|
||||
JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": [" + jwkSetString + "]}");
|
||||
|
||||
if(StringUtils.hasText(mediaType)
|
||||
&& mediaType.equalsIgnoreCase(ContentType.XML)) {
|
||||
response.setContentType(ContentType.APPLICATION_XML_UTF8);
|
||||
}else {
|
||||
response.setContentType(ContentType.APPLICATION_JSON_UTF8);
|
||||
}
|
||||
return jwkSetKeyStore.toString(mediaType);
|
||||
}
|
||||
|
||||
return appId + " not exist . \n" + JpaWebContext.version();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed 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.maxkey.authz.oauth2.provider.wellknown;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class OauthServerConfiguration {
|
||||
String client_id;
|
||||
String issuer;
|
||||
String authorization_endpoint;
|
||||
String token_endpoint;
|
||||
String userinfo_endpoint;
|
||||
String registration_endpoint;
|
||||
String jwks_uri;
|
||||
Set<String> code_challenge_methods_supported;
|
||||
|
||||
Set<String> response_types_supported;
|
||||
Set<String> response_modes_supported;
|
||||
Set<String> grant_types_supported;
|
||||
Set<String> subject_types_supported;
|
||||
Set<String> id_token_signing_alg_values_supported;
|
||||
|
||||
Set<String> scopes_supported;
|
||||
Set<String> token_endpoint_auth_methods_supported;
|
||||
Set<String> claims_supported;
|
||||
String introspection_endpoint;
|
||||
Set<String> introspection_endpoint_auth_methods_supported;
|
||||
String revocation_endpoint;
|
||||
Set<String> revocation_endpoint_auth_methods_supported;
|
||||
String end_session_endpoint;
|
||||
boolean request_parameter_supported;
|
||||
Set<String> request_object_signing_alg_values_supported;
|
||||
Set<String> backchannel_token_delivery_modes_supported;
|
||||
Set<String> backchannel_authentication_request_signing_alg_values_supported;
|
||||
|
||||
|
||||
public String getClient_id() {
|
||||
return client_id;
|
||||
}
|
||||
|
||||
public void setClient_id(String client_id) {
|
||||
this.client_id = client_id;
|
||||
}
|
||||
|
||||
public String getIssuer() {
|
||||
return issuer;
|
||||
}
|
||||
|
||||
public void setIssuer(String issuer) {
|
||||
this.issuer = issuer;
|
||||
}
|
||||
|
||||
public String getAuthorization_endpoint() {
|
||||
return authorization_endpoint;
|
||||
}
|
||||
|
||||
public void setAuthorization_endpoint(String authorization_endpoint) {
|
||||
this.authorization_endpoint = authorization_endpoint;
|
||||
}
|
||||
|
||||
public Set<String> getCode_challenge_methods_supported() {
|
||||
return code_challenge_methods_supported;
|
||||
}
|
||||
|
||||
public void setCode_challenge_methods_supported(Set<String> code_challenge_methods_supported) {
|
||||
this.code_challenge_methods_supported = code_challenge_methods_supported;
|
||||
}
|
||||
|
||||
public String getToken_endpoint() {
|
||||
return token_endpoint;
|
||||
}
|
||||
|
||||
public void setToken_endpoint(String token_endpoint) {
|
||||
this.token_endpoint = token_endpoint;
|
||||
}
|
||||
|
||||
public String getUserinfo_endpoint() {
|
||||
return userinfo_endpoint;
|
||||
}
|
||||
|
||||
public void setUserinfo_endpoint(String userinfo_endpoint) {
|
||||
this.userinfo_endpoint = userinfo_endpoint;
|
||||
}
|
||||
|
||||
public String getRegistration_endpoint() {
|
||||
return registration_endpoint;
|
||||
}
|
||||
|
||||
public void setRegistration_endpoint(String registration_endpoint) {
|
||||
this.registration_endpoint = registration_endpoint;
|
||||
}
|
||||
|
||||
public String getJwks_uri() {
|
||||
return jwks_uri;
|
||||
}
|
||||
|
||||
public void setJwks_uri(String jwks_uri) {
|
||||
this.jwks_uri = jwks_uri;
|
||||
}
|
||||
|
||||
public Set<String> getResponse_types_supported() {
|
||||
return response_types_supported;
|
||||
}
|
||||
|
||||
public void setResponse_types_supported(Set<String> response_types_supported) {
|
||||
this.response_types_supported = response_types_supported;
|
||||
}
|
||||
|
||||
public Set<String> getResponse_modes_supported() {
|
||||
return response_modes_supported;
|
||||
}
|
||||
|
||||
public void setResponse_modes_supported(Set<String> response_modes_supported) {
|
||||
this.response_modes_supported = response_modes_supported;
|
||||
}
|
||||
|
||||
public Set<String> getGrant_types_supported() {
|
||||
return grant_types_supported;
|
||||
}
|
||||
|
||||
public void setGrant_types_supported(Set<String> grant_types_supported) {
|
||||
this.grant_types_supported = grant_types_supported;
|
||||
}
|
||||
|
||||
public Set<String> getSubject_types_supported() {
|
||||
return subject_types_supported;
|
||||
}
|
||||
|
||||
public void setSubject_types_supported(Set<String> subject_types_supported) {
|
||||
this.subject_types_supported = subject_types_supported;
|
||||
}
|
||||
|
||||
public Set<String> getId_token_signing_alg_values_supported() {
|
||||
return id_token_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public void setId_token_signing_alg_values_supported(Set<String> id_token_signing_alg_values_supported) {
|
||||
this.id_token_signing_alg_values_supported = id_token_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public Set<String> getScopes_supported() {
|
||||
return scopes_supported;
|
||||
}
|
||||
|
||||
public void setScopes_supported(Set<String> scopes_supported) {
|
||||
this.scopes_supported = scopes_supported;
|
||||
}
|
||||
|
||||
public Set<String> getToken_endpoint_auth_methods_supported() {
|
||||
return token_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public void setToken_endpoint_auth_methods_supported(Set<String> token_endpoint_auth_methods_supported) {
|
||||
this.token_endpoint_auth_methods_supported = token_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public Set<String> getClaims_supported() {
|
||||
return claims_supported;
|
||||
}
|
||||
|
||||
public void setClaims_supported(Set<String> claims_supported) {
|
||||
this.claims_supported = claims_supported;
|
||||
}
|
||||
|
||||
public String getIntrospection_endpoint() {
|
||||
return introspection_endpoint;
|
||||
}
|
||||
|
||||
public void setIntrospection_endpoint(String introspection_endpoint) {
|
||||
this.introspection_endpoint = introspection_endpoint;
|
||||
}
|
||||
|
||||
public Set<String> getIntrospection_endpoint_auth_methods_supported() {
|
||||
return introspection_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public void setIntrospection_endpoint_auth_methods_supported(
|
||||
Set<String> introspection_endpoint_auth_methods_supported) {
|
||||
this.introspection_endpoint_auth_methods_supported = introspection_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public String getRevocation_endpoint() {
|
||||
return revocation_endpoint;
|
||||
}
|
||||
|
||||
public void setRevocation_endpoint(String revocation_endpoint) {
|
||||
this.revocation_endpoint = revocation_endpoint;
|
||||
}
|
||||
|
||||
public Set<String> getRevocation_endpoint_auth_methods_supported() {
|
||||
return revocation_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public void setRevocation_endpoint_auth_methods_supported(
|
||||
Set<String> revocation_endpoint_auth_methods_supported) {
|
||||
this.revocation_endpoint_auth_methods_supported = revocation_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public String getEnd_session_endpoint() {
|
||||
return end_session_endpoint;
|
||||
}
|
||||
|
||||
public void setEnd_session_endpoint(String end_session_endpoint) {
|
||||
this.end_session_endpoint = end_session_endpoint;
|
||||
}
|
||||
|
||||
public boolean isRequest_parameter_supported() {
|
||||
return request_parameter_supported;
|
||||
}
|
||||
|
||||
public void setRequest_parameter_supported(boolean request_parameter_supported) {
|
||||
this.request_parameter_supported = request_parameter_supported;
|
||||
}
|
||||
|
||||
public Set<String> getRequest_object_signing_alg_values_supported() {
|
||||
return request_object_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public void setRequest_object_signing_alg_values_supported(
|
||||
Set<String> request_object_signing_alg_values_supported) {
|
||||
this.request_object_signing_alg_values_supported = request_object_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public Set<String> getBackchannel_token_delivery_modes_supported() {
|
||||
return backchannel_token_delivery_modes_supported;
|
||||
}
|
||||
|
||||
public void setBackchannel_token_delivery_modes_supported(
|
||||
Set<String> backchannel_token_delivery_modes_supported) {
|
||||
this.backchannel_token_delivery_modes_supported = backchannel_token_delivery_modes_supported;
|
||||
}
|
||||
|
||||
public Set<String> getBackchannel_authentication_request_signing_alg_values_supported() {
|
||||
return backchannel_authentication_request_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public void setBackchannel_authentication_request_signing_alg_values_supported(
|
||||
Set<String> backchannel_authentication_request_signing_alg_values_supported) {
|
||||
this.backchannel_authentication_request_signing_alg_values_supported = backchannel_authentication_request_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public OauthServerConfiguration() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed 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.maxkey.authz.oauth2.provider.wellknown;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class OpenidConfiguration {
|
||||
String client_id;
|
||||
String issuer;
|
||||
String authorization_endpoint;
|
||||
String token_endpoint;
|
||||
String userinfo_endpoint;
|
||||
String registration_endpoint;
|
||||
String jwks_uri;
|
||||
Set<String> response_types_supported;
|
||||
Set<String> response_modes_supported;
|
||||
Set<String> grant_types_supported;
|
||||
Set<String> subject_types_supported;
|
||||
Set<String> id_token_signing_alg_values_supported;
|
||||
|
||||
Set<String> scopes_supported;
|
||||
Set<String> token_endpoint_auth_methods_supported;
|
||||
Set<String> claims_supported;
|
||||
String introspection_endpoint;
|
||||
Set<String> introspection_endpoint_auth_methods_supported;
|
||||
String revocation_endpoint;
|
||||
Set<String> revocation_endpoint_auth_methods_supported;
|
||||
String end_session_endpoint;
|
||||
boolean request_parameter_supported;
|
||||
Set<String> request_object_signing_alg_values_supported;
|
||||
Set<String> backchannel_token_delivery_modes_supported;
|
||||
Set<String> backchannel_authentication_request_signing_alg_values_supported;
|
||||
|
||||
|
||||
public String getClient_id() {
|
||||
return client_id;
|
||||
}
|
||||
|
||||
public void setClient_id(String client_id) {
|
||||
this.client_id = client_id;
|
||||
}
|
||||
|
||||
public String getIssuer() {
|
||||
return issuer;
|
||||
}
|
||||
|
||||
public void setIssuer(String issuer) {
|
||||
this.issuer = issuer;
|
||||
}
|
||||
|
||||
public String getAuthorization_endpoint() {
|
||||
return authorization_endpoint;
|
||||
}
|
||||
|
||||
public void setAuthorization_endpoint(String authorization_endpoint) {
|
||||
this.authorization_endpoint = authorization_endpoint;
|
||||
}
|
||||
|
||||
public String getToken_endpoint() {
|
||||
return token_endpoint;
|
||||
}
|
||||
|
||||
public void setToken_endpoint(String token_endpoint) {
|
||||
this.token_endpoint = token_endpoint;
|
||||
}
|
||||
|
||||
public String getUserinfo_endpoint() {
|
||||
return userinfo_endpoint;
|
||||
}
|
||||
|
||||
public void setUserinfo_endpoint(String userinfo_endpoint) {
|
||||
this.userinfo_endpoint = userinfo_endpoint;
|
||||
}
|
||||
|
||||
public String getRegistration_endpoint() {
|
||||
return registration_endpoint;
|
||||
}
|
||||
|
||||
public void setRegistration_endpoint(String registration_endpoint) {
|
||||
this.registration_endpoint = registration_endpoint;
|
||||
}
|
||||
|
||||
public String getJwks_uri() {
|
||||
return jwks_uri;
|
||||
}
|
||||
|
||||
public void setJwks_uri(String jwks_uri) {
|
||||
this.jwks_uri = jwks_uri;
|
||||
}
|
||||
|
||||
public Set<String> getResponse_types_supported() {
|
||||
return response_types_supported;
|
||||
}
|
||||
|
||||
public void setResponse_types_supported(Set<String> response_types_supported) {
|
||||
this.response_types_supported = response_types_supported;
|
||||
}
|
||||
|
||||
public Set<String> getResponse_modes_supported() {
|
||||
return response_modes_supported;
|
||||
}
|
||||
|
||||
public void setResponse_modes_supported(Set<String> response_modes_supported) {
|
||||
this.response_modes_supported = response_modes_supported;
|
||||
}
|
||||
|
||||
public Set<String> getGrant_types_supported() {
|
||||
return grant_types_supported;
|
||||
}
|
||||
|
||||
public void setGrant_types_supported(Set<String> grant_types_supported) {
|
||||
this.grant_types_supported = grant_types_supported;
|
||||
}
|
||||
|
||||
public Set<String> getSubject_types_supported() {
|
||||
return subject_types_supported;
|
||||
}
|
||||
|
||||
public void setSubject_types_supported(Set<String> subject_types_supported) {
|
||||
this.subject_types_supported = subject_types_supported;
|
||||
}
|
||||
|
||||
public Set<String> getId_token_signing_alg_values_supported() {
|
||||
return id_token_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public void setId_token_signing_alg_values_supported(Set<String> id_token_signing_alg_values_supported) {
|
||||
this.id_token_signing_alg_values_supported = id_token_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public Set<String> getScopes_supported() {
|
||||
return scopes_supported;
|
||||
}
|
||||
|
||||
public void setScopes_supported(Set<String> scopes_supported) {
|
||||
this.scopes_supported = scopes_supported;
|
||||
}
|
||||
|
||||
public Set<String> getToken_endpoint_auth_methods_supported() {
|
||||
return token_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public void setToken_endpoint_auth_methods_supported(Set<String> token_endpoint_auth_methods_supported) {
|
||||
this.token_endpoint_auth_methods_supported = token_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public Set<String> getClaims_supported() {
|
||||
return claims_supported;
|
||||
}
|
||||
|
||||
public void setClaims_supported(Set<String> claims_supported) {
|
||||
this.claims_supported = claims_supported;
|
||||
}
|
||||
|
||||
public String getIntrospection_endpoint() {
|
||||
return introspection_endpoint;
|
||||
}
|
||||
|
||||
public void setIntrospection_endpoint(String introspection_endpoint) {
|
||||
this.introspection_endpoint = introspection_endpoint;
|
||||
}
|
||||
|
||||
public Set<String> getIntrospection_endpoint_auth_methods_supported() {
|
||||
return introspection_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public void setIntrospection_endpoint_auth_methods_supported(
|
||||
Set<String> introspection_endpoint_auth_methods_supported) {
|
||||
this.introspection_endpoint_auth_methods_supported = introspection_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public String getRevocation_endpoint() {
|
||||
return revocation_endpoint;
|
||||
}
|
||||
|
||||
public void setRevocation_endpoint(String revocation_endpoint) {
|
||||
this.revocation_endpoint = revocation_endpoint;
|
||||
}
|
||||
|
||||
public Set<String> getRevocation_endpoint_auth_methods_supported() {
|
||||
return revocation_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public void setRevocation_endpoint_auth_methods_supported(
|
||||
Set<String> revocation_endpoint_auth_methods_supported) {
|
||||
this.revocation_endpoint_auth_methods_supported = revocation_endpoint_auth_methods_supported;
|
||||
}
|
||||
|
||||
public String getEnd_session_endpoint() {
|
||||
return end_session_endpoint;
|
||||
}
|
||||
|
||||
public void setEnd_session_endpoint(String end_session_endpoint) {
|
||||
this.end_session_endpoint = end_session_endpoint;
|
||||
}
|
||||
|
||||
public boolean isRequest_parameter_supported() {
|
||||
return request_parameter_supported;
|
||||
}
|
||||
|
||||
public void setRequest_parameter_supported(boolean request_parameter_supported) {
|
||||
this.request_parameter_supported = request_parameter_supported;
|
||||
}
|
||||
|
||||
public Set<String> getRequest_object_signing_alg_values_supported() {
|
||||
return request_object_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public void setRequest_object_signing_alg_values_supported(
|
||||
Set<String> request_object_signing_alg_values_supported) {
|
||||
this.request_object_signing_alg_values_supported = request_object_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public Set<String> getBackchannel_token_delivery_modes_supported() {
|
||||
return backchannel_token_delivery_modes_supported;
|
||||
}
|
||||
|
||||
public void setBackchannel_token_delivery_modes_supported(
|
||||
Set<String> backchannel_token_delivery_modes_supported) {
|
||||
this.backchannel_token_delivery_modes_supported = backchannel_token_delivery_modes_supported;
|
||||
}
|
||||
|
||||
public Set<String> getBackchannel_authentication_request_signing_alg_values_supported() {
|
||||
return backchannel_authentication_request_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public void setBackchannel_authentication_request_signing_alg_values_supported(
|
||||
Set<String> backchannel_authentication_request_signing_alg_values_supported) {
|
||||
this.backchannel_authentication_request_signing_alg_values_supported = backchannel_authentication_request_signing_alg_values_supported;
|
||||
}
|
||||
|
||||
public OpenidConfiguration() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed 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.maxkey.authz.oauth2.provider.wellknown.endpoint;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.maxkey.authz.oauth2.common.OAuth2Constants;
|
||||
import org.maxkey.authz.oauth2.provider.endpoint.AbstractEndpoint;
|
||||
import org.maxkey.authz.oauth2.provider.wellknown.OauthServerConfiguration;
|
||||
import org.maxkey.entity.apps.oauth2.provider.ClientDetails;
|
||||
import org.maxkey.pretty.impl.JsonPretty;
|
||||
import org.maxkey.web.WebContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
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.alibaba.cloud.commons.lang.StringUtils;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@Tag(name = "2-1-OAuth v2.0 API文档模块")
|
||||
@Controller
|
||||
public class OauthAuthorizationServerEndpoint extends AbstractEndpoint {
|
||||
final static Logger _logger = LoggerFactory.getLogger(OauthAuthorizationServerEndpoint.class);
|
||||
|
||||
@Operation(summary = "OAuth v2 metadata 元数据接口", description = "参数client_id",method="GET,POST")
|
||||
@RequestMapping(
|
||||
value = {
|
||||
OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/.well-known/oauth-authorization-server"},
|
||||
produces = "application/json",
|
||||
method={RequestMethod.POST, RequestMethod.GET})
|
||||
@ResponseBody
|
||||
public String configuration(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@RequestParam(value = "client_id", required = false) String client_id) {
|
||||
return configurationMetadata(request,response, null,client_id);
|
||||
}
|
||||
|
||||
@Operation(summary = "OAuth v2 metadata 元数据接口", description = "参数client_id",method="GET,POST")
|
||||
@RequestMapping(
|
||||
value = {
|
||||
OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/{instId}/.well-known/oauth-authorization-server"},
|
||||
produces = "application/json",
|
||||
method={RequestMethod.POST, RequestMethod.GET})
|
||||
@ResponseBody
|
||||
public String configurationMetadata(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@PathVariable("instId") String instId,
|
||||
@RequestParam(value = "client_id", required = false) String client_id) {
|
||||
_logger.debug("instId {} , client_id {}" , instId ,client_id);
|
||||
|
||||
String baseUrl = WebContext.getContextPath(true);
|
||||
|
||||
ClientDetails clientDetails = null;
|
||||
|
||||
if(StringUtils.isNotBlank(client_id)) {
|
||||
try {
|
||||
clientDetails = getClientDetailsService().loadClientByClientId(client_id,true);
|
||||
}catch(Exception e) {
|
||||
_logger.error("getClientDetailsService", e);
|
||||
}
|
||||
}
|
||||
|
||||
OauthServerConfiguration oauthConfig = new OauthServerConfiguration();
|
||||
oauthConfig.setRequest_parameter_supported(true);
|
||||
oauthConfig.setAuthorization_endpoint(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/authorize");
|
||||
oauthConfig.setToken_endpoint(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/token");
|
||||
oauthConfig.setIntrospection_endpoint(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/introspect");
|
||||
oauthConfig.setUserinfo_endpoint(baseUrl + "/api/oauth/v20/me");
|
||||
oauthConfig.setEnd_session_endpoint(baseUrl + "/force/logout");
|
||||
|
||||
Set<String> code_challenge_methods_supported = new HashSet<String>();
|
||||
code_challenge_methods_supported.add("S256");
|
||||
oauthConfig.setCode_challenge_methods_supported(code_challenge_methods_supported);
|
||||
|
||||
if(clientDetails != null) {
|
||||
oauthConfig.setClient_id(client_id);
|
||||
oauthConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks?client_id="+ clientDetails.getClientId());
|
||||
|
||||
Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>();
|
||||
introspection_endpoint_auth_methods_supported.add("client_secret_basic");
|
||||
oauthConfig.setIntrospection_endpoint_auth_methods_supported(introspection_endpoint_auth_methods_supported);
|
||||
|
||||
oauthConfig.setIssuer(clientDetails.getIssuer());
|
||||
oauthConfig.setResponse_types_supported(clientDetails.getAuthorizedGrantTypes());
|
||||
|
||||
Set<String> response_modes_supported = new HashSet<String>();
|
||||
response_modes_supported.add("query");
|
||||
response_modes_supported.add("form_post");
|
||||
oauthConfig.setResponse_modes_supported(response_modes_supported);
|
||||
|
||||
oauthConfig.setGrant_types_supported(clientDetails.getAuthorizedGrantTypes());
|
||||
oauthConfig.setClaims_supported(clientDetails.getScope());
|
||||
|
||||
|
||||
Set<String> id_token_signing_alg_values_supported = new HashSet<String>();
|
||||
id_token_signing_alg_values_supported.add(clientDetails.getSignature().toUpperCase());
|
||||
oauthConfig.setId_token_signing_alg_values_supported(id_token_signing_alg_values_supported);
|
||||
|
||||
oauthConfig.setScopes_supported(clientDetails.getScope());
|
||||
|
||||
Set<String> token_endpoint_auth_methods_supported = new HashSet<String>();
|
||||
token_endpoint_auth_methods_supported.add("client_secret_basic");
|
||||
token_endpoint_auth_methods_supported.add("client_secret_post");
|
||||
token_endpoint_auth_methods_supported.add("none");
|
||||
oauthConfig.setToken_endpoint_auth_methods_supported(token_endpoint_auth_methods_supported);
|
||||
|
||||
Set<String> claims_supported = new HashSet<String>();
|
||||
claims_supported.add("iss");
|
||||
claims_supported.add("sub");
|
||||
claims_supported.add("aud");
|
||||
claims_supported.add("iat");
|
||||
claims_supported.add("exp");
|
||||
claims_supported.add("jti");
|
||||
claims_supported.add("auth_time");
|
||||
|
||||
claims_supported.add("institution");
|
||||
claims_supported.add("online_ticket");
|
||||
|
||||
claims_supported.add("userId");
|
||||
claims_supported.add("user");
|
||||
claims_supported.add("name");
|
||||
claims_supported.add("preferred_username");
|
||||
claims_supported.add("given_name");
|
||||
claims_supported.add("family_name");
|
||||
claims_supported.add("middle_name");
|
||||
claims_supported.add("nickname");
|
||||
claims_supported.add("displayName");
|
||||
claims_supported.add("departmentId");
|
||||
claims_supported.add("department");
|
||||
claims_supported.add("gender");
|
||||
claims_supported.add("zoneinfo");
|
||||
claims_supported.add("locale");
|
||||
claims_supported.add("updated_time");
|
||||
claims_supported.add("birthdate");
|
||||
|
||||
claims_supported.add("email");
|
||||
claims_supported.add("email_verified");
|
||||
|
||||
claims_supported.add("phone_number");
|
||||
claims_supported.add("phone_number_verified");
|
||||
|
||||
claims_supported.add("address");
|
||||
claims_supported.add("country");
|
||||
claims_supported.add("region");
|
||||
claims_supported.add("locality");
|
||||
claims_supported.add("street_address");
|
||||
claims_supported.add("formatted");
|
||||
claims_supported.add("postal_code");
|
||||
|
||||
oauthConfig.setClaims_supported(claims_supported);
|
||||
}else {
|
||||
oauthConfig.setClient_id(client_id);
|
||||
oauthConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks");
|
||||
|
||||
Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>();
|
||||
introspection_endpoint_auth_methods_supported.add("client_secret_basic");
|
||||
oauthConfig.setIntrospection_endpoint_auth_methods_supported(introspection_endpoint_auth_methods_supported);
|
||||
|
||||
oauthConfig.setIssuer(baseUrl + "/maxkey");
|
||||
Set<String> response_types_supported = new HashSet<String>();
|
||||
response_types_supported.add("code");
|
||||
response_types_supported.add("code id_token");
|
||||
response_types_supported.add("id_token");
|
||||
oauthConfig.setResponse_types_supported(response_types_supported);
|
||||
|
||||
Set<String> response_modes_supported = new HashSet<String>();
|
||||
response_modes_supported.add("query");
|
||||
response_modes_supported.add("form_post");
|
||||
oauthConfig.setResponse_modes_supported(response_modes_supported);
|
||||
|
||||
Set<String> grant_types_supported = new HashSet<String>();
|
||||
grant_types_supported.add("authorization_code");
|
||||
grant_types_supported.add("refresh_token");
|
||||
grant_types_supported.add("password");
|
||||
grant_types_supported.add("client_credentials");
|
||||
oauthConfig.setGrant_types_supported(grant_types_supported);
|
||||
|
||||
Set<String> id_token_signing_alg_values_supported = new HashSet<String>();
|
||||
id_token_signing_alg_values_supported.add("RS256");
|
||||
oauthConfig.setId_token_signing_alg_values_supported(id_token_signing_alg_values_supported);
|
||||
|
||||
Set<String> scopes_supported = new HashSet<String>();
|
||||
scopes_supported.add("openid");
|
||||
scopes_supported.add("email");
|
||||
scopes_supported.add("profile");
|
||||
scopes_supported.add("address");
|
||||
scopes_supported.add("phone");
|
||||
oauthConfig.setScopes_supported(scopes_supported);
|
||||
|
||||
Set<String> token_endpoint_auth_methods_supported = new HashSet<String>();
|
||||
token_endpoint_auth_methods_supported.add("client_secret_basic");
|
||||
token_endpoint_auth_methods_supported.add("client_secret_post");
|
||||
token_endpoint_auth_methods_supported.add("none");
|
||||
oauthConfig.setToken_endpoint_auth_methods_supported(token_endpoint_auth_methods_supported);
|
||||
|
||||
Set<String> claims_supported = new HashSet<String>();
|
||||
claims_supported.add("iss");
|
||||
claims_supported.add("sub");
|
||||
claims_supported.add("aud");
|
||||
claims_supported.add("iat");
|
||||
claims_supported.add("exp");
|
||||
claims_supported.add("jti");
|
||||
claims_supported.add("auth_time");
|
||||
|
||||
claims_supported.add("institution");
|
||||
claims_supported.add("online_ticket");
|
||||
|
||||
claims_supported.add("userId");
|
||||
claims_supported.add("user");
|
||||
claims_supported.add("name");
|
||||
claims_supported.add("preferred_username");
|
||||
claims_supported.add("given_name");
|
||||
claims_supported.add("family_name");
|
||||
claims_supported.add("middle_name");
|
||||
claims_supported.add("nickname");
|
||||
claims_supported.add("displayName");
|
||||
claims_supported.add("departmentId");
|
||||
claims_supported.add("department");
|
||||
claims_supported.add("gender");
|
||||
claims_supported.add("zoneinfo");
|
||||
claims_supported.add("locale");
|
||||
claims_supported.add("updated_time");
|
||||
claims_supported.add("birthdate");
|
||||
|
||||
claims_supported.add("email");
|
||||
claims_supported.add("email_verified");
|
||||
|
||||
claims_supported.add("phone_number");
|
||||
claims_supported.add("phone_number_verified");
|
||||
|
||||
claims_supported.add("address");
|
||||
claims_supported.add("country");
|
||||
claims_supported.add("region");
|
||||
claims_supported.add("locality");
|
||||
claims_supported.add("street_address");
|
||||
claims_supported.add("formatted");
|
||||
claims_supported.add("postal_code");
|
||||
|
||||
oauthConfig.setClaims_supported(claims_supported);
|
||||
}
|
||||
return JsonPretty.getInstance().format(oauthConfig,true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed 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.maxkey.authz.oauth2.provider.wellknown.endpoint;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.maxkey.authz.oauth2.common.OAuth2Constants;
|
||||
import org.maxkey.authz.oauth2.provider.endpoint.AbstractEndpoint;
|
||||
import org.maxkey.authz.oauth2.provider.wellknown.OpenidConfiguration;
|
||||
import org.maxkey.entity.apps.oauth2.provider.ClientDetails;
|
||||
import org.maxkey.pretty.impl.JsonPretty;
|
||||
import org.maxkey.web.WebContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
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.alibaba.cloud.commons.lang.StringUtils;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
@Tag(name = "2-1-OAuth v2.0 API文档模块")
|
||||
@Controller
|
||||
public class OpenidConfigurationEndpoint extends AbstractEndpoint {
|
||||
final static Logger _logger = LoggerFactory.getLogger(OpenidConfigurationEndpoint.class);
|
||||
|
||||
|
||||
@Operation(summary = "OpenID Connect metadata 元数据接口", description = "参数client_id",method="GET,POST")
|
||||
@RequestMapping(
|
||||
value = {
|
||||
OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/.well-known/openid-configuration"},
|
||||
produces = "application/json",
|
||||
method={RequestMethod.POST, RequestMethod.GET})
|
||||
@ResponseBody
|
||||
public String configuration(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@RequestParam(value = "client_id", required = false) String client_id) {
|
||||
return configurationMetadata(request,response, null,client_id);
|
||||
}
|
||||
|
||||
@Operation(summary = "OpenID Connect metadata 元数据接口", description = "参数client_id",method="GET,POST")
|
||||
@RequestMapping(
|
||||
value = {
|
||||
OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/{instId}/.well-known/openid-configuration"},
|
||||
produces = "application/json",
|
||||
method={RequestMethod.POST, RequestMethod.GET})
|
||||
@ResponseBody
|
||||
public String configurationMetadata(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@PathVariable("instId") String instId,
|
||||
@RequestParam(value = "client_id", required = false) String client_id) {
|
||||
_logger.debug("instId {} , client_id {}" , instId ,client_id);
|
||||
|
||||
String baseUrl = WebContext.getContextPath(true);
|
||||
|
||||
ClientDetails clientDetails = null;
|
||||
|
||||
if(StringUtils.isNotBlank(client_id)) {
|
||||
try {
|
||||
clientDetails = getClientDetailsService().loadClientByClientId(client_id,true);
|
||||
}catch(Exception e) {
|
||||
_logger.error("getClientDetailsService", e);
|
||||
}
|
||||
}
|
||||
|
||||
OpenidConfiguration openidConfig = new OpenidConfiguration();
|
||||
openidConfig.setRequest_parameter_supported(true);
|
||||
openidConfig.setAuthorization_endpoint(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/authorize");
|
||||
openidConfig.setToken_endpoint(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/token");
|
||||
openidConfig.setIntrospection_endpoint(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/introspect");
|
||||
openidConfig.setUserinfo_endpoint(baseUrl + "/api/connect/v10/userinfo");
|
||||
openidConfig.setEnd_session_endpoint(baseUrl + "/force/logout");
|
||||
|
||||
if(clientDetails != null) {
|
||||
openidConfig.setClient_id(client_id);
|
||||
openidConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks?client_id=" + clientDetails.getClientId());
|
||||
|
||||
Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>();
|
||||
introspection_endpoint_auth_methods_supported.add("client_secret_basic");
|
||||
openidConfig.setIntrospection_endpoint_auth_methods_supported(introspection_endpoint_auth_methods_supported);
|
||||
|
||||
openidConfig.setIssuer(clientDetails.getIssuer());
|
||||
openidConfig.setResponse_types_supported(clientDetails.getAuthorizedGrantTypes());
|
||||
|
||||
Set<String> response_modes_supported = new HashSet<String>();
|
||||
response_modes_supported.add("query");
|
||||
response_modes_supported.add("form_post");
|
||||
openidConfig.setResponse_modes_supported(response_modes_supported);
|
||||
|
||||
openidConfig.setGrant_types_supported(clientDetails.getAuthorizedGrantTypes());
|
||||
openidConfig.setClaims_supported(clientDetails.getScope());
|
||||
|
||||
|
||||
Set<String> id_token_signing_alg_values_supported = new HashSet<String>();
|
||||
id_token_signing_alg_values_supported.add(clientDetails.getSignature().toUpperCase());
|
||||
openidConfig.setId_token_signing_alg_values_supported(id_token_signing_alg_values_supported);
|
||||
|
||||
openidConfig.setScopes_supported(clientDetails.getScope());
|
||||
|
||||
Set<String> token_endpoint_auth_methods_supported = new HashSet<String>();
|
||||
token_endpoint_auth_methods_supported.add("client_secret_basic");
|
||||
token_endpoint_auth_methods_supported.add("client_secret_post");
|
||||
token_endpoint_auth_methods_supported.add("none");
|
||||
openidConfig.setToken_endpoint_auth_methods_supported(token_endpoint_auth_methods_supported);
|
||||
|
||||
Set<String> claims_supported = new HashSet<String>();
|
||||
claims_supported.add("iss");
|
||||
claims_supported.add("sub");
|
||||
claims_supported.add("aud");
|
||||
claims_supported.add("iat");
|
||||
claims_supported.add("exp");
|
||||
claims_supported.add("jti");
|
||||
claims_supported.add("auth_time");
|
||||
|
||||
claims_supported.add("institution");
|
||||
claims_supported.add("online_ticket");
|
||||
|
||||
claims_supported.add("userId");
|
||||
claims_supported.add("user");
|
||||
claims_supported.add("name");
|
||||
claims_supported.add("preferred_username");
|
||||
claims_supported.add("given_name");
|
||||
claims_supported.add("family_name");
|
||||
claims_supported.add("middle_name");
|
||||
claims_supported.add("nickname");
|
||||
claims_supported.add("displayName");
|
||||
claims_supported.add("departmentId");
|
||||
claims_supported.add("department");
|
||||
claims_supported.add("gender");
|
||||
claims_supported.add("zoneinfo");
|
||||
claims_supported.add("locale");
|
||||
claims_supported.add("updated_time");
|
||||
claims_supported.add("birthdate");
|
||||
|
||||
claims_supported.add("email");
|
||||
claims_supported.add("email_verified");
|
||||
|
||||
claims_supported.add("phone_number");
|
||||
claims_supported.add("phone_number_verified");
|
||||
|
||||
claims_supported.add("address");
|
||||
claims_supported.add("country");
|
||||
claims_supported.add("region");
|
||||
claims_supported.add("locality");
|
||||
claims_supported.add("street_address");
|
||||
claims_supported.add("formatted");
|
||||
claims_supported.add("postal_code");
|
||||
|
||||
openidConfig.setClaims_supported(claims_supported);
|
||||
}else {
|
||||
openidConfig.setClient_id(client_id);
|
||||
openidConfig.setJwks_uri(baseUrl + OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/jwks");
|
||||
|
||||
Set<String> introspection_endpoint_auth_methods_supported = new HashSet<String>();
|
||||
introspection_endpoint_auth_methods_supported.add("client_secret_basic");
|
||||
openidConfig.setIntrospection_endpoint_auth_methods_supported(introspection_endpoint_auth_methods_supported);
|
||||
|
||||
openidConfig.setIssuer(baseUrl + "/maxkey");
|
||||
Set<String> response_types_supported = new HashSet<String>();
|
||||
response_types_supported.add("code");
|
||||
response_types_supported.add("code id_token");
|
||||
response_types_supported.add("id_token");
|
||||
openidConfig.setResponse_types_supported(response_types_supported);
|
||||
|
||||
Set<String> response_modes_supported = new HashSet<String>();
|
||||
response_modes_supported.add("query");
|
||||
response_modes_supported.add("form_post");
|
||||
openidConfig.setResponse_modes_supported(response_modes_supported);
|
||||
|
||||
Set<String> grant_types_supported = new HashSet<String>();
|
||||
grant_types_supported.add("authorization_code");
|
||||
grant_types_supported.add("refresh_token");
|
||||
grant_types_supported.add("password");
|
||||
grant_types_supported.add("client_credentials");
|
||||
openidConfig.setGrant_types_supported(grant_types_supported);
|
||||
|
||||
Set<String> id_token_signing_alg_values_supported = new HashSet<String>();
|
||||
id_token_signing_alg_values_supported.add("RS256");
|
||||
openidConfig.setId_token_signing_alg_values_supported(id_token_signing_alg_values_supported);
|
||||
|
||||
Set<String> scopes_supported = new HashSet<String>();
|
||||
scopes_supported.add("openid");
|
||||
scopes_supported.add("email");
|
||||
scopes_supported.add("profile");
|
||||
scopes_supported.add("address");
|
||||
scopes_supported.add("phone");
|
||||
openidConfig.setScopes_supported(scopes_supported);
|
||||
|
||||
Set<String> token_endpoint_auth_methods_supported = new HashSet<String>();
|
||||
token_endpoint_auth_methods_supported.add("client_secret_basic");
|
||||
token_endpoint_auth_methods_supported.add("client_secret_post");
|
||||
token_endpoint_auth_methods_supported.add("none");
|
||||
openidConfig.setToken_endpoint_auth_methods_supported(token_endpoint_auth_methods_supported);
|
||||
|
||||
Set<String> claims_supported = new HashSet<String>();
|
||||
claims_supported.add("iss");
|
||||
claims_supported.add("sub");
|
||||
claims_supported.add("aud");
|
||||
claims_supported.add("iat");
|
||||
claims_supported.add("exp");
|
||||
claims_supported.add("jti");
|
||||
claims_supported.add("auth_time");
|
||||
|
||||
claims_supported.add("institution");
|
||||
claims_supported.add("online_ticket");
|
||||
|
||||
claims_supported.add("userId");
|
||||
claims_supported.add("user");
|
||||
claims_supported.add("name");
|
||||
claims_supported.add("preferred_username");
|
||||
claims_supported.add("given_name");
|
||||
claims_supported.add("family_name");
|
||||
claims_supported.add("middle_name");
|
||||
claims_supported.add("nickname");
|
||||
claims_supported.add("displayName");
|
||||
claims_supported.add("departmentId");
|
||||
claims_supported.add("department");
|
||||
claims_supported.add("gender");
|
||||
claims_supported.add("zoneinfo");
|
||||
claims_supported.add("locale");
|
||||
claims_supported.add("updated_time");
|
||||
claims_supported.add("birthdate");
|
||||
|
||||
claims_supported.add("email");
|
||||
claims_supported.add("email_verified");
|
||||
|
||||
claims_supported.add("phone_number");
|
||||
claims_supported.add("phone_number_verified");
|
||||
|
||||
claims_supported.add("address");
|
||||
claims_supported.add("country");
|
||||
claims_supported.add("region");
|
||||
claims_supported.add("locality");
|
||||
claims_supported.add("street_address");
|
||||
claims_supported.add("formatted");
|
||||
claims_supported.add("postal_code");
|
||||
|
||||
openidConfig.setClaims_supported(claims_supported);
|
||||
}
|
||||
|
||||
return JsonPretty.getInstance().format(openidConfig,true);
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,8 @@ public class OIDCIdTokenEnhancer implements TokenEnhancer {
|
||||
builder.claim("auth_time", loginDate.getMillis()/1000);
|
||||
}
|
||||
|
||||
String nonce = (String)request.getExtensions().get("nonce");
|
||||
String nonce = request.getRequestParameters().get("nonce");
|
||||
_logger.debug("getRequestParameters nonce {}",nonce);
|
||||
if (!Strings.isNullOrEmpty(nonce)) {
|
||||
builder.claim("nonce", nonce);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,8 @@ import com.nimbusds.jose.JWEAlgorithm;
|
||||
@ComponentScan(basePackages = {
|
||||
"org.maxkey.authz.oauth2.provider.endpoint",
|
||||
"org.maxkey.authz.oauth2.provider.userinfo.endpoint",
|
||||
"org.maxkey.authz.oauth2.provider.approval.controller"
|
||||
"org.maxkey.authz.oauth2.provider.approval.controller",
|
||||
"org.maxkey.authz.oauth2.provider.wellknown.endpoint"
|
||||
})
|
||||
public class Oauth20AutoConfiguration implements InitializingBean {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(Oauth20AutoConfiguration.class);
|
||||
|
||||
Reference in New Issue
Block a user