Search in sources :

Example 1 with HonoUser

use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.

the class AmqpServiceBase method setRemoteConnectionOpenHandler.

private void setRemoteConnectionOpenHandler(final ProtonConnection connection) {
    connection.sessionOpenHandler(remoteOpenSession -> handleSessionOpen(connection, remoteOpenSession));
    connection.receiverOpenHandler(remoteOpenReceiver -> handleReceiverOpen(connection, remoteOpenReceiver));
    connection.senderOpenHandler(remoteOpenSender -> handleSenderOpen(connection, remoteOpenSender));
    connection.disconnectHandler(this::handleRemoteDisconnect);
    connection.closeHandler(remoteClose -> handleRemoteConnectionClose(connection, remoteClose));
    connection.openHandler(remoteOpen -> {
        final HonoUser clientPrincipal = Constants.getClientPrincipal(connection);
        LOG.debug("client [container: {}, user: {}] connected", connection.getRemoteContainer(), clientPrincipal.getName());
        // attach an ID so that we can later inform downstream components when connection is closed
        connection.attachments().set(Constants.KEY_CONNECTION_ID, String.class, UUID.randomUUID().toString());
        final Duration delay = Duration.between(Instant.now(), clientPrincipal.getExpirationTime());
        final WeakReference<ProtonConnection> conRef = new WeakReference<>(connection);
        vertx.setTimer(delay.toMillis(), timerId -> {
            if (conRef.get() != null) {
                closeExpiredConnection(conRef.get());
            }
        });
        connection.open();
    });
}
Also used : ProtonConnection(io.vertx.proton.ProtonConnection) HonoUser(org.eclipse.hono.auth.HonoUser) WeakReference(java.lang.ref.WeakReference) Duration(java.time.Duration)

Example 2 with HonoUser

use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.

the class AuthenticationEndpoint method onLinkAttach.

@Override
public final void onLinkAttach(final ProtonConnection con, final ProtonSender sender, final ResourceIdentifier targetResource) {
    if (ProtonQoS.AT_LEAST_ONCE.equals(sender.getRemoteQoS())) {
        HonoUser user = Constants.getClientPrincipal(con);
        sender.setQoS(ProtonQoS.AT_LEAST_ONCE).open();
        logger.debug("transferring token to client...");
        Message tokenMsg = ProtonHelper.message(user.getToken());
        MessageHelper.addProperty(tokenMsg, AuthenticationConstants.APPLICATION_PROPERTY_TYPE, AuthenticationConstants.TYPE_AMQP_JWT);
        sender.send(tokenMsg, disposition -> {
            if (disposition.remotelySettled()) {
                logger.debug("successfully transferred auth token to client");
            } else {
                logger.debug("failed to transfer auth token to client");
            }
            sender.close();
        });
    } else {
        onLinkDetach(sender, ProtonHelper.condition(AmqpError.INVALID_FIELD, "supports AT_LEAST_ONCE delivery mode only"));
    }
}
Also used : HonoUser(org.eclipse.hono.auth.HonoUser) Message(org.apache.qpid.proton.message.Message)

Example 3 with HonoUser

use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.

the class FileBasedAuthenticationService method verify.

private void verify(final String authenticationId, final JsonObject user, final String authorizationId, final Handler<AsyncResult<HonoUser>> authenticationResultHandler) {
    JsonObject effectiveUser = user;
    String effectiveAuthorizationId = authenticationId;
    if (authorizationId != null && !authorizationId.isEmpty() && isAuthorizedToImpersonate(user)) {
        JsonObject impersonatedUser = users.get(authorizationId);
        if (impersonatedUser != null) {
            effectiveUser = impersonatedUser;
            effectiveAuthorizationId = authorizationId;
            log.debug("granting authorization id specified by client");
        } else {
            log.debug("no user found for authorization id provided by client, granting authentication id instead");
        }
    }
    final Authorities grantedAuthorities = getAuthorities(effectiveUser);
    final String grantedAuthorizationId = effectiveAuthorizationId;
    final Instant tokenExpirationTime = Instant.now().plus(tokenFactory.getTokenLifetime());
    final String token = tokenFactory.createToken(grantedAuthorizationId, grantedAuthorities);
    HonoUser honoUser = new HonoUser() {

        @Override
        public String getName() {
            return grantedAuthorizationId;
        }

        @Override
        public String getToken() {
            return token;
        }

        @Override
        public Authorities getAuthorities() {
            return grantedAuthorities;
        }

        @Override
        public boolean isExpired() {
            return !Instant.now().isBefore(tokenExpirationTime);
        }

        @Override
        public Instant getExpirationTime() {
            return tokenExpirationTime;
        }
    };
    authenticationResultHandler.handle(Future.succeededFuture(honoUser));
}
Also used : HonoUser(org.eclipse.hono.auth.HonoUser) Instant(java.time.Instant) JsonObject(io.vertx.core.json.JsonObject) Authorities(org.eclipse.hono.auth.Authorities)

Example 4 with HonoUser

use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.

the class SimpleAuthenticationServer method handleSenderOpen.

/**
 * Handles a request from a client to establish a link for receiving messages from this server.
 *
 * @param con the connection to the client.
 * @param sender the sender created for the link.
 */
@Override
protected void handleSenderOpen(final ProtonConnection con, final ProtonSender sender) {
    final Source remoteSource = sender.getRemoteSource();
    LOG.debug("client [{}] wants to open a link for receiving messages [address: {}]", con.getRemoteContainer(), remoteSource);
    try {
        final ResourceIdentifier targetResource = getResourceIdentifier(remoteSource.getAddress());
        final AmqpEndpoint endpoint = getEndpoint(targetResource);
        if (endpoint == null) {
            LOG.debug("no endpoint registered for node [{}]", targetResource);
            con.setCondition(ProtonHelper.condition(AmqpError.NOT_FOUND, "no such node")).close();
        } else {
            HonoUser user = Constants.getClientPrincipal(con);
            if (Constants.SUBJECT_ANONYMOUS.equals(user.getName())) {
                con.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS, "client must authenticate using SASL")).close();
            } else {
                Constants.copyProperties(con, sender);
                sender.setSource(sender.getRemoteSource());
                endpoint.onLinkAttach(con, sender, targetResource);
                vertx.setTimer(5000, closeCon -> {
                    if (!con.isDisconnected()) {
                        LOG.debug("connection with client [{}] timed out after 5 seconds, closing connection", con.getRemoteContainer());
                        con.setCondition(ProtonHelper.condition("hono: inactivity", "client must retrieve token within 5 secs after opening connection")).close();
                    }
                });
            }
        }
    } catch (final IllegalArgumentException e) {
        LOG.debug("client has provided invalid resource identifier as source address", e);
        con.setCondition(ProtonHelper.condition(AmqpError.INVALID_FIELD, "malformed source address")).close();
    }
}
Also used : ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) HonoUser(org.eclipse.hono.auth.HonoUser) AmqpEndpoint(org.eclipse.hono.service.amqp.AmqpEndpoint) Source(org.apache.qpid.proton.amqp.transport.Source)

Example 5 with HonoUser

use of org.eclipse.hono.auth.HonoUser in project hono by eclipse.

the class AmqpServiceBase method closeExpiredConnection.

/**
 * Closes an expired client connection.
 * <p>
 * A connection is considered expired if the {@link HonoUser#isExpired()} method
 * of the user principal attached to the connection returns {@code true}.
 *
 * @param con The client connection.
 */
protected final void closeExpiredConnection(final ProtonConnection con) {
    if (!con.isDisconnected()) {
        final HonoUser clientPrincipal = Constants.getClientPrincipal(con);
        if (clientPrincipal != null) {
            LOG.debug("client's [{}] access token has expired, closing connection", clientPrincipal.getName());
            con.disconnectHandler(null);
            con.closeHandler(null);
            con.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS, "access token expired"));
            con.close();
            con.disconnect();
            publishConnectionClosedEvent(con);
        }
    }
}
Also used : HonoUser(org.eclipse.hono.auth.HonoUser)

Aggregations

HonoUser (org.eclipse.hono.auth.HonoUser)11 ProtonConnection (io.vertx.proton.ProtonConnection)4 ResourceIdentifier (org.eclipse.hono.util.ResourceIdentifier)4 Future (io.vertx.core.Future)2 Vertx (io.vertx.core.Vertx)2 JsonObject (io.vertx.core.json.JsonObject)2 ProtonClientOptions (io.vertx.proton.ProtonClientOptions)2 ProtonReceiver (io.vertx.proton.ProtonReceiver)2 Objects (java.util.Objects)2 Source (org.apache.qpid.proton.amqp.transport.Source)2 Message (org.apache.qpid.proton.message.Message)2 MessageHelper (org.eclipse.hono.util.MessageHelper)2 Autowired (org.springframework.beans.factory.annotation.Autowired)2 AsyncResult (io.vertx.core.AsyncResult)1 Handler (io.vertx.core.Handler)1 MessageConsumer (io.vertx.core.eventbus.MessageConsumer)1 DecodeException (io.vertx.core.json.DecodeException)1 ProtonDelivery (io.vertx.proton.ProtonDelivery)1 ProtonHelper (io.vertx.proton.ProtonHelper)1 ProtonMessageHandler (io.vertx.proton.ProtonMessageHandler)1