org.eclipse.hono.adapter.http.HonoBasicAuthHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.hono.adapter.http.HonoBasicAuthHandler.java

Source

/*
 * Copyright 2014 Red Hat, Inc. and others.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Apache License v2.0 which accompanies this distribution.
 *
 *  The Eclipse Public License is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  The Apache License v2.0 is available at
 *  http://www.opensource.org/licenses/apache2.0.php
 *
 *  You may elect to redistribute this code under either of these licenses.
 */

package org.eclipse.hono.adapter.http;

import java.util.Base64;

import org.eclipse.hono.service.auth.device.HonoAuthHandler;

import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.AuthProvider;
import io.vertx.ext.web.RoutingContext;

/**
 * A Hono specific version of vert.x web's standard {@code BasicAuthHandlerImpl}
 * that does not swallow the root exception which caused an authentication failure.
 * <p>
 * This class is a combination of
 * {@code io.vertx.ext.web.handler.impl.BasicAuthHandlerImpl} and
 * {@code io.vertx.ext.web.handler.impl.AuthorizationAuthHandler}.
 *
 */
public class HonoBasicAuthHandler extends HonoAuthHandler {

    /**
     * Creates a new handler for an authentication provider and a security realm.
     * 
     * @param authProvider The provider to use for verifying credentials.
     * @param realm The security realm.
     */
    public HonoBasicAuthHandler(final AuthProvider authProvider, final String realm) {
        super(authProvider, realm);
    }

    @Override
    public void parseCredentials(final RoutingContext context, final Handler<AsyncResult<JsonObject>> handler) {

        parseAuthorization(context, false, parseAuthorization -> {
            if (parseAuthorization.failed()) {
                handler.handle(Future.failedFuture(parseAuthorization.cause()));
                return;
            }

            final String suser;
            final String spass;

            try {
                // decode the payload
                final String decoded = new String(Base64.getDecoder().decode(parseAuthorization.result()));

                final int colonIdx = decoded.indexOf(":");
                if (colonIdx != -1) {
                    suser = decoded.substring(0, colonIdx);
                    spass = decoded.substring(colonIdx + 1);
                } else {
                    suser = decoded;
                    spass = null;
                }
            } catch (RuntimeException e) {
                // IllegalArgumentException includes PatternSyntaxException
                context.fail(e);
                return;
            }

            handler.handle(Future.succeededFuture(new JsonObject().put("username", suser).put("password", spass)));
        });
    }

    @Override
    protected String authenticateHeader(final RoutingContext context) {
        return "Basic realm=\"" + realm + "\"";
    }

    /**
     * Extracts authentication information from the <em>Authorization</em>
     * header of an HTTP request.
     * 
     * @param ctx The routing context that contains the HTTP request.
     * @param optional Indicates whether the authorization header is mandatory.
     * @param handler The handler to invoke with the authentication info.
     */
    protected final void parseAuthorization(final RoutingContext ctx, final boolean optional,
            final Handler<AsyncResult<String>> handler) {

        final HttpServerRequest request = ctx.request();
        final String authorization = request.headers().get(HttpHeaders.AUTHORIZATION);

        if (authorization == null) {
            if (optional) {
                // this is allowed
                handler.handle(Future.succeededFuture());
            } else {
                handler.handle(Future.failedFuture(UNAUTHORIZED));
            }
            return;
        }

        try {
            final int idx = authorization.indexOf(' ');

            if (idx <= 0) {
                handler.handle(Future.failedFuture(BAD_REQUEST));
                return;
            }

            if (!"Basic".equalsIgnoreCase(authorization.substring(0, idx))) {
                handler.handle(Future.failedFuture(UNAUTHORIZED));
                return;
            }

            handler.handle(Future.succeededFuture(authorization.substring(idx + 1)));
        } catch (RuntimeException e) {
            handler.handle(Future.failedFuture(e));
        }
    }
}