org.surfnet.oaaas.web.ClientController.java Source code

Java tutorial

Introduction

Here is the source code for org.surfnet.oaaas.web.ClientController.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.surfnet.oaaas.web;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.PartialRequestBuilder;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.core.header.OutBoundHeaders;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;

/**
 * Entry point for testing the resource server. Listens to http://localhost:8084/test
 */
@Controller
public class ClientController {

    private static final String AUTHORIZATION = "Authorization";
    private static final String SETTINGS = "settings";
    private static final String BR = System.getProperty("line.separator");

    private static final ObjectMapper mapper = new ObjectMapper();

    private Client client;

    private Environment env;

    /**
     * @param env
     */
    public ClientController(Environment env) {
        ClientConfig config = new DefaultClientConfig();
        config.getClasses().add(JacksonJsonProvider.class);
        this.client = Client.create(config);
        Assert.notNull(env);
        this.env = env;
    }

    @RequestMapping(value = { "test" }, method = RequestMethod.GET)
    public String start(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        modelMap.addAttribute(SETTINGS, createDefaultSettings(false));
        return "oauth-client";
    }

    @RequestMapping(value = "/test", method = RequestMethod.POST, params = "reset")
    public String reset(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        return start(modelMap, request, response);
    }

    @RequestMapping(value = "test", method = RequestMethod.POST, params = "step1")
    public String step1(ModelMap modelMap, @ModelAttribute("settings") ClientSettings settings,
            HttpServletRequest request, HttpServletResponse response) throws IOException {
        settings.setStep("step2");
        modelMap.addAttribute(SETTINGS, settings);
        return "oauth-client";
    }

    @RequestMapping(value = "test", method = RequestMethod.POST, params = "step2")
    public void step2(ModelMap modelMap, @ModelAttribute("settings") ClientSettings settings,
            HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.sendRedirect(settings.getAuthorizationURLComplete());
    }

    @RequestMapping(value = "redirect", method = RequestMethod.GET)
    public String redirect(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response)
            throws JsonParseException, JsonMappingException, IOException {
        String code = request.getParameter("code");
        ClientSettings settings = createDefaultSettings(false);

        MultivaluedMap<String, String> formData = new MultivaluedMapImpl();
        formData.add("grant_type", "authorization_code");
        formData.add("code", code);
        formData.add("redirect_uri", env.getProperty("redirect_uri"));

        String auth = "Basic ".concat(new String(Base64
                .encodeBase64(settings.getOauthKey().concat(":").concat(settings.getOauthSecret()).getBytes())));
        Builder builder = client.resource(settings.getAccessTokenEndPoint()).header(AUTHORIZATION, auth)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE);
        OutBoundHeaders headers = getHeadersCopy(builder);
        ClientResponse clientResponse = builder.post(ClientResponse.class, formData);
        String json = IOUtils.toString(clientResponse.getEntityInputStream());
        HashMap map = mapper.readValue(json, HashMap.class);
        settings.setStep("step3");
        settings.setAccessToken((String) map.get("access_token"));
        modelMap.put(SETTINGS, settings);
        modelMap.put("requestInfo",
                "Method: POST".concat(BR).concat("URL: ").concat(settings.getAccessTokenEndPoint()).concat(BR)
                        .concat("Headers: ").concat(headers.toString()).concat(BR).concat("Body: ")
                        .concat(formData.toString()));
        addResponseInfo(modelMap, clientResponse);
        modelMap.put("rawResponseInfo", json);
        return "oauth-client";
    }

    @RequestMapping(value = "test", method = RequestMethod.POST, params = "step3")
    public String step3(ModelMap modelMap, @ModelAttribute("settings") ClientSettings settings,
            HttpServletRequest request, HttpServletResponse response) throws IOException {
        Builder builder = client.resource(settings.getRequestURL())
                .header(AUTHORIZATION, "bearer ".concat(settings.getAccessToken()))
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE);
        OutBoundHeaders headers = getHeadersCopy(builder);
        ClientResponse clientResponse = builder.get(ClientResponse.class);
        String json = IOUtils.toString(clientResponse.getEntityInputStream());
        settings.setStep("step3");
        modelMap.put(SETTINGS, settings);
        modelMap.put("requestInfo", "Method: GET".concat(BR).concat("URL: ").concat(settings.getRequestURL())
                .concat(BR).concat("Headers: ").concat(headers.toString()));
        addResponseInfo(modelMap, clientResponse);
        modelMap.put("rawResponseInfo", json);
        return "oauth-client";
    }

    private void addResponseInfo(ModelMap modelMap, ClientResponse clientResponse) {
        modelMap.put("responseInfo", "Status: ".concat(String.valueOf(clientResponse.getStatus()).concat(BR)
                .concat("Headers:").concat(clientResponse.getHeaders().toString())));
    }

    /*
     * Nasty trick to be able to print out the headers after the POST is done
     */
    private OutBoundHeaders getHeadersCopy(Builder builder) {
        Field metaData;
        try {
            metaData = PartialRequestBuilder.class.getDeclaredField("metadata");
            metaData.setAccessible(true);
            return new OutBoundHeaders((OutBoundHeaders) metaData.get(builder));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * See /apis-authorization-server/src/main/resources/db/migration/hsqldb/V1__auth-server-admin.sql
     */
    protected ClientSettings createDefaultSettings(boolean implicitGrant) {
        String responseType = implicitGrant ? "token" : "code";
        String redirectUri = env.getProperty("redirect_uri");
        String tokenUri = env.getProperty("token_uri");
        String clientId = env.getProperty("client_id");
        String clientSecret = env.getProperty("client_secret");
        String authorizeUrl = env.getProperty("authorize_url");
        String resourceServerApiUrl = env.getProperty("resource_server_api_url");
        ClientSettings settings = new ClientSettings(tokenUri, clientId, clientSecret, authorizeUrl, "step1",
                resourceServerApiUrl);
        settings.setAuthorizationURLComplete(String.format(
                settings.getAuthorizationURL()
                        .concat("?response_type=%s&client_id=%s&redirect_uri=%s&scope=read&state=example"),
                responseType, settings.getOauthKey(), redirectUri));
        return settings;

    }
}