am.ik.categolj2.app.authentication.AuthenticationHelper.java Source code

Java tutorial

Introduction

Here is the source code for am.ik.categolj2.app.authentication.AuthenticationHelper.java

Source

/*
 * Copyright (C) 2014 Toshiaki Maki
 *
 * 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 am.ik.categolj2.app.authentication;

import am.ik.categolj2.app.Categolj2Cookies;
import am.ik.categolj2.config.Categolj2AdminProperties;
import am.ik.categolj2.core.logger.LogManager;
import am.ik.categolj2.core.web.RemoteAddresses;
import am.ik.categolj2.core.web.UserAgents;
import am.ik.categolj2.domain.model.LoginHistory;
import am.ik.categolj2.domain.service.loginhistory.LoginHistoryService;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.terasoluna.gfw.common.date.DateFactory;

import javax.inject.Inject;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;

@Component
public class AuthenticationHelper {
    private static Logger logger = LogManager.getLogger();

    @Inject
    LoginHistoryService loginHistoryService;
    @Inject
    DateFactory dateFactory;
    @Inject
    ObjectMapper objectMapper;
    @Inject
    Categolj2AdminProperties adminClientProperties;

    public HttpEntity<MultiValueMap<String, Object>> createRopRequest(String username, String password) {
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("username", username);
        params.add("password", password);
        params.add("grant_type", "password");
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        byte[] clientInfo = (adminClientProperties.getClientId() + ":" + adminClientProperties.getClientSecret())
                .getBytes(StandardCharsets.UTF_8);
        String basic = new String(Base64.getEncoder().encode(clientInfo), StandardCharsets.UTF_8);
        headers.set(com.google.common.net.HttpHeaders.AUTHORIZATION, "Basic " + basic);
        return new HttpEntity<>(params, headers);
    }

    int getRefreshTokenMaxAge(OAuth2AccessToken accessToken) {
        return accessToken.getExpiresIn() * 10 /* FIXME */;
    }

    void saveAccessTokenInCookie(OAuth2AccessToken accessToken, HttpServletResponse response)
            throws UnsupportedEncodingException {
        Cookie accessTokenValueCookie = new Cookie(Categolj2Cookies.ACCESS_TOKEN_VALUE_COOKIE,
                URLEncoder.encode(accessToken.getValue(), "UTF-8"));
        accessTokenValueCookie.setMaxAge(accessToken.getExpiresIn());
        Cookie accessTokenExpireCookie = new Cookie(Categolj2Cookies.ACCESS_TOKEN_EXPIRATION_COOKIE,
                URLEncoder.encode(String.valueOf(accessToken.getExpiration().getTime()), "UTF-8"));
        accessTokenExpireCookie.setMaxAge(accessToken.getExpiresIn());

        response.addCookie(accessTokenValueCookie);
        response.addCookie(accessTokenExpireCookie);

        OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
        if (refreshToken != null) {
            Cookie refreshTokenCookie = new Cookie(Categolj2Cookies.REFRESH_TOKEN_VALUE_COOKIE,
                    URLEncoder.encode(refreshToken.getValue(), "UTF-8"));
            refreshTokenCookie.setMaxAge(getRefreshTokenMaxAge(accessToken));
            response.addCookie(refreshTokenCookie);
        }
    }

    void removeCookie(String cookieName, HttpServletResponse response) throws UnsupportedEncodingException {
        Cookie cookie = new Cookie(cookieName, URLEncoder.encode("", "UTF-8"));
        cookie.setMaxAge(0);
        response.addCookie(cookie);
    }

    void removeAccessTokenFromCookie(HttpServletResponse response) throws UnsupportedEncodingException {
        removeCookie(Categolj2Cookies.ACCESS_TOKEN_VALUE_COOKIE, response);
        removeCookie(Categolj2Cookies.ACCESS_TOKEN_EXPIRATION_COOKIE, response);
    }

    void removeRefreshTokenFromCookie(HttpServletResponse response) throws UnsupportedEncodingException {
        removeCookie(Categolj2Cookies.REFRESH_TOKEN_VALUE_COOKIE, response);
    }

    @SuppressWarnings("unchecked")
    void writeLoginHistory(OAuth2AccessToken accessToken, HttpServletRequest request, HttpServletResponse response)
            throws UnsupportedEncodingException {
        // user
        Map<String, ?> user = (Map<String, ?>) accessToken.getAdditionalInformation().get("user");
        if (user != null) {
            String username = (String) user.get("username");
            String firstName = (String) user.get("firstName");
            String lastName = (String) user.get("lastName");
            String email = (String) user.get("email");

            LoginHistory loginHistory = createHistory(username, request);
            loginHistoryService.save(loginHistory);

            saveUserInformationInCookie(username, firstName, lastName, email, accessToken, response);
        } else {
            logger.error("No user information! (access_token={})", accessToken);
        }
    }

    void saveUserInformationInCookie(String username, String firstName, String lastName, String email,
            OAuth2AccessToken accessToken, HttpServletResponse response) throws UnsupportedEncodingException {
        try {
            Cookie cookie = new Cookie(Categolj2Cookies.USER_COOKIE,
                    objectMapper.writeValueAsString(new UserInfo(username, firstName, lastName, email)));

            cookie.setMaxAge(getRefreshTokenMaxAge(accessToken));
            response.addCookie(cookie);
        } catch (JsonProcessingException e) {
            logger.error("JSON conversion failed!", e);
        }
    }

    LoginHistory createHistory(String username, HttpServletRequest request) {
        LoginHistory loginHistory = new LoginHistory();
        loginHistory.setLoginAgent(UserAgents.getUserAgent(request));
        loginHistory.setLoginHost(RemoteAddresses.getRemoteAddress(request));
        loginHistory.setLoginDate(dateFactory.newDateTime());
        loginHistory.setUsername(username);
        return loginHistory;
    }

    void handleHttpStatusCodeException(HttpStatusCodeException e, RedirectAttributes attributes)
            throws IOException {
        if (logger.isInfoEnabled()) {
            logger.info("authentication failed (message={},X-Track={})", e.getMessage(),
                    e.getResponseHeaders().get("X-Track"));
        }
        try {
            OAuth2Exception oAuth2Exception = objectMapper.readValue(e.getResponseBodyAsByteArray(),
                    OAuth2Exception.class);
            attributes.addAttribute("error", oAuth2Exception.getMessage());
        } catch (JsonMappingException | JsonParseException ex) {
            attributes.addAttribute("error", e.getMessage());
        }
    }

}