Package lib.security

Source Code of lib.security.RedirectAuthenticator

/*
* Copyright 2013 TORCH UG
*
* This file is part of Graylog2.
*
* Graylog2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Graylog2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Graylog2.  If not, see <http://www.gnu.org/licenses/>.
*/
package lib.security;

import com.ning.http.util.Base64;
import controllers.routes;
import org.graylog2.restclient.lib.APIException;
import org.graylog2.restclient.lib.Graylog2ServerUnavailableException;
import org.graylog2.restclient.models.SessionService;
import org.graylog2.restclient.models.User;
import org.graylog2.restclient.models.UserService;
import org.graylog2.restclient.models.api.responses.SessionCreateResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.libs.Crypto;
import play.mvc.Http;
import play.mvc.Http.Context;
import play.mvc.Result;
import play.mvc.Security.Authenticator;

import javax.inject.Inject;
import java.io.IOException;
import java.util.StringTokenizer;

public class RedirectAuthenticator extends Authenticator {
    private static final Logger log = LoggerFactory.getLogger(RedirectAuthenticator.class);
    public static final String GRAYLOG_2_SERVER_MISSING_KEY = "GRAYLOG2SERVERMISSING";

    // TODO crutch, we need to write out own AuthenticatedAction filter... :(
    @Inject
    public static UserService userService;
    @Inject
    public static SessionService sessionService;

    @Override
    public String getUsername(Context ctx) {
        try {
            final User sessionUser = pipelineAuths(authenticateSessionUser(), authenticateBasicAuthUser());
            if (sessionUser == null) {
                return null;
            }
            return sessionUser.getName();
        } catch (Graylog2ServerUnavailableException e) {
            ctx.args.put(GRAYLOG_2_SERVER_MISSING_KEY, e);
            return null;
        }
    }

    @Override
  public Result onUnauthorized(Context ctx) {
        if (ctx.args.containsKey(GRAYLOG_2_SERVER_MISSING_KEY)) {
            // the client is not "unauthorized" per se, but we couldn't reach any backend to authenticate against.
            // if this is a XMLHttpRequest, we respond with a 504 Gateway Timeout, to trigger the error handlers in Javascript
            final String xhr = ctx.request().getHeader("X-Requested-With");
            if ("xmlhttprequest".equalsIgnoreCase(xhr)) {
                return status(Http.Status.GATEWAY_TIMEOUT);
            }

            // otherwise we couldn't reach any backend, and need to tell the user so.
            // we redirect to a special controller, which won't try to load user.
            ctx.session().put("disconnected_orig_uri", ctx.request().uri());
            return redirect(routes.LonesomeInterfaceController.index());
        } else {
            // XMLHttpRequests should still get a 401 if the backend server couldn't authenticate, because the session
            // has most likely expired.
            // As such, the XHR code in the web interface should then redirect to /
            final String xhr = ctx.request().getHeader("X-Requested-With");
            if (xhr != null && xhr.equalsIgnoreCase("xmlhttprequest")) {
                return status(Http.Status.UNAUTHORIZED);
            }

        }
        final String destination = ctx.request().uri();
        // don't redirect to /logout directly after login ;)
        if (routes.SessionsController.destroy().url().equals(destination)) {
            return redirect(controllers.routes.SessionsController.index(""));
        }
        return redirect(controllers.routes.SessionsController.index(destination));
  }

    public User authenticateSessionUser() {
        // is there a logged in user at all?
        final Http.Session session = Http.Context.current().session();
        final String encryptedSessionId = session.get("sessionid");
        if (encryptedSessionId == null) {
            // there is no authenticated user yet.
            log.info("Accessing the current user failed, there's no sessionid in the cookie.");
            return null;
        }
        final String userAndSessionId = Crypto.decryptAES(encryptedSessionId);
        final StringTokenizer tokenizer = new StringTokenizer(userAndSessionId, "\t");
        if (tokenizer.countTokens() != 2) {
            return null;
        }
        final String userName = tokenizer.nextToken();
        final String sessionId = tokenizer.nextToken();
        Http.Context.current().args.put("sessionId", sessionId);
        // special case for the local admin user for the web interface
//        if (userName != null) {
//            final LocalAdminUser localAdminUser = LocalAdminUser.getInstance();
//            if (userName.equals(localAdminUser.getName())) {
//                setCurrent(localAdminUser);
//                return localAdminUser;
//            }
//        }
        return userService.retrieveUserWithSessionId(userName, sessionId);
    }

    protected User authenticateBasicAuthUser() {
        final Http.Request request = Http.Context.current().request();
        final String authorizationHeader = request.getHeader("authorization");

        if (authorizationHeader == null)
            return null;

        final String[] tokens = authorizationHeader.split(" ");
        final String authToken;
        if (tokens.length >= 2)
            authToken = tokens[1];
        else
            return null;

        if (authToken == null)
            return null;

        final byte[] decodedAuth;
        final String[] credString;
        try {
            decodedAuth = Base64.decode(authToken);
            credString = new String(decodedAuth, "UTF-8").split(":", 2);
        } catch (IOException e) {
            log.error("Unable to decode basic auth information: ", e);
            return null;
        }

        if (credString == null || credString.length != 2)
            return null;

        final String userName = credString[0];
        final String password = credString[1];

        try {
            SessionCreateResponse session = sessionService.create(userName, password, request.remoteAddress());
            return userService.retrieveUserWithSessionId(userName, session.sessionId);
        } catch (IOException e) {
            log.error("Could not reach graylog2 server", e);
        } catch (APIException e) {
            log.error("Unauthorized to load user " + userName, e);
        } catch (Graylog2ServerUnavailableException e) {
            // this leads to a different return code in RedirectAuthenticator.
            throw e;
        }

        return null;
    }

    protected User pipelineAuths(User... authResults) {
        for (User user : authResults)
            if (user != null)
                return user;
        return null;
    }
}
TOP

Related Classes of lib.security.RedirectAuthenticator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.