Search in sources :

Example 1 with RSocketAppPrincipal

use of org.kin.rsocket.auth.RSocketAppPrincipal in project kin-rsocket-broker by huangjianqin.

the class RSocketServiceManager method acceptor.

/**
 * service rsocket endpoint acceptor逻辑
 */
@SuppressWarnings("ConstantConditions")
@Nonnull
private Mono<RSocket> acceptor(ConnectionSetupPayload setupPayload, RSocket requester) {
    // parse setup payload
    RSocketCompositeMetadata compositeMetadata = null;
    AppMetadata appMetadata = null;
    String credentials = "";
    RSocketAppPrincipal principal = null;
    String errorMsg = null;
    try {
        compositeMetadata = RSocketCompositeMetadata.of(setupPayload.metadata());
        if (!authRequired) {
            // authentication not required
            principal = RSocketAppPrincipal.DEFAULT;
            credentials = UUID.randomUUID().toString();
        } else if (compositeMetadata.contains(RSocketMimeType.BEARER_TOKEN)) {
            BearerTokenMetadata bearerTokenMetadata = compositeMetadata.getMetadata(RSocketMimeType.BEARER_TOKEN);
            credentials = new String(bearerTokenMetadata.getBearerToken());
            principal = authenticationService.auth(credentials);
        } else {
            // no jwt token supplied
            errorMsg = "Failed to accept the connection, please check app info and JWT token";
        }
        // validate application information
        if (principal != null && compositeMetadata.contains(RSocketMimeType.APPLICATION)) {
            AppMetadata temp = compositeMetadata.getMetadata(RSocketMimeType.APPLICATION);
            // App registration validation: app id: UUID and unique in server
            String appId = temp.getUuid();
            // validate appId data format
            if (StringUtils.isNotBlank(appId) && appId.length() >= 32) {
                int instanceId = MurmurHash3.hash32(credentials + ":" + temp.getUuid());
                temp.updateInstanceId(instanceId);
                // application instance not connected
                if (!containsInstanceId(instanceId)) {
                    appMetadata = temp;
                    appMetadata.updateConnectedAt(new Date());
                } else {
                    // application connected already
                    errorMsg = "Connection created already, Please don't create multiple connections.";
                }
            } else {
                // 没有uuid是否要拒绝连接
                // illegal application id, appID should be UUID
                errorMsg = String.format("'%s' is not legal application ID, please supply legal UUID as Application ID", appId == null ? "" : appId);
            }
        } else {
            errorMsg = "Can not found application metadata";
        }
        if (errorMsg == null) {
            // Security authentication
            if (appMetadata != null) {
                appMetadata.addMetadata("_orgs", String.join(",", principal.getOrganizations()));
                appMetadata.addMetadata("_roles", String.join(",", principal.getRoles()));
                appMetadata.addMetadata("_serviceAccounts", String.join(",", principal.getServiceAccounts()));
            } else {
                errorMsg = "Please supply message/x.rsocket.application+json metadata in setup payload";
            }
        }
    } catch (Exception e) {
        log.error("Error to parse setup payload", e);
        errorMsg = String.format("Failed to parse composite metadata: %s", e.getMessage());
    }
    // validate connection legal or not
    if (principal == null) {
        errorMsg = "Failed to accept the connection, please check app info and JWT token";
    }
    if (errorMsg != null) {
        return returnRejectedRSocket(errorMsg, requester);
    }
    // create rsocket endpoint
    try {
        RSocketBrokerResponderHandler responderHandler = new RSocketBrokerResponderHandler(setupPayload, appMetadata, principal, this, serviceMeshInspector, upstreamBrokers, rsocketFilterChain);
        RSocketEndpoint rsocketEndpoint = new RSocketEndpoint(compositeMetadata, appMetadata, requester, this, responderHandler);
        rsocketEndpoint.onClose().doOnTerminate(() -> onRSocketEndpointDisposed(rsocketEndpoint)).subscribeOn(Schedulers.parallel()).subscribe();
        // handler registration notify
        registerRSocketEndpoint(rsocketEndpoint);
        // connect success, so publish service now
        rsocketEndpoint.publishServices();
        log.info(String.format("succeed to accept connection from application '%s'", appMetadata.getName()));
        return Mono.just(responderHandler);
    } catch (Exception e) {
        String formattedErrorMsg = String.format("failed to accept the connection: %s", e.getMessage());
        log.error(formattedErrorMsg, e);
        return returnRejectedRSocket(formattedErrorMsg, requester);
    }
}
Also used : RSocketCompositeMetadata(org.kin.rsocket.core.metadata.RSocketCompositeMetadata) BearerTokenMetadata(org.kin.rsocket.core.metadata.BearerTokenMetadata) AppMetadata(org.kin.rsocket.core.metadata.AppMetadata) RSocketAppPrincipal(org.kin.rsocket.auth.RSocketAppPrincipal) RejectedSetupException(io.rsocket.exceptions.RejectedSetupException) ApplicationErrorException(io.rsocket.exceptions.ApplicationErrorException) Nonnull(javax.annotation.Nonnull)

Example 2 with RSocketAppPrincipal

use of org.kin.rsocket.auth.RSocketAppPrincipal in project kin-rsocket-broker by huangjianqin.

the class RSocketApiController method handle.

@RequestMapping(value = "/{service}/{method}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Mono<ResponseEntity<String>> handle(@PathVariable("service") String service, @PathVariable("method") String method, @RequestParam(name = "group", required = false, defaultValue = "") String group, @RequestParam(name = "version", required = false, defaultValue = "") String version, @RequestBody(required = false) byte[] body, @RequestHeader(name = "X-Endpoint", required = false, defaultValue = "") String endpoint, @RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false, defaultValue = "") String token) {
    try {
        GSVRoutingMetadata routingMetadata = GSVRoutingMetadata.of(group, service, method, version);
        int serviceId = routingMetadata.serviceId();
        ByteBuf bodyBuf = body == null ? EMPTY_BUFFER : Unpooled.wrappedBuffer(body);
        RSocketEndpoint rsocketEndpoint;
        if (endpoint.startsWith("id:")) {
            // 存在endpoint
            int instanceId = Integer.parseInt(endpoint.substring(3).trim());
            rsocketEndpoint = serviceManager.getByInstanceId(instanceId);
        } else {
            rsocketEndpoint = serviceManager.routeByServiceId(serviceId);
        }
        if (Objects.nonNull(rsocketEndpoint)) {
            if (rsocketBrokerProperties.isAuth()) {
                RSocketAppPrincipal principal = authenticationService.auth(token);
                if (principal == null || !serviceMeshInspector.isAllowed(principal, serviceId, rsocketEndpoint.getPrincipal())) {
                    return Mono.just(error(String.format("Service request not allowed '%s'", routingMetadata.gsv())));
                }
            }
            RSocketCompositeMetadata compositeMetadata = RSocketCompositeMetadata.of(routingMetadata, JSON_ENCODING_METADATA);
            return rsocketEndpoint.requestResponse(DefaultPayload.create(bodyBuf, compositeMetadata.getContent())).map(payload -> {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                headers.setCacheControl(CacheControl.noCache().getHeaderValue());
                return new ResponseEntity<>(payload.getDataUtf8(), headers, HttpStatus.OK);
            });
        }
        return Mono.just(error(String.format("service not found, '%s'", routingMetadata.gsv())));
    } catch (Exception e) {
        return Mono.just(error(e.getMessage()));
    }
}
Also used : RSocketCompositeMetadata(org.kin.rsocket.core.metadata.RSocketCompositeMetadata) GSVRoutingMetadata(org.kin.rsocket.core.metadata.GSVRoutingMetadata) ByteBuf(io.netty.buffer.ByteBuf) RSocketEndpoint(org.kin.rsocket.broker.RSocketEndpoint) RSocketAppPrincipal(org.kin.rsocket.auth.RSocketAppPrincipal) RSocketEndpoint(org.kin.rsocket.broker.RSocketEndpoint)

Example 3 with RSocketAppPrincipal

use of org.kin.rsocket.auth.RSocketAppPrincipal in project kin-rsocket-broker by huangjianqin.

the class JwtAuthenticationService method auth.

@Override
public RSocketAppPrincipal auth(String credentials) {
    if (Objects.isNull(credentials) || credentials.isEmpty()) {
        return null;
    }
    // bearer jwt_token
    credentials = credentials.substring(credentials.lastIndexOf(" ") + 1);
    int tokenHashCode = credentials.hashCode();
    RSocketAppPrincipal principal = jwtVerifyCache.getIfPresent(tokenHashCode);
    for (JWTVerifier verifier : verifiers) {
        try {
            principal = new JwtPrincipal(verifier.verify(credentials));
            jwtVerifyCache.put(tokenHashCode, principal);
            break;
        } catch (JWTVerificationException ignore) {
        // do nothing
        }
    }
    return principal;
}
Also used : JWTVerificationException(com.auth0.jwt.exceptions.JWTVerificationException) RSocketAppPrincipal(org.kin.rsocket.auth.RSocketAppPrincipal) JWTVerifier(com.auth0.jwt.interfaces.JWTVerifier)

Aggregations

RSocketAppPrincipal (org.kin.rsocket.auth.RSocketAppPrincipal)3 RSocketCompositeMetadata (org.kin.rsocket.core.metadata.RSocketCompositeMetadata)2 JWTVerificationException (com.auth0.jwt.exceptions.JWTVerificationException)1 JWTVerifier (com.auth0.jwt.interfaces.JWTVerifier)1 ByteBuf (io.netty.buffer.ByteBuf)1 ApplicationErrorException (io.rsocket.exceptions.ApplicationErrorException)1 RejectedSetupException (io.rsocket.exceptions.RejectedSetupException)1 Nonnull (javax.annotation.Nonnull)1 RSocketEndpoint (org.kin.rsocket.broker.RSocketEndpoint)1 AppMetadata (org.kin.rsocket.core.metadata.AppMetadata)1 BearerTokenMetadata (org.kin.rsocket.core.metadata.BearerTokenMetadata)1 GSVRoutingMetadata (org.kin.rsocket.core.metadata.GSVRoutingMetadata)1