Skip to content

Commit

Permalink
feat(jans-auth-server): allow return custom authz params to rp in res…
Browse files Browse the repository at this point in the history
…ponse (#756)

* feat(jans-auth-server): allow return of custom authz endpoint request parameters to rp in response

* feat(jans-auth-server): allow return of custom authz endpoint request parameters to rp in response
  • Loading branch information
qbert2k authored Feb 3, 2022
1 parent 8c71bd5 commit 0e865fb
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 57 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 @@ -238,7 +238,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 @@ -2010,11 +2010,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
Loading

0 comments on commit 0e865fb

Please sign in to comment.