Implemented OAuth2 authorization error response using redirect URI.

Change-Id: Id79f3eec0beacaca792fb3130e3e41f5d9bbc7ad
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java
index c0353be..77f8e17 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java
@@ -1,5 +1,8 @@
 package de.ids_mannheim.korap.oauth2.oltu.service;
 
+import java.net.URI;
+import java.net.URISyntaxException;
+
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
@@ -13,6 +16,8 @@
 import com.sun.jersey.api.client.ClientResponse.Status;
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
 import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
 import de.ids_mannheim.korap.oauth2.service.OAuth2AuthorizationService;
 
@@ -35,29 +40,60 @@
      * @param request
      * @param authzRequest
      * @param username
-     * @return
+     * @return redirect URI containing authorization code if
+     *         successful.
+     * 
      * @throws KustvaktException
      * @throws OAuthSystemException
      */
     public String requestAuthorizationCode (HttpServletRequest request,
             OAuthAuthzRequest authzRequest, String username)
-            throws KustvaktException, OAuthSystemException {
+            throws OAuthSystemException, KustvaktException {
 
         String code = oauthIssuer.authorizationCode();
         checkResponseType(authzRequest.getResponseType());
 
         String clientId = authzRequest.getClientId();
         OAuth2Client client = clientService.authenticateClientId(clientId);
-        
+
         String redirectUri = authzRequest.getRedirectURI();
         String verifiedRedirectUri = verifyRedirectUri(client, redirectUri);
-        String scope = createAuthorization(username, authzRequest.getClientId(),
-                redirectUri, authzRequest.getScopes(), code);
 
-        OAuthResponse oAuthResponse = OAuthASResponse
-                .authorizationResponse(request, Status.FOUND.getStatusCode())
-                .setCode(code).setScope(scope)
-                .location(verifiedRedirectUri).buildQueryMessage();
+        URI redirectURI;
+        try {
+            redirectURI = new URI(verifiedRedirectUri);
+        }
+        catch (URISyntaxException e) {
+            throw new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
+                    "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
+        }
+
+        String scope;
+        try {
+            scope = createAuthorization(username, authzRequest.getClientId(),
+                    redirectUri, authzRequest.getScopes(), code);
+        }
+        catch (KustvaktException e) {
+            e.setRedirectUri(redirectURI);
+            throw e;
+        }
+
+        OAuthResponse oAuthResponse;
+        try {
+            oAuthResponse = OAuthASResponse
+                    .authorizationResponse(request,
+                            Status.FOUND.getStatusCode())
+                    .setCode(code).setScope(scope).location(verifiedRedirectUri)
+                    .buildQueryMessage();
+        }
+        catch (OAuthSystemException e) {
+            // Should not happen
+            KustvaktException ke =
+                    new KustvaktException(StatusCodes.OAUTH2_SYSTEM_ERROR,
+                            e.getMessage(), OAuth2Error.SERVER_ERROR);
+            ke.setRedirectUri(redirectURI);
+            throw ke;
+        }
         return oAuthResponse.getLocationUri();
     }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java
index f6a223c..d244e90 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java
@@ -4,6 +4,7 @@
 import java.net.URISyntaxException;
 
 import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.Response.Status;
@@ -13,6 +14,7 @@
 import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
 import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
 import org.apache.oltu.oauth2.common.message.OAuthResponse;
+import org.apache.oltu.oauth2.common.message.OAuthResponse.OAuthErrorResponseBuilder;
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
@@ -105,10 +107,37 @@
             int statusCode) throws OAuthSystemException {
         OAuthProblemException oAuthProblemException = OAuthProblemException
                 .error(e.getEntity()).description(e.getMessage());
-        return OAuthResponse.errorResponse(statusCode)
-                .error(oAuthProblemException).buildJSONMessage();
+
+        OAuthErrorResponseBuilder responseBuilder = OAuthResponse
+                .errorResponse(statusCode).error(oAuthProblemException);
+        URI redirectUri = e.getRedirectUri();
+        if (redirectUri != null) {
+            responseBuilder.location(redirectUri.toString());
+            return responseBuilder.buildQueryMessage();
+        }
+
+        return responseBuilder.buildJSONMessage();
     }
 
+    /**
+     * RFC 6749 regarding authorization error response:
+     * 
+     * If the request fails due to a missing, invalid, or mismatching
+     * redirection URI, or if the client identifier is missing or
+     * invalid, the authorization server SHOULD inform the resource
+     * owner of the error and MUST NOT automatically redirect the
+     * user-agent to the invalid redirection URI.
+     * 
+     * If the resource owner denies the access request or if the
+     * request fails for reasons other than a missing or invalid
+     * redirection URI, the authorization server informs the client by
+     * adding the following parameters to the query component of the
+     * redirection URI using the "application/x-www-form-urlencoded"
+     * format.
+     * 
+     * @param oAuthResponse
+     * @return
+     */
     public Response createResponse (OAuthResponse oAuthResponse) {
         ResponseBuilder builder =
                 Response.status(oAuthResponse.getResponseStatus());
@@ -121,6 +150,17 @@
             builder.header(HttpHeaders.WWW_AUTHENTICATE,
                     "Basic realm=\"Kustvakt\"");
         }
+        String uri = oAuthResponse.getLocationUri();
+        if (uri != null && !uri.isEmpty()) {
+            try {
+                builder.location(new URI(uri));
+                builder.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE);
+            }
+            catch (URISyntaxException e) {
+                e.printStackTrace();
+            }
+        }
+
         return builder.build();
     }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/OpenIdResponseHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/OpenIdResponseHandler.java
index 4c50d75..21cecdb 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/OpenIdResponseHandler.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/OpenIdResponseHandler.java
@@ -4,6 +4,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 
@@ -104,7 +105,8 @@
                     state, responseMode).toURI();
         }
 
-        ResponseBuilder builder = Response.temporaryRedirect(uri);
+        ResponseBuilder builder = Response.temporaryRedirect(uri)
+                .type(MediaType.APPLICATION_FORM_URLENCODED);
         return builder.build();
     }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
index 4b2e19e..6614f11 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
@@ -79,9 +79,9 @@
         TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
         String username = tokenContext.getUsername();
 
+        HttpServletRequest requestWithForm =
+                new FormRequestWrapper(request, form);
         try {
-            HttpServletRequest requestWithForm =
-                    new FormRequestWrapper(request, form);
             OAuth2AuthorizationRequest authzRequest =
                     new OAuth2AuthorizationRequest(requestWithForm);
             String uri = authorizationService.requestAuthorizationCode(
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2WithOpenIdController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2WithOpenIdController.java
index d3605de..82affd6 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2WithOpenIdController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2WithOpenIdController.java
@@ -5,7 +5,6 @@
 
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;