Skip to content

Commit

Permalink
add Subject Token Response Validator
Browse files Browse the repository at this point in the history
add class doc for subject token validator
  • Loading branch information
Thumimku committed Apr 26, 2024
1 parent 3a8948e commit 7fd261f
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ public static SubjectType fromValue(String text) {
public static final String CODE_TOKEN = "code token";
public static final String CODE_IDTOKEN = "code id_token";
public static final String CODE_IDTOKEN_TOKEN = "code id_token token";
public static final String SUBJECT_TOKEN = "subject_token";
public static final String IMPERSONATED_SUBJECT = "IMPERSONATED_SUBJECT";
public static final String IMPERSONATING_ACTOR = "IMPERSONATING_ACTOR";
public static final String IDTOKEN_TOKEN = "id_token token";
public static final String SCOPE = "scope";

Expand Down Expand Up @@ -351,6 +354,7 @@ public static class OAuth20Params {
public static final String RESPONSE_TYPE = "response_type";
public static final String RESPONSE_MODE = "response_mode";
public static final String REQUEST = "request";
public static final String REQUESTED_SUBJECT = "requested_subject";

private OAuth20Params() {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. 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.wso2.carbon.identity.oauth.common;

import org.apache.commons.lang.StringUtils;
import org.apache.oltu.oauth2.as.validator.TokenValidator;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;

import javax.servlet.http.HttpServletRequest;

import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OAuth20Params.REQUESTED_SUBJECT;

/**
* This class implements a validator for custom response type "subject_token".
* It extends the TokenValidator class and provides methods to validate the HTTP method and required parameters
* in the subject_token response.
*/
public class SubjectTokenResponseValidator extends TokenValidator {

/**
* Validates the HTTP method used in the request.
* Only GET and POST methods are allowed for subject_token response.
*
* @param request The HttpServletRequest object representing the incoming request.
* @throws OAuthProblemException If the HTTP method is not GET or POST.
*/
@Override
public void validateMethod(HttpServletRequest request) throws OAuthProblemException {

String method = request.getMethod();
if (!OAuth.HttpMethod.GET.equals(method) && !OAuth.HttpMethod.POST.equals(method)) {
throw OAuthProblemException.error(OAuthError.CodeResponse.INVALID_REQUEST)
.description("Http Method is not correct.");
}
}

/**
* Validates the required parameters for the subject_token response type.
* The 'requested_subject' parameter should contain a valid string.
*
* @param request The HttpServletRequest object representing the incoming request.
* @throws OAuthProblemException If the 'requested_subject' parameter is missing or blank.
*/
public void validateRequiredParameters(HttpServletRequest request) throws OAuthProblemException {

super.validateRequiredParameters(request);

// for subject_token response type, the requested_subject parameter should contain valid string.
String requested_subject = request.getParameter(REQUESTED_SUBJECT);
if (StringUtils.isBlank(requested_subject)) {
throw OAuthProblemException.error(OAuthError.TokenResponse.INVALID_REQUEST)
.description("response_type is subject_token. " +
"but requested_subject parameter not found.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. 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.wso2.carbon.identity.oauth.common;

import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OAuth20Params.CLIENT_ID;
import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OAuth20Params.REQUESTED_SUBJECT;

/**
* Test class for Subject Token Response Validator.
*/
public class SubjectTokenResponseValidatorTest {

protected SubjectTokenResponseValidator testedResponseValidator;
private static final String SUBJECT_ID = "8122e3de-0f3b-4b0e-a43a-d0c237451b7a";

@BeforeTest
public void setUp() throws Exception {

testedResponseValidator = new SubjectTokenResponseValidator();
}

@DataProvider(name = "Request Param Provider")
public Object[][] getRequestParams() {

Map<String, String> validSubjectMap = new HashMap<>();
validSubjectMap.put(REQUESTED_SUBJECT, SUBJECT_ID);
Map<String, String> blankSubjectMap = new HashMap<>();
blankSubjectMap.put(REQUESTED_SUBJECT, "");
Map<String, String> emptySubjectMap = new HashMap<>();
return new Object[][]{
{validSubjectMap, true},
{blankSubjectMap, false},
{emptySubjectMap, false},
};
}

@Test(dataProvider = "Request Param Provider")
public void testValidateRequiredParameters(Map<String, String> headerMap, boolean shouldPass) throws Exception {

HttpServletRequest mockRequest = mock(HttpServletRequest.class);
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
when(mockRequest.getParameter(entry.getKey())).thenReturn(entry.getValue());
}
when(mockRequest.getParameter("response_type")).thenReturn(getResponseTypeValue());
when(mockRequest.getParameter(CLIENT_ID)).thenReturn(CLIENT_ID);
when(mockRequest.getParameter("redirect_uri")).thenReturn("www.oidc.test.com");
if (shouldPass) {
testedResponseValidator.validateRequiredParameters(mockRequest);
// Nothing to assert here. The above method will only throw an exception if not valid
} else {
try {
testedResponseValidator.validateRequiredParameters(mockRequest);
fail("Request validation should have failed");
} catch (OAuthProblemException e) {
assertTrue(e.getMessage().startsWith(OAuthError.TokenResponse.INVALID_REQUEST), "Invalid error " +
"message received");
}
}
}

@DataProvider(name = "Request Method Provider")
public Object[][] getRequestMethod() {

return new Object[][]{
{"GET", true},
{"POST", true},
{"HEAD", false},
{"DELETE", false},
{"OPTIONS", false},
{"PUT", false},
{"", false},
{null, false}
};
}

@Test(dataProvider = "Request Method Provider")
public void testValidateMethod(String method, boolean shouldPass) throws Exception {

HttpServletRequest mockRequest = mock(HttpServletRequest.class);
when(mockRequest.getMethod()).thenReturn(method);
if (shouldPass) {
testedResponseValidator.validateMethod(mockRequest);
// Nothing to assert here. The above method will only throw an exception if not valid
} else {
try {
testedResponseValidator.validateMethod(mockRequest);
fail("Request validation should have failed");
} catch (OAuthProblemException e) {
assertTrue(e.getMessage().startsWith(OAuthError.TokenResponse.INVALID_REQUEST), "Invalid error " +
"message received. Received was: " + e.getMessage());
}
}
}

/**
* Method returns the response type associated with the class.
*
* @return response_type
*/
protected String getResponseTypeValue() {

return "subject_token";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

<test name="oauth-common-test">
<classes>
<class name="org.wso2.carbon.identity.oauth.common.SubjectTokenResponseValidatorTest"/>
<class name="org.wso2.carbon.identity.oauth.common.IDTokenResponseValidatorTest"/>
<class name="org.wso2.carbon.identity.oauth.common.CodeTokenResponseValidatorTest"/>
<class name="org.wso2.carbon.identity.oauth.common.NTLMAuthenticationValidatorTest"/>
Expand Down

0 comments on commit 7fd261f

Please sign in to comment.