org.energyos.espi.thirdparty.web.AuthorizationController.java Source code

Java tutorial

Introduction

Here is the source code for org.energyos.espi.thirdparty.web.AuthorizationController.java

Source

/*
 * Copyright 2013, 2014, 2015 EnergyOS.org
 *
 *    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 org.energyos.espi.thirdparty.web;

import java.security.Principal;
import java.util.GregorianCalendar;

import javax.persistence.NoResultException;
import javax.xml.bind.JAXBException;

import org.energyos.espi.common.domain.AccessToken;
import org.energyos.espi.common.domain.ApplicationInformation;
import org.energyos.espi.common.domain.Authorization;
import org.energyos.espi.common.domain.RetailCustomer;
import org.energyos.espi.common.domain.Routes;
import org.energyos.espi.common.service.AuthorizationService;
import org.energyos.espi.thirdparty.repository.UsagePointRESTRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.HttpClientErrorException;

@Controller
public class AuthorizationController extends BaseController {

    @Autowired
    private AuthorizationService authorizationService;

    // TODO The following is legacy code that will do the import of a
    // subscription
    // from a DC. Needs to be separated out of the "repository" level and be
    // callable as a TP specific service level.

    @Autowired
    private UsagePointRESTRepository usagePointRESTRepository;

    @Autowired
    @Qualifier("clientRestTemplateFactory")
    private ClientRestTemplateFactory templateFactory;

    @RequestMapping(value = Routes.THIRD_PARTY_OAUTH_CODE_CALLBACK, method = RequestMethod.GET)
    public String authorization(String code, String state, ModelMap model, Principal principal,
            @RequestParam(value = "error", required = false) String error,
            @RequestParam(value = "error_description", required = false) String error_description,
            @RequestParam(value = "error_uri", required = false) String error_uri) {

        try {

            // Is /oauth/authorization response valid (i.e. is the "state"
            // element correct)?
            Authorization authorization = authorizationService.findByState(state);

            // Process valid /oauth/authorization response
            ApplicationInformation applicationInformation = authorization.getApplicationInformation();

            // Verify /oauth/authorization Endpoint process completed
            // successfully
            if (code != null) {
                try {

                    // Update Authorization record with returned authorization
                    // code for audit purposes
                    authorization.setCode(code);
                    authorization.setGrantType("authorization_code");
                    authorization.setUpdated(new GregorianCalendar());
                    authorizationService.merge(authorization);

                    // Format /oauth/token Endpoint request
                    String url = String.format("%s?redirect_uri=%s&code=%s&grant_type=authorization_code",
                            applicationInformation.getAuthorizationServerTokenEndpoint(),
                            applicationInformation.getRedirectUri(), code);

                    // Build /oauth/token Endpoint request
                    ClientRestTemplate restTemplate = templateFactory.newClientRestTemplate(
                            applicationInformation.getClientId(), applicationInformation.getClientSecret());

                    // Issue /oauth/token Endpoint request
                    AccessToken token = restTemplate.getForObject(url, AccessToken.class);

                    // Process /oauth/token Endpoint response

                    if (token.getAccessToken() != null) {
                        authorization.setAccessToken(token.getAccessToken());
                        authorization.setTokenType(token.getTokenType());
                        authorization.setExpiresIn(token.getExpiresIn());
                        authorization.setRefreshToken(token.getRefreshToken());
                        authorization.setScope(token.getScope());
                        authorization.setAuthorizationURI(token.getAuthorizationURI());
                        authorization.setResourceURI(token.getResourceURI());
                        authorization.setUpdated(new GregorianCalendar());
                        authorization.setStatus("1"); // Set authorization
                        // record status as
                        // "Active"
                        authorization.setState(null); // Clear State as a
                        // security measure

                        // Update authorization record with /oauth/token
                        // response data
                        authorizationService.merge(authorization);

                        // now do the initial import of the Authorized Resource,
                        // if it is
                        // not ready, then we will wait till we receive a Notify
                        // or the UX call for it.
                        // TODO: create a Subscription to work with if needed

                        RetailCustomer currentCustomer = currentCustomer(principal);

                        try {
                            usagePointRESTRepository.findAllByRetailCustomerId(currentCustomer.getId());

                        } catch (JAXBException e) {
                            // nothing there, so log the fact and move on. It
                            // will get imported later.
                            System.out.printf("\nThirdParty Import Exception: %s\n", e.toString());
                            e.printStackTrace();
                        }
                    } else {

                        System.out.printf("\n/oauth/token Request did not return an access token\n");
                    }

                } catch (HttpClientErrorException x) {

                    // TODO: Extract error, error_description and error_uri from
                    // JSON response. Currently recording null for all three
                    // fields.

                    // Update authorization record
                    System.out.printf("\nHTTPClientException: %s\n", x.toString());

                    authorization.setError(error);
                    authorization.setErrorDescription(error_description);
                    authorization.setErrorUri(error_uri);
                    authorization.setUpdated(new GregorianCalendar());
                    authorization.setStatus("2"); // Set authorization record
                    // status as "Denied"
                    authorization.setState(null); // Clear State as a security
                    // measure
                    authorizationService.merge(authorization);

                    // TODO: Should the "message" differ based on the exception?
                    throw new UserDeniedAuthorizationException("Unable to retrieve OAuth token", x);
                }
            } else {

                System.out.printf("\nOAuth2 authorization_request returned an error:\n");
                System.out.printf("Error:             " + error + "\n");
                System.out.printf("Error_description: " + error_description + "\n");
                System.out.printf("Error_uri:         " + error_uri + "\n");

                // Update authorization record with error response
                authorization.setError(error);
                authorization.setErrorDescription(error_description);
                authorization.setErrorUri(error_uri);
                authorization.setUpdated(new GregorianCalendar());
                authorization.setStatus("2"); // Set authorization record status
                // as "Denied"
                authorization.setState(null); // Clear State as a security
                // measure
                authorizationService.merge(authorization);

                throw new UserDeniedAuthorizationException("Error: " + error_description);

            }

        } catch (NoResultException | EmptyResultDataAccessException e) {

            // We received an invalid /oauth/authorization response
            // TODO: Log receipt of an invalid /oauth/authorization response
            return "/home";

        }

        return "redirect:/RetailCustomer/" + currentCustomer(principal).getId() + "/AuthorizationList";
    }

    @RequestMapping(value = Routes.THIRD_PARTY_AUTHORIZATION, method = RequestMethod.GET)
    public String index(ModelMap model, Authentication principal) {
        model.put("authorizationList",
                authorizationService.findAllByRetailCustomerId(currentCustomer(principal).getId()));
        return "/RetailCustomer/AuthorizationList/index";
    }

    public void setAuthorizationService(AuthorizationService authorizationService) {
        this.authorizationService = authorizationService;
    }

    public AuthorizationService getAuthorizationService() {
        return this.authorizationService;
    }

    public void setUsagePointRESTRepository(UsagePointRESTRepository usagePointRESTRepository) {
        this.usagePointRESTRepository = usagePointRESTRepository;
    }

    public UsagePointRESTRepository getUsagePointRESTRepository() {
        return this.usagePointRESTRepository;
    }

    public void setClientRestTemplateFactory(ClientRestTemplateFactory templateFactory) {
        this.templateFactory = templateFactory;
    }

    public ClientRestTemplateFactory getClientRestTemplateFactory() {
        return this.templateFactory;
    }

}