org.awesomeagile.testing.google.FakeGoogleController.java Source code

Java tutorial

Introduction

Here is the source code for org.awesomeagile.testing.google.FakeGoogleController.java

Source

package org.awesomeagile.testing.google;

/*
 * ================================================================================================
 * Awesome Agile
 * %%
 * Copyright (C) 2015 Mark Warren, Phillip Heller, Matt Kubej, Linghong Chen, Stanislav Belov, Qanit Al
 * %%
 * 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.
 * ------------------------------------------------------------------------------------------------
 */

import com.google.common.collect.ImmutableList;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestHeader;
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.bind.annotation.ResponseBody;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author sbelov@google.com (Stan Belov)
 */
@Controller
public class FakeGoogleController {

    private static final String CODE = "code";
    private static final String AUTHORIZATION_CODE = "authorization_code";
    private static final int EXPIRATION_MILLIS = 3600000;
    public static final String BEARER = "Bearer";
    private String clientId;
    private String clientSecret;
    private List<String> redirectUriPrefixes = ImmutableList.of();
    private Map<String, AccessToken> codeToToken = new ConcurrentHashMap<>();
    private Set<String> knownTokens = Collections.newSetFromMap(new ConcurrentHashMap<>());
    private Person person;

    @ResponseBody
    @RequestMapping(method = RequestMethod.GET, path = "/oauth2/auth")
    public ResponseEntity<?> authenticate(@RequestParam("client_id") String clientId,
            @RequestParam(value = "client_secret", required = false) String clientSecret,
            @RequestParam("response_type") String responseType, @RequestParam("redirect_uri") String redirectUri,
            @RequestParam("scope") String scope) {
        // Validate client_id and client_secret
        if (!this.clientId.equals(clientId) || (clientSecret != null && !this.clientSecret.equals(clientSecret))) {
            return ResponseEntity.<String>badRequest().body("Wrong client_id or client_secret!");
        }
        if (!prefixMatches(redirectUri)) {
            return wrongRedirectUriResponse();
        }
        String code = RandomStringUtils.randomAlphanumeric(64);
        String token = RandomStringUtils.randomAlphanumeric(64);
        codeToToken.put(code, new AccessToken(token, scope, "", System.currentTimeMillis() + EXPIRATION_MILLIS));
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(redirectUri).queryParam(CODE, code);
        return ResponseEntity.status(HttpStatus.FOUND).header(HttpHeaders.LOCATION, builder.build().toUriString())
                .build();
    }

    @RequestMapping(value = "/oauth2/token", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> getToken(@RequestParam("code") String code,
            @RequestParam("redirect_uri") String redirectUri, @RequestParam("grant_type") String grantType) {
        if (AUTHORIZATION_CODE.equals(grantType)) {
            if (!prefixMatches(redirectUri)) {
                return wrongRedirectUriResponse();
            }
            if (!codeToToken.containsKey(code)) {
                return ResponseEntity.<String>badRequest().body("Wrong code!");
            }
            AccessToken accessToken = codeToToken.get(code);
            knownTokens.add(accessToken.getAccessToken());
            return ResponseEntity.ok(accessToken);
        }
        return ResponseEntity.<String>badRequest().body("Wrong grant_type!");
    }

    @RequestMapping(value = "/plus/v1/people/me", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public Person getMe(@RequestHeader(value = "Authorization", required = false) String authorizationHeader) {
        validateAuthorization(authorizationHeader);
        return person;
    }

    @ResponseBody
    @ExceptionHandler({ AuthenticationException.class })
    public ResponseEntity<String> handleAuthenticationException(AuthenticationException ex) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ex.getMessage());
    }

    private void validateAuthorization(String authorizationHeader) {
        if (StringUtils.startsWithIgnoreCase(authorizationHeader, BEARER)) {
            if (knownTokens.contains(StringUtils.removeStartIgnoreCase(authorizationHeader, BEARER).trim())) {
                return;
            }
        }
        throw new BadCredentialsException("Invalid authorization header: " + authorizationHeader);
    }

    private ResponseEntity<String> wrongRedirectUriResponse() {
        return ResponseEntity.<String>badRequest().body("Wrong redirect_uri!");
    }

    private boolean prefixMatches(String redirectUri) {
        for (String prefix : redirectUriPrefixes) {
            if (redirectUri.startsWith(prefix)) {
                return true;
            }
        }
        return false;
    }

    public FakeGoogleController setClientId(String clientId) {
        this.clientId = clientId;
        return this;
    }

    public FakeGoogleController setClientSecret(String clientSecret) {
        this.clientSecret = clientSecret;
        return this;
    }

    public FakeGoogleController setRedirectUriPrefixes(List<String> redirectUriPrefixes) {
        this.redirectUriPrefixes = ImmutableList.copyOf(redirectUriPrefixes);
        return this;
    }

    public FakeGoogleController setPerson(Person person) {
        this.person = person;
        return this;
    }
}