Skip to content

Commit

Permalink
feat(jans-auth-server): allow return of custom authz endpoint request…
Browse files Browse the repository at this point in the history
… parameters to rp in response
  • Loading branch information
qbert2k committed Feb 3, 2022
1 parent 4e0ea4a commit 8bbd659
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@

package io.jans.as.client.ws.rs;

import io.jans.as.client.AuthorizationRequest;
import io.jans.as.client.AuthorizationResponse;
import io.jans.as.client.AuthorizeClient;
import io.jans.as.client.BaseTest;
import io.jans.as.client.RegisterClient;
import io.jans.as.client.RegisterRequest;
import io.jans.as.client.RegisterResponse;
import io.jans.as.client.*;
import io.jans.as.model.common.Prompt;
import io.jans.as.model.common.ResponseType;
import io.jans.as.model.register.ApplicationType;
Expand All @@ -21,19 +15,13 @@
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.*;

/**
* @author Javier Rojas Blum
* @version December 26, 2016
* @version February 2, 2022
*/
public class AuthorizationResponseCustomHeaderTest extends BaseTest {

Expand Down Expand Up @@ -93,6 +81,9 @@ public void requestAuthorizationCustomHeader(
assertTrue(authorizationResponse.getHeaders().containsKey("CustomHeader1"));
assertTrue(authorizationResponse.getHeaders().containsKey("CustomHeader2"));
assertTrue(authorizationResponse.getHeaders().containsKey("CustomHeader3"));
assertTrue(authorizationResponse.getHeaders().get("CustomHeader1").contains("custom_header_value_1"));
assertTrue(authorizationResponse.getHeaders().get("CustomHeader2").contains("custom_header_value_2"));
assertTrue(authorizationResponse.getHeaders().get("CustomHeader3").contains("custom_header_value_3"));
}

@DataProvider(name = "requestAuthorizationCustomHeaderDataProvider")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@
import java.util.List;
import java.util.UUID;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.*;

/**
* @author Javier Rojas Blum
* @version November 23, 2017
* @version February 2, 2022
*/
public class AuthorizationSupportCustomParams extends BaseTest {

Expand Down Expand Up @@ -68,9 +67,11 @@ public void authorizationSupportCustomParams(

AuthorizationRequest authorizationRequest = new AuthorizationRequest(responseTypes, clientId, scopes, redirectUri, nonce);
authorizationRequest.setState(state);
authorizationRequest.addCustomParameter("customParam1", "value1");
authorizationRequest.addCustomParameter("customParam2", "value2");
authorizationRequest.addCustomParameter("customParam3", "value3");
authorizationRequest.addCustomParameter("customParam1", "value1"); // returnInResponse = false
authorizationRequest.addCustomParameter("customParam2", "value2"); // returnInResponse = false
authorizationRequest.addCustomParameter("customParam3", "value3"); // returnInResponse = false
authorizationRequest.addCustomParameter("customParam4", "value4"); // returnInResponse = true
authorizationRequest.addCustomParameter("customParam5", "value5"); // returnInResponse = true

AuthorizeClient authorizeClient = new AuthorizeClient(authorizationEndpoint);
authorizeClient.setRequest(authorizationRequest);
Expand All @@ -84,6 +85,15 @@ public void authorizationSupportCustomParams(
assertNotNull(authorizationResponse.getIdToken(), "The idToken is null");
assertNotNull(authorizationResponse.getState(), "The state is null");

assertNotNull(authorizationResponse.getCustomParams());
assertFalse(authorizationResponse.getCustomParams().containsKey("customParam1"));
assertFalse(authorizationResponse.getCustomParams().containsKey("customParam2"));
assertFalse(authorizationResponse.getCustomParams().containsKey("customParam3"));
assertTrue(authorizationResponse.getCustomParams().containsKey("customParam4"));
assertTrue(authorizationResponse.getCustomParams().containsKey("customParam5"));
assertEquals(authorizationResponse.getCustomParams().get("customParam4"), "value4");
assertEquals(authorizationResponse.getCustomParams().get("customParam5"), "value5");

// NOTE: After complete successfully this test, check whether the stored session in LDAP has the 3 custom params
// stored in its session attributes list.
}
Expand Down
6 changes: 6 additions & 0 deletions jans-auth-server/client/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@
</classes>
</test>

<test name="Authorization Support Custom Params" enabled="true">
<classes>
<class name="io.jans.as.client.ws.rs.AuthorizationSupportCustomParams"></class>
</classes>
</test>

<!-- Authorize test -->
<test name="Authorize test (HTTP)" enabled="true">
<classes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @author Javier Rojas Blum
* @author Yuriy Zabrovarnyy
* @author Yuriy Movchan
* @version September 30, 2021
* @version February 2, 2022
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class AppConfiguration implements Configuration {
Expand Down Expand Up @@ -239,7 +239,7 @@ public class AppConfiguration implements Configuration {
private Boolean logClientIdOnClientAuthentication;
private Boolean logClientNameOnClientAuthentication;
private Boolean disableJdkLogger = true;
private Set<String> authorizationRequestCustomAllowedParameters;
private Set<AuthorizationRequestCustomParameter> authorizationRequestCustomAllowedParameters;
private Boolean openidScopeBackwardCompatibility = false;
private Boolean disableU2fEndpoint = false;

Expand Down Expand Up @@ -2019,11 +2019,11 @@ public void setExternalLoggerConfiguration(String externalLoggerConfiguration) {
this.externalLoggerConfiguration = externalLoggerConfiguration;
}

public Set<String> getAuthorizationRequestCustomAllowedParameters() {
public Set<AuthorizationRequestCustomParameter> getAuthorizationRequestCustomAllowedParameters() {
return authorizationRequestCustomAllowedParameters;
}

public void setAuthorizationRequestCustomAllowedParameters(Set<String> authorizationRequestCustomAllowedParameters) {
public void setAuthorizationRequestCustomAllowedParameters(Set<AuthorizationRequestCustomParameter> authorizationRequestCustomAllowedParameters) {
this.authorizationRequestCustomAllowedParameters = authorizationRequestCustomAllowedParameters;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text.
*
* Copyright (c) 2020, Janssen Project
*/

package io.jans.as.model.configuration;

import io.jans.util.exception.ConfigurationException;
import org.apache.commons.lang.StringUtils;

/**
* @author Javier Rojas Blum
* @version February 2, 2022
*/
public class AuthorizationRequestCustomParameter {

private String paramName;
private Boolean returnInResponse;

private static final Boolean DEFAULT_RETURN_IN_RESPONSE = false;

public String getParamName() {
if (StringUtils.isEmpty(paramName)) {
throw new ConfigurationException("The param name in a AuthorizationRequestCustomParameter is empty");
}
return paramName;
}

public void setParamName(String paramName) {
this.paramName = paramName;
}

public Boolean getReturnInResponse() {
if (returnInResponse == null) {
returnInResponse = DEFAULT_RETURN_IN_RESPONSE;
}
return returnInResponse;
}

public void setReturnInResponse(Boolean returnInResponse) {
this.returnInResponse = returnInResponse;
}
}
23 changes: 20 additions & 3 deletions jans-auth-server/server/conf/jans-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,26 @@
"logClientIdOnClientAuthentication": true,
"logClientNameOnClientAuthentication": false,
"authorizationRequestCustomAllowedParameters" : [
"customParam1",
"customParam2",
"customParam3"
{
"paramName": "customParam1",
"returnInResponse": false
},
{
"paramName": "customParam2",
"returnInResponse": false
},
{
"paramName": "customParam3",
"returnInResponse": false
},
{
"paramName": "customParam4",
"returnInResponse": true
},
{
"paramName": "customParam5",
"returnInResponse": true
}
],
"legacyDynamicRegistrationScopeParam": false,
"openidScopeBackwardCompatibility": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import io.jans.as.model.jwk.JSONWebKeySet;
import io.jans.as.model.jwk.Use;
import io.jans.as.model.jwt.Jwt;
import io.jans.as.model.jwt.JwtClaims;
import io.jans.as.model.jwt.JwtClaimName;
import io.jans.as.model.jwt.JwtClaims;
import io.jans.as.model.token.JsonWebResponse;
import io.jans.as.model.util.JwtUtil;
import io.jans.as.model.util.Util;
Expand Down Expand Up @@ -66,7 +66,6 @@
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;
import org.slf4j.Logger;

Expand Down Expand Up @@ -95,7 +94,7 @@
* Implementation for request authorization through REST web services.
*
* @author Javier Rojas Blum
* @version January 24, 2022
* @version February 2, 2022
*/
@Path("/")
public class AuthorizeRestWebServiceImpl implements AuthorizeRestWebService {
Expand Down Expand Up @@ -708,6 +707,10 @@ private Response requestAuthorization(
redirectUriResponse.getRedirectUri().addResponseParameter(AuthorizeResponseParam.ACR_VALUES, acrValuesStr);
}

for (Map.Entry<String, String> customParam : requestParameterService.getCustomParameters(customParameters, true).entrySet()) {
redirectUriResponse.getRedirectUri().addResponseParameter(customParam.getKey(), customParam.getValue());
}

if (sessionUser.getId() == null) {
final SessionId newSessionUser = sessionIdService.generateAuthenticatedSessionId(httpRequest, sessionUser.getUserDn(), prompt);
String newSessionId = newSessionUser.getId();
Expand Down Expand Up @@ -781,7 +784,6 @@ private Response requestAuthorization(
return builder.build();
}

@Nullable
private ResponseMode extractResponseMode(String request) {
final Jwt jwt = Jwt.parseSilently(request);
if (jwt == null) {
Expand All @@ -799,6 +801,7 @@ private void fillRedirectUriResponseforJARM(RedirectUriResponse redirectUriRespo
redirectUriResponse.getRedirectUri().setBaseRedirectUri(URLDecoder.decode(tempRedirectUri, "UTF-8"));
}
}
redirectUriResponse.getRedirectUri().setResponseMode(ResponseMode.JWT);
String clientId = client.getClientId();
redirectUriResponse.getRedirectUri().setIssuer(appConfiguration.getIssuer());
redirectUriResponse.getRedirectUri().setAudience(clientId);
Expand All @@ -812,7 +815,7 @@ private void fillRedirectUriResponseforJARM(RedirectUriResponse redirectUriRespo
if (client.getAttributes().getAuthorizationEncryptedResponseAlg() != null
&& client.getAttributes().getAuthorizationEncryptedResponseEnc() != null) {
if (client.getAttributes().getAuthorizationSignedResponseAlg() != null) { // Signed then Encrypted
// response
// response
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm
.fromString(client.getAttributes().getAuthorizationSignedResponseAlg());

Expand Down Expand Up @@ -860,7 +863,7 @@ private void fillRedirectUriResponseforJARM(RedirectUriResponse redirectUriRespo
log.error(e.getMessage(), e);
}
}

private void validateJwtRequest(String clientId, String state, HttpServletRequest httpRequest, List<ResponseType> responseTypes, RedirectUriResponse redirectUriResponse, JwtAuthorizationRequest jwtRequest) {
try {
jwtRequest.validate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.google.common.collect.Lists;
import io.jans.as.model.authorize.AuthorizeRequestParam;
import io.jans.as.model.configuration.AppConfiguration;
import io.jans.as.model.configuration.AuthorizationRequestCustomParameter;
import io.jans.as.model.util.Util;
import io.jans.as.server.model.authorize.JwtAuthorizationRequest;
import io.jans.model.security.Identity;
Expand All @@ -23,21 +24,15 @@
import javax.inject.Named;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;

import static org.apache.commons.lang3.BooleanUtils.isTrue;

/**
* @author Yuriy Movchan
* @author Javier Rojas Blum
* @version October 7, 2019
* @version February 2, 2022
*/
@Stateless
@Named
Expand Down Expand Up @@ -85,7 +80,7 @@ private List<String> getAllAllowedParameters() {
}

public Map<String, String> getAllowedParameters(@Nonnull final Map<String, String> requestParameterMap) {
Set<String> authorizationRequestCustomAllowedParameters = appConfiguration.getAuthorizationRequestCustomAllowedParameters();
Set<AuthorizationRequestCustomParameter> authorizationRequestCustomAllowedParameters = appConfiguration.getAuthorizationRequestCustomAllowedParameters();
if (authorizationRequestCustomAllowedParameters == null) {
authorizationRequestCustomAllowedParameters = new HashSet<>(0);
}
Expand All @@ -98,15 +93,21 @@ public Map<String, String> getAllowedParameters(@Nonnull final Map<String, Strin
final List<String> allAllowed = getAllAllowedParameters();
final Set<Map.Entry<String, String>> set = requestParameterMap.entrySet();
for (Map.Entry<String, String> entry : set) {
if (allAllowed.contains(entry.getKey()) || authorizationRequestCustomAllowedParameters.contains(entry.getKey())) {
if (allAllowed.contains(entry.getKey())
|| authorizationRequestCustomAllowedParameters.stream()
.filter(o -> StringUtils.isNotBlank(o.getParamName()) && o.getParamName().equals(entry.getKey())).findFirst().isPresent()) {
result.put(entry.getKey(), entry.getValue());
}
}
return result;
}

public Map<String, String> getCustomParameters(@Nonnull final Map<String, String> requestParameterMap) {
Set<String> authorizationRequestCustomAllowedParameters = appConfiguration.getAuthorizationRequestCustomAllowedParameters();
return getCustomParameters(requestParameterMap, false);
}

public Map<String, String> getCustomParameters(@Nonnull final Map<String, String> requestParameterMap, boolean onlyReturnInResponseParams) {
Set<AuthorizationRequestCustomParameter> authorizationRequestCustomAllowedParameters = appConfiguration.getAuthorizationRequestCustomAllowedParameters();

final Map<String, String> result = new HashMap<>();
if (authorizationRequestCustomAllowedParameters == null) {
Expand All @@ -116,7 +117,15 @@ public Map<String, String> getCustomParameters(@Nonnull final Map<String, String
if (!requestParameterMap.isEmpty()) {
final Set<Map.Entry<String, String>> set = requestParameterMap.entrySet();
for (Map.Entry<String, String> entry : set) {
if (authorizationRequestCustomAllowedParameters.contains(entry.getKey())) {

if (onlyReturnInResponseParams && authorizationRequestCustomAllowedParameters.stream()
.filter(o -> StringUtils.isNotBlank(o.getParamName())
&& o.getParamName().equals(entry.getKey())
&& o.getReturnInResponse()).findFirst().isPresent()) {
result.put(entry.getKey(), entry.getValue());
} else if (!onlyReturnInResponseParams && authorizationRequestCustomAllowedParameters.stream()
.filter(o -> StringUtils.isNotBlank(o.getParamName())
&& o.getParamName().equals(entry.getKey())).findFirst().isPresent()) {
result.put(entry.getKey(), entry.getValue());
}
}
Expand Down Expand Up @@ -213,16 +222,16 @@ public Object getTypedValue(String stringValue, String type) {
* @param customParameters Custom parameters used in the authorization flow.
*/
public void getCustomParameters(JwtAuthorizationRequest jwtRequest, Map<String, String> customParameters) {
Set<String> authorizationRequestCustomAllowedParameters = appConfiguration.getAuthorizationRequestCustomAllowedParameters();
Set<AuthorizationRequestCustomParameter> authorizationRequestCustomAllowedParameters = appConfiguration.getAuthorizationRequestCustomAllowedParameters();

if (authorizationRequestCustomAllowedParameters == null) {
return;
}

JSONObject jsonPayload = jwtRequest.getJsonPayload();
for (String customParam : authorizationRequestCustomAllowedParameters) {
if (jsonPayload.has(customParam)) {
customParameters.put(customParam, jsonPayload.getString(customParam));
for (AuthorizationRequestCustomParameter customParam : authorizationRequestCustomAllowedParameters) {
if (jsonPayload.has(customParam.getParamName())) {
customParameters.put(customParam.getParamName(), jsonPayload.getString(customParam.getParamName()));
}
}
}
Expand Down

1 comment on commit 8bbd659

@qbert2k
Copy link
Contributor Author

@qbert2k qbert2k commented on 8bbd659 Feb 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.