public View getUnsuccessfulView(
      AuthorizationRequest authorizationRequest, OAuth2Exception failure) {

    if (authorizationRequest == null || authorizationRequest.getRedirectUri() == null) {
      // we have no redirect for the user. very sad.
      throw new UnapprovedClientAuthenticationException(
          "Authorization failure, and no redirect URI.", failure);
    }

    Map<String, String> query = new LinkedHashMap<String, String>();

    query.put("error", failure.getOAuth2ErrorCode());
    query.put("error_description", failure.getMessage());

    if (authorizationRequest.getState() != null) {
      query.put("state", authorizationRequest.getState());
    }

    if (failure.getAdditionalInformation() != null) {
      for (Map.Entry<String, String> additionalInfo :
          failure.getAdditionalInformation().entrySet()) {
        query.put(additionalInfo.getKey(), additionalInfo.getValue());
      }
    }

    String url =
        append(
            authorizationRequest.getRedirectUri(), query, appendToFragment(authorizationRequest));
    return new RedirectView(url, false, true, false);
  }
  @Override
  public View getSuccessfulAuthorizationCodeView(
      AuthorizationRequest authorizationRequest, String authorizationCode) {
    if (authorizationCode == null) {
      throw new IllegalStateException("No authorization code found in the current request scope.");
    }

    Map<String, String> query = new LinkedHashMap<String, String>();
    query.put("code", authorizationCode);

    String state = authorizationRequest.getState();
    if (state != null) {
      query.put("state", state);
    }

    return new RedirectView(
        append(authorizationRequest.getRedirectUri(), query, false), false, true, false);
  }
  private String appendAccessToken(
      AuthorizationRequest authorizationRequest, OAuth2AccessToken accessToken) {

    Map<String, Object> vars = new LinkedHashMap<String, Object>();
    Map<String, String> keys = new HashMap<String, String>();

    if (accessToken == null) {
      throw new InvalidRequestException("An implicit grant could not be made");
    }

    vars.put("access_token", accessToken.getValue());
    vars.put("token_type", accessToken.getTokenType());
    String state = authorizationRequest.getState();

    if (state != null) {
      vars.put("state", state);
    }
    Date expiration = accessToken.getExpiration();
    if (expiration != null) {
      long expires_in = (expiration.getTime() - System.currentTimeMillis()) / 1000;
      vars.put("expires_in", expires_in);
    }
    String originalScope = authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE);
    if (originalScope == null
        || !OAuth2Utils.parseParameterList(originalScope).equals(accessToken.getScope())) {
      vars.put("scope", OAuth2Utils.formatParameterList(accessToken.getScope()));
    }
    Map<String, Object> additionalInformation = accessToken.getAdditionalInformation();
    for (String key : additionalInformation.keySet()) {
      Object value = additionalInformation.get(key);
      if (value != null) {
        keys.put("extra_" + key, key);
        vars.put("extra_" + key, value);
      }
    }
    // Do not include the refresh token (even if there is one)
    return append(authorizationRequest.getRedirectUri(), vars, keys, true);
  }