Added test case for authorization page
This commit is contained in:
parent
8af91a9169
commit
f65cb0e4c4
6 changed files with 233 additions and 20 deletions
|
|
@ -62,6 +62,7 @@ public class HttpURL {
|
|||
this.setHost(url.getHost());
|
||||
this.setPort(url.getPort());
|
||||
this.setPath(url.getPath());
|
||||
this.setParameters(url.getQuery());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -115,6 +116,16 @@ public class HttpURL {
|
|||
this.parameters = pars;
|
||||
}
|
||||
|
||||
protected void setParameters(String query) {
|
||||
if (query == null)
|
||||
return;
|
||||
HttpHeaderParser.parseURLParameters(parameters, query);
|
||||
}
|
||||
|
||||
public String getParameter(String key) {
|
||||
return parameters.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the parameter string in a URL.
|
||||
* <p>
|
||||
|
|
|
|||
|
|
@ -80,23 +80,23 @@ public class OAuth2AuthorizationPage implements HttpPage {
|
|||
|
||||
/** The request is missing a required parameter, includes an invalid parameter value, includes a parameter
|
||||
more than once, or is otherwise malformed. **/
|
||||
protected static final String ERROR_INVALID_REQUEST = "invalid_request";
|
||||
private static final String ERROR_INVALID_REQUEST = "invalid_request";
|
||||
/** The client is not authorized to request an authorization code using this method. **/
|
||||
protected static final String ERROR_UNAUTHORIZED_CLIENT = "unauthorized_client";
|
||||
private static final String ERROR_UNAUTHORIZED_CLIENT = "unauthorized_client";
|
||||
/** The resource owner or authorization server denied the request. **/
|
||||
protected static final String ERROR_ACCESS_DENIED = "access_denied";
|
||||
private static final String ERROR_ACCESS_DENIED = "access_denied";
|
||||
/** The authorization server does not support obtaining an authorization code using this method. **/
|
||||
protected static final String ERROR_UNSUPPORTED_RESP_TYPE = "unsupported_response_type";
|
||||
private static final String ERROR_UNSUPPORTED_RESP_TYPE = "unsupported_response_type";
|
||||
/** The requested scope is invalid, unknown, or malformed. **/
|
||||
protected static final String ERROR_INVALID_SCOPE = "invalid_scope";
|
||||
private static final String ERROR_INVALID_SCOPE = "invalid_scope";
|
||||
/** The authorization server encountered an unexpected condition that prevented it from fulfilling the request.
|
||||
(This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client
|
||||
via an HTTP redirect.) **/
|
||||
protected static final String ERROR_SERVER_ERROR = "server_error";
|
||||
private static final String ERROR_SERVER_ERROR = "server_error";
|
||||
/** The authorization server is currently unable to handle the request due to a temporary overloading or maintenance
|
||||
of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned
|
||||
to the client via an HTTP redirect.) **/
|
||||
protected static final String ERROR_TEMPORARILY_UNAVAILABLE = "temporarily_unavailable";
|
||||
private static final String ERROR_TEMPORARILY_UNAVAILABLE = "temporarily_unavailable";
|
||||
|
||||
private static final String RESPONSE_TYPE_CODE = "code";
|
||||
private static final String RESPONSE_TYPE_PASSWORD = "password";
|
||||
|
|
@ -117,34 +117,64 @@ public class OAuth2AuthorizationPage implements HttpPage {
|
|||
HttpHeader headers,
|
||||
Map<String, Object> session,
|
||||
Map<String, String> cookie,
|
||||
Map<String, String> request) throws MalformedURLException {
|
||||
Map<String, String> request) {
|
||||
|
||||
// -----------------------------------------------
|
||||
// Validate parameters
|
||||
// -----------------------------------------------
|
||||
|
||||
// Validate redirect_uri
|
||||
|
||||
if (!request.containsKey("redirect_uri")) {
|
||||
errorResponse(out, "Bad Request, missing property: redirect_uri");
|
||||
errorResponse(out, "Bad Request, missing parameter: redirect_uri");
|
||||
return;
|
||||
}
|
||||
|
||||
HttpURL url = null;
|
||||
try {
|
||||
url = new HttpURL(URLDecoder.decode(request.get("redirect_uri")));
|
||||
} catch(Exception e) {}
|
||||
|
||||
if (url == null || !"HTTPS".equalsIgnoreCase(url.getProtocol())) {
|
||||
errorResponse(out, "Invalid redirect URL: " + request.get("redirect_uri"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate client_id
|
||||
|
||||
if (!request.containsKey("client_id")) {
|
||||
errorResponse(out, "Bad Request, missing parameter: client_id");
|
||||
return;
|
||||
}
|
||||
|
||||
String clientId = request.get("client_id");
|
||||
|
||||
if (registry.isClientIdValid(clientId)) {
|
||||
errorResponse(out, "Bad Request, missing or invalid client_id value.");
|
||||
if (!registry.isClientIdValid(clientId)) {
|
||||
errorRedirect(out, url, ERROR_UNAUTHORIZED_CLIENT, request.get("state"),
|
||||
"Bad Request, invalid client_id value.");
|
||||
return;
|
||||
}
|
||||
|
||||
HttpURL url = new HttpURL(URLDecoder.decode(request.get("redirect_uri")));
|
||||
// Validate response_type
|
||||
|
||||
if (!"HTTPS".equalsIgnoreCase(url.getProtocol())) {
|
||||
errorResponse(out, "Bad redirect protocol: " + url.getProtocol());
|
||||
if (!request.containsKey("response_type")) {
|
||||
errorRedirect(out, url, ERROR_INVALID_REQUEST, request.get("state"),
|
||||
"Missing parameter response_type.");
|
||||
return;
|
||||
}
|
||||
|
||||
// -----------------------------------------------
|
||||
// Handle request
|
||||
// -----------------------------------------------
|
||||
|
||||
switch (request.get("response_type")) {
|
||||
case RESPONSE_TYPE_CODE:
|
||||
String code = generateCode();
|
||||
registry.registerAuthorizationCode(clientId, code);
|
||||
|
||||
url.setParameter("state", request.get("state"));
|
||||
url.setParameter("code", code);
|
||||
if (request.containsKey("state"))
|
||||
url.setParameter("state", request.get("state"));
|
||||
break;
|
||||
case RESPONSE_TYPE_PASSWORD:
|
||||
case RESPONSE_TYPE_CREDENTIALS:
|
||||
|
|
@ -160,7 +190,7 @@ public class OAuth2AuthorizationPage implements HttpPage {
|
|||
}
|
||||
|
||||
private String generateCode() {
|
||||
return String.valueOf(random.nextInt());
|
||||
return String.valueOf(Math.abs(random.nextLong()));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class OAuth2Registry {
|
|||
private static final long DEFAULT_TIMEOUT = 24 * 60 * 60 * 1000; // 24h
|
||||
|
||||
private Map<String, ClientRegister> clientRegistry = new HashMap<>();
|
||||
private boolean requireWhitelist = false;
|
||||
private boolean requireWhitelist = true;
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
|
|
@ -71,7 +71,7 @@ public class OAuth2Registry {
|
|||
/**
|
||||
* Set the requirement or non-requirement of pre-registered client-ids.
|
||||
* If enabled then any clients starting a OAuth2 process needs to have a
|
||||
* preregistered client-id value in the registry object.
|
||||
* preregistered client-id value in the registry object. (Default is set to true)
|
||||
*
|
||||
* @param enabled if true then all requests will be required to be in whitelist
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ public class OAuth2TokenPage extends HttpJsonPage {
|
|||
}
|
||||
|
||||
private String generateToken() {
|
||||
return String.valueOf(random.nextInt());
|
||||
return String.valueOf(Math.abs(random.nextLong()));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public class HttpTestUtil {
|
|||
StringOutputStream buff = new StringOutputStream();
|
||||
HttpPrintStream out = new HttpPrintStream(buff);
|
||||
|
||||
page.respond(out, headers, session, new HashMap(), new HashMap());
|
||||
page.respond(out, headers, session, new HashMap(), headers.getURLAttributeMap());
|
||||
|
||||
out.flush();
|
||||
HttpHeaderParser parser = new HttpHeaderParser(buff.toString());
|
||||
|
|
|
|||
172
test/zutil/net/http/page/oauth/OAuth2TokenPageTest.java
Normal file
172
test/zutil/net/http/page/oauth/OAuth2TokenPageTest.java
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Ziver Koc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package zutil.net.http.page.oauth;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import zutil.net.http.HttpHeader;
|
||||
import zutil.net.http.HttpTestUtil;
|
||||
import zutil.net.http.HttpURL;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class OAuth2TokenPageTest {
|
||||
|
||||
private OAuth2Registry registry;
|
||||
private OAuth2AuthorizationPage authPage;
|
||||
|
||||
@Before
|
||||
public void init(){
|
||||
registry = new OAuth2Registry();
|
||||
authPage = new OAuth2AuthorizationPage(registry);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidRedirect() throws IOException {
|
||||
registry.addWhitelist("12345");
|
||||
HttpHeader reqHeader = new HttpHeader();
|
||||
HttpHeader rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
// redirect_uri and client_id not provided
|
||||
|
||||
assertEquals(400, rspHeader.getResponseStatusCode());
|
||||
assertNull(rspHeader.getHeader("Location"));
|
||||
|
||||
// redirect_uri not provided
|
||||
|
||||
reqHeader.setURLAttribute("client_id", "12345");
|
||||
rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
assertEquals(400, rspHeader.getResponseStatusCode());
|
||||
assertNull(rspHeader.getHeader("Location"));
|
||||
|
||||
// redirect_uri is not a valid URL
|
||||
|
||||
reqHeader.setURLAttribute("redirect_uri", "incorrect url");
|
||||
rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
assertEquals(400, rspHeader.getResponseStatusCode());
|
||||
assertNull(rspHeader.getHeader("Location"));
|
||||
|
||||
// redirect_uri is not HTTPS
|
||||
|
||||
reqHeader.setURLAttribute("redirect_uri", "http://example.com");
|
||||
rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
assertEquals(400, rspHeader.getResponseStatusCode());
|
||||
assertNull(rspHeader.getHeader("Location"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidClientId() throws IOException {
|
||||
HttpHeader reqHeader = new HttpHeader();
|
||||
reqHeader.setURLAttribute("redirect_uri", "https://example.com");
|
||||
HttpHeader rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
// client_id not provided
|
||||
|
||||
assertEquals(400, rspHeader.getResponseStatusCode());
|
||||
assertNull(rspHeader.getHeader("Location"));
|
||||
|
||||
}
|
||||
|
||||
/** The request is missing a required parameter, includes an invalid parameter value, includes a parameter
|
||||
more than once, or is otherwise malformed. **/
|
||||
@Test
|
||||
public void errorInvalidRequest() throws IOException {
|
||||
registry.addWhitelist("12345");
|
||||
HttpHeader reqHeader = new HttpHeader();
|
||||
reqHeader.setURLAttribute("client_id", "12345");
|
||||
reqHeader.setURLAttribute("redirect_uri", "https://example.com");
|
||||
HttpHeader rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
// Missing response_type
|
||||
|
||||
assertEquals(302, rspHeader.getResponseStatusCode());
|
||||
HttpURL url = new HttpURL(rspHeader.getHeader("Location"));
|
||||
assertNull(url.getParameter("code"));
|
||||
assertEquals("invalid_request", url.getParameter("error"));
|
||||
|
||||
// response_type is not code
|
||||
|
||||
reqHeader.setURLAttribute("response_type", "not_code");
|
||||
rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
assertEquals(302, rspHeader.getResponseStatusCode());
|
||||
assertNull(url.getParameter("code"));
|
||||
assertEquals("invalid_request", url.getParameter("error"));
|
||||
}
|
||||
|
||||
/** The client is not authorized to request an authorization code using this method. **/
|
||||
@Test
|
||||
public void errorUnauthorizedClient() throws IOException {
|
||||
registry.addWhitelist("12345");
|
||||
HttpHeader reqHeader = new HttpHeader();
|
||||
reqHeader.setURLAttribute("client_id", "67890");
|
||||
reqHeader.setURLAttribute("redirect_uri", "https://example.com");
|
||||
HttpHeader rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
// Missing response_type
|
||||
|
||||
assertEquals(302, rspHeader.getResponseStatusCode());
|
||||
HttpURL url = new HttpURL(rspHeader.getHeader("Location"));
|
||||
assertNull(url.getParameter("code"));
|
||||
assertEquals("unauthorized_client", url.getParameter("error"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestBasic() throws IOException {
|
||||
registry.addWhitelist("12345");
|
||||
HttpHeader reqHeader = new HttpHeader();
|
||||
reqHeader.setURLAttribute("client_id", "12345");
|
||||
reqHeader.setURLAttribute("redirect_uri", "https://example.com");
|
||||
reqHeader.setURLAttribute("response_type", "code");
|
||||
HttpHeader rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
assertEquals(302, rspHeader.getResponseStatusCode());
|
||||
HttpURL url = new HttpURL(rspHeader.getHeader("Location"));
|
||||
assertEquals("example.com", url.getHost());
|
||||
assertNotNull(url.getParameter("code"));
|
||||
assertNull(url.getParameter("state"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithState() throws IOException {
|
||||
registry.addWhitelist("12345");
|
||||
HttpHeader reqHeader = new HttpHeader();
|
||||
reqHeader.setURLAttribute("client_id", "12345");
|
||||
reqHeader.setURLAttribute("redirect_uri", "https://example.com");
|
||||
reqHeader.setURLAttribute("response_type", "code");
|
||||
reqHeader.setURLAttribute("state", "app_state");
|
||||
HttpHeader rspHeader = HttpTestUtil.makeRequest(authPage, reqHeader);
|
||||
|
||||
assertEquals(302, rspHeader.getResponseStatusCode());
|
||||
HttpURL url = new HttpURL(rspHeader.getHeader("Location"));
|
||||
assertEquals("app_state", url.getParameter("state"));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue