是否可以验证从WSO2中的外部OAuth2服务器创建的JWT令牌? [英] Is it possible to validate a JWT token created from an external OAuth2 Server in WSO2?

查看:86
本文介绍了是否可以验证从WSO2中的外部OAuth2服务器创建的JWT令牌?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Spring Security OAuth2服务器,它为前端应用程序生成JWT令牌.

I have a Spring Security OAuth2 server that generates JWT tokens for frontend applications.

此令牌将在调用中通过API网关(WSO2 API管理器)发送到后端.

This tokens will be sent in the calls to the backends, passing through an API Gateway (WSO2 API Manager).

我想要在WSO2中注册后端API,并能够验证外部生成的JWT令牌.

What I would like is to have the backend APIs registered in WSO2 and be able to validate that externally generated JWT token.

这可能吗?您能否提供需要配置以包含此逻辑的WSO2 APIM不同位置的示例?

Is this possible? Can you provide a sample of the different places of the WSO2 APIM that would need to be configured to include this logic?

注意:WSO2永远不需要创建令牌,它始终是以前创建的,只需要验证它即可.

NOTICE: The WSO2 will never need to create the token, it'll always have been created previously, it only needs to validate it.

推荐答案

经过大量的试验和错误,以及Stackoverflow的一些帮助(对Bee表示敬意),这是我的可行解决方案.我希望它能对其他人有所帮助,因为使其工作起来确实很棘手:

After a lot of trial and error and some help from Stackoverflow (kudos to Bee) this is my working solution. I hope it helps others since it was really tricky to make it work:

1.实现JWTAuthHandler以验证JWT令牌:

public class JwtAuthHandler extends AbstractHandler {

    private final PublicKeyFactory pkf = new PublicKeyFactory();
    private final JwtVerifier jwtVerifier = new JwtVerifier();

    @Override
    public boolean handleRequest(MessageContext messageContext) {

        try {
            final String jwtToken = getJwtTokenFromHeaders(messageContext).replace("Bearer ", "");

            SignedJWT signedJwt = SignedJWT.parse(jwtToken);
            final JSONObject payload = signedJwt.getPayload().toJSONObject();
            final JSONObject environment = (JSONObject)payload.get("environment");

            PublicKey publicKey = readPublicKey();

            JWSVerifier verifier = new RSASSAVerifier(((RSAPublicKey) publicKey));
            final boolean signatureVerification = signedJwt.verify(verifier)

            if (signatureVerification) {
                AuthenticationContext authContext = new AuthenticationContext();
                authContext.setAuthenticated(true);
                if (isProductionRequest(environment)) {
                    authContext.setKeyType(APIConstants.API_KEY_TYPE_PRODUCTION);
                } else {
                    authContext.setKeyType(APIConstants.API_KEY_TYPE_SANDBOX);
                }
                APISecurityUtils.setAuthenticationContext(messageContext, authContext, "Authorization");
            } else {
                LOG.debug("handleRequest() - Sending 401 Unauthorized");
                Utils.sendFault(messageContext, 401);
            }
            return signatureVerification;
        } catch (Exception e) {
            e.printStackTrace();
            Utils.sendFault(messageContext, 500);
            return false;
        }
    }

    @Override
    public boolean handleResponse(MessageContext messageContext) {
        return true;
    }

    private String getJwtTokenFromHeaders(MessageContext messageContext) {
        Map headers = (Map) ((Axis2MessageContext) messageContext).getAxis2MessageContext().
                getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
        return (String) headers.get("Authorization");
    }

    private boolean isProductionRequest(JSONObject environment) {
        return environment != null && environment.equals("pro");
    }

}

2.覆盖您的API定义(/repository/deployment/server/synapse-configs/default/api/yourapi.xml)以使用jwt处理程序并删除APIAuthenticationHandler和ThrottleHandler(由于非oauth2身份验证的api的一个众所周知的错误,因此需要删除ThrottleHandler):

2. Override your API definition (/repository/deployment/server/synapse-configs/default/api/yourapi.xml) to use the jwt handler and remove the APIAuthenticationHandler and the ThrottleHandler (the latter needs to be removed because of a well known bug for non-oauth2-authenticated apis):

它应该是这样的:

<handlers>
  <handler class="com.codependent.JwtAuthHandler"/>
  <handler class="org.wso2.carbon.apimgt.gateway.handlers.common.APIMgtLatencyStatsHandler"/>
  <handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler">
     <property name="apiImplementationType" value="ENDPOINT"/>
  </handler>
  <handler class="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtUsageHandler"/>
  <handler class="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtGoogleAnalyticsTrackingHandler">
     <property name="configKey" value="gov:/apimgt/statistics/ga-config.xml"/>
  </handler>
  <handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/>


</handlers>

重要提示:

  1. 处理后端通常是从OAuth2访问令牌派生的(在正常的OAuth2请求中).由于在这里我们替换了它,WSO2无法确定要调用哪个环境,因此它将默认调用PRODUCTION.要解决此问题,在我的案例环境中,请在您的JWT中插入一些额外的字段,以帮助您做出决定.然后,如图所示,在适当的环境中创建AuthenticationContext.就是这样!

如果直接编辑yourapi.xml描述符,则下次发布时它将被替换.要自动生成,请编辑速度模板(/repository/resources/api_templates/velocity_template.xml).就我而言,我只希望它适用于某些应用程序,因此我使用标签(jwt-auth)来选择它们.

If you directly edit yourapi.xml descriptor it'll be replaced the next time you publish it. To automate its generation edit the velocity template (/repository/resources/api_templates/velocity_template.xml). In my case I only want it to apply to some applications, so I use a tag (jwt-auth) to select them.

velocity_template.xml:

<handlers xmlns="http://ws.apache.org/ns/synapse">
#if($apiObj.tags.contains("jwt-auth"))
    <handler class="com.codependent.JwtAuthHandler"/>
#end
#foreach($handler in $handlers)
    #if((($handler.className != "org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler") && 
         ($handler.className != "org.wso2.carbon.apimgt.gateway.handlers.throttling.ThrottleHandler")) || 
            !($apiObj.tags.contains("jwt-auth")))
    <handler xmlns="http://ws.apache.org/ns/synapse" class="$handler.className">
        #if($handler.hasProperties())
            #set ($map = $handler.getProperties() )
            #foreach($property in $map.entrySet())
        <property name="$!property.key" value="$!property.value"/>
            #end
        #end
    </handler>
    #end
#end
</handlers>

这篇关于是否可以验证从WSO2中的外部OAuth2服务器创建的JWT令牌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆