All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.httpd.auth.container.HttpLoginServlet Maven / Gradle / Ivy

There is a newer version: 3.10.1
Show newest version
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.httpd.auth.container;

import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_EXTERNAL;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.httpd.CanonicalWebUrl;
import com.google.gerrit.httpd.HtmlDomUtil;
import com.google.gerrit.httpd.LoginUrlToken;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.AuthResult;
import com.google.gerrit.server.account.externalids.ExternalIdKeyFactory;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.util.http.CacheHeaders;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Initializes the user session if HTTP authentication is enabled.
 *
 * 

If HTTP authentication has been enabled this servlet binds to {@code /login/} and initializes * the user session based on user information contained in the HTTP request. */ @Singleton class HttpLoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final FluentLogger logger = FluentLogger.forEnclosingClass(); private final DynamicItem webSession; private final CanonicalWebUrl urlProvider; private final AccountManager accountManager; private final HttpAuthFilter authFilter; private final AuthConfig authConfig; private final ExternalIdKeyFactory externalIdKeyFactory; private final AuthRequest.Factory authRequestFactory; @Inject HttpLoginServlet( final DynamicItem webSession, final CanonicalWebUrl urlProvider, final AccountManager accountManager, final HttpAuthFilter authFilter, final AuthConfig authConfig, final ExternalIdKeyFactory externalIdKeyFactory, final AuthRequest.Factory authRequestFactory) { this.webSession = webSession; this.urlProvider = urlProvider; this.accountManager = accountManager; this.authFilter = authFilter; this.authConfig = authConfig; this.externalIdKeyFactory = externalIdKeyFactory; this.authRequestFactory = authRequestFactory; } @Override protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws ServletException, IOException { final String token = LoginUrlToken.getToken(req); CacheHeaders.setNotCacheable(rsp); final String user = authFilter.getRemoteUser(req); if (user == null || "".equals(user)) { logger.atSevere().log( "Unable to authenticate user by %s request header." + " Check container or server configuration.", authFilter.getLoginHeader()); final Document doc = HtmlDomUtil.parseFile( // HttpLoginServlet.class, "ConfigurationError.html"); replace(doc, "loginHeader", authFilter.getLoginHeader()); replace(doc, "ServerName", req.getServerName()); replace(doc, "ServerPort", ":" + req.getServerPort()); replace(doc, "ContextPath", req.getContextPath()); final byte[] bin = HtmlDomUtil.toUTF8(doc); rsp.setStatus(HttpServletResponse.SC_FORBIDDEN); rsp.setContentType("text/html"); rsp.setCharacterEncoding(UTF_8.name()); rsp.setContentLength(bin.length); try (ServletOutputStream out = rsp.getOutputStream()) { out.write(bin); } return; } final AuthRequest areq = authRequestFactory.createForUser(user); areq.setDisplayName(authFilter.getRemoteDisplayname(req)); areq.setEmailAddress(authFilter.getRemoteEmail(req)); final AuthResult arsp; try { arsp = accountManager.authenticate(areq); } catch (AccountException e) { logger.atSevere().withCause(e).log("Unable to authenticate user \"%s\"", user); rsp.sendError(HttpServletResponse.SC_FORBIDDEN); return; } String remoteExternalId = authFilter.getRemoteExternalIdToken(req); if (remoteExternalId != null) { try { logger.atFine().log( "Associating external identity \"%s\" to user \"%s\"", remoteExternalId, user); updateRemoteExternalId(arsp, remoteExternalId); } catch (AccountException | ConfigInvalidException e) { logger.atSevere().withCause(e).log( "Unable to associate external identity \"%s\" to user \"%s\"", remoteExternalId, user); rsp.sendError(HttpServletResponse.SC_FORBIDDEN); return; } } final StringBuilder rdr = new StringBuilder(); if (arsp.isNew() && authConfig.getRegisterPageUrl() != null) { rdr.append(authConfig.getRegisterPageUrl()); } else { rdr.append(urlProvider.get(req)); if (arsp.isNew() && !token.startsWith(PageLinks.REGISTER + "/")) { rdr.append('#' + PageLinks.REGISTER); } rdr.append(token); } webSession.get().login(arsp, true /* persistent cookie */); rsp.sendRedirect(rdr.toString()); } private void updateRemoteExternalId(AuthResult arsp, String remoteAuthToken) throws AccountException, IOException, ConfigInvalidException { accountManager.updateLink( arsp.getAccountId(), authRequestFactory.create(externalIdKeyFactory.create(SCHEME_EXTERNAL, remoteAuthToken))); } private void replace(Document doc, String name, String value) { Element e = HtmlDomUtil.find(doc, name); if (e != null) { e.setTextContent(value); } else { replaceByClass(doc, name, value); } } private void replaceByClass(Node parent, String name, String value) { final NodeList list = parent.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { final Node n = list.item(i); if (n instanceof Element) { final Element e = (Element) n; if (name.equals(e.getAttribute("class"))) { e.setTextContent(value); } } replaceByClass(n, name, value); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy