Skip to content

Commit

Permalink
feat(jans-auth-server): authorized acr values (#1068)
Browse files Browse the repository at this point in the history
Signed-off-by: Javier Rojas Blum <javier.rojas.blum@gmail.com>
  • Loading branch information
qbert2k authored Mar 17, 2022
1 parent 833aab1 commit 26e576a
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
*
* @author Javier Rojas Blum
* @author Yuriy Zabrovarnyy
* @version March 2, 2022
* @version March 17, 2022
*/
public class RegisterRequest extends BaseRequest {

Expand Down Expand Up @@ -114,6 +114,7 @@ public class RegisterRequest extends BaseRequest {
private String softwareVersion;
private String softwareStatement;
private Boolean defaultPromptLogin;
private List<String> authorizedAcrValues;
private BackchannelTokenDeliveryMode backchannelTokenDeliveryMode;
private String backchannelClientNotificationEndpoint;
private AsymmetricSignatureAlgorithm backchannelAuthenticationRequestSigningAlg;
Expand Down Expand Up @@ -157,6 +158,7 @@ public RegisterRequest() {
this.scope = new ArrayList<>();
this.claims = new ArrayList<>();
this.customAttributes = new HashMap<>();
this.authorizedAcrValues = new ArrayList<>();
}

/**
Expand Down Expand Up @@ -1171,6 +1173,14 @@ public void setDefaultPromptLogin(Boolean defaultPromptLogin) {
this.defaultPromptLogin = defaultPromptLogin;
}

public List<String> getAuthorizedAcrValues() {
return authorizedAcrValues;
}

public void setAuthorizedAcrValues(List<String> authorizedAcrValues) {
this.authorizedAcrValues = authorizedAcrValues;
}

public String getHttpMethod() {
return httpMethod;
}
Expand Down Expand Up @@ -1396,9 +1406,11 @@ public Map<String, String> getParameters() {
if (defaultPromptLogin != null) {
parameters.put(DEFAULT_PROMPT_LOGIN.getName(), defaultPromptLogin.toString());
}

if (authorizedAcrValues != null && !authorizedAcrValues.isEmpty()) {
parameters.put(AUTHORIZED_ACR_VALUES.getName(), toJSONArray(authorizedAcrValues).toString());
}
if (redirectUrisRegex != null) {
parameters.put(REDIRECT_URIS_REGEX.toString(), redirectUrisRegex.toString()) ;
parameters.put(REDIRECT_URIS_REGEX.toString(), redirectUrisRegex.toString());
}

// Custom params
Expand Down Expand Up @@ -1488,6 +1500,7 @@ public static RegisterRequest fromJson(JSONObject requestObject) throws JSONExce
result.setBackchannelUserCodeParameter(booleanOrNull(requestObject, BACKCHANNEL_USER_CODE_PARAMETER.toString()));
result.setRedirectUrisRegex(requestObject.optString(REDIRECT_URIS_REGEX.toString()));
result.setDefaultPromptLogin(requestObject.optBoolean(DEFAULT_PROMPT_LOGIN.getName()));
result.setAuthorizedAcrValues(extractListByKey(requestObject, AUTHORIZED_ACR_VALUES.getName()));

return result;
}
Expand Down Expand Up @@ -1701,12 +1714,15 @@ public JSONObject getJSONParameters() throws JSONException {
}

if (redirectUrisRegex != null) {
parameters.put(REDIRECT_URIS_REGEX.toString(), redirectUrisRegex) ;
parameters.put(REDIRECT_URIS_REGEX.toString(), redirectUrisRegex);
}

if (defaultPromptLogin != null) {
parameters.put(DEFAULT_PROMPT_LOGIN.getName(), defaultPromptLogin);
}
if (authorizedAcrValues != null && !authorizedAcrValues.isEmpty()) {
parameters.put(AUTHORIZED_ACR_VALUES.toString(), toJSONArray(authorizedAcrValues));
}

// Custom params
if (customAttributes != null && !customAttributes.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* 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.client.ws.rs;

import io.jans.as.client.*;
import io.jans.as.client.client.AssertBuilder;
import io.jans.as.model.common.ResponseType;
import io.jans.as.model.register.ApplicationType;
import io.jans.as.model.util.StringUtils;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
* @author Javier Rojas Blum
* @version March 17, 2022
*/
public class AuthorizedAcrValuesTest extends BaseTest {

@Parameters({"userId", "userSecret", "redirectUris", "redirectUri", "sectorIdentifierUri"})
@Test
public void authorizedAcrValues(
final String userId, final String userSecret, final String redirectUris, final String redirectUri,
final String sectorIdentifierUri) {
showTitle("authorizedAcrValues");

List<ResponseType> responseTypes = Arrays.asList(ResponseType.CODE, ResponseType.ID_TOKEN);

// 1. Register client
RegisterRequest registerRequest = new RegisterRequest(ApplicationType.WEB, "jans test app",
StringUtils.spaceSeparatedToList(redirectUris));
registerRequest.setResponseTypes(responseTypes);
registerRequest.setSectorIdentifierUri(sectorIdentifierUri);
registerRequest.setAuthorizedAcrValues(Arrays.asList(
"acr_1", "acr_2", "acr_3", "basic"
));

RegisterClient registerClient = newRegisterClient(registerRequest);
RegisterResponse registerResponse = registerClient.exec();

showClient(registerClient);
AssertBuilder.registerResponse(registerResponse)
.created()
.check();

String clientId = registerResponse.getClientId();

List<String> scopes = Arrays.asList("openid", "profile", "address", "email");
String state = UUID.randomUUID().toString();
String nonce = UUID.randomUUID().toString();

AuthorizationRequest authorizationRequest = new AuthorizationRequest(responseTypes, clientId, scopes, redirectUri, nonce);
authorizationRequest.setState(state);
authorizationRequest.setAcrValues(Arrays.asList("basic"));

AuthorizationResponse authorizationResponse = authenticateResourceOwnerAndGrantAccess(authorizationEndpoint,
authorizationRequest, userId, userSecret);

AssertBuilder.authorizationResponse(authorizationResponse)
.responseTypes(responseTypes)
.check();
}

@Parameters({"userId", "userSecret", "redirectUris", "redirectUri", "sectorIdentifierUri"})
@Test
public void authorizedAcrValuesFail(
final String userId, final String userSecret, final String redirectUris, final String redirectUri,
final String sectorIdentifierUri) {
showTitle("authorizedAcrValuesFail");

List<ResponseType> responseTypes = Arrays.asList(ResponseType.CODE, ResponseType.ID_TOKEN);

// 1. Register client
RegisterRequest registerRequest = new RegisterRequest(ApplicationType.WEB, "jans test app",
StringUtils.spaceSeparatedToList(redirectUris));
registerRequest.setResponseTypes(responseTypes);
registerRequest.setSectorIdentifierUri(sectorIdentifierUri);
registerRequest.setAuthorizedAcrValues(Arrays.asList(
"acr_1", "acr_2", "acr_3"
));

RegisterClient registerClient = newRegisterClient(registerRequest);
RegisterResponse registerResponse = registerClient.exec();

showClient(registerClient);
AssertBuilder.registerResponse(registerResponse)
.created()
.check();

String clientId = registerResponse.getClientId();

List<String> scopes = Arrays.asList("openid", "profile", "address", "email");
String state = UUID.randomUUID().toString();
String nonce = UUID.randomUUID().toString();

AuthorizationRequest authorizationRequest = new AuthorizationRequest(responseTypes, clientId, scopes, redirectUri, nonce);
authorizationRequest.setState(state);
authorizationRequest.setAcrValues(Arrays.asList("basic"));

AuthorizeClient authorizeClient = new AuthorizeClient(authorizationEndpoint);
authorizeClient.setRequest(authorizationRequest);

AuthorizationResponse authorizationResponse = authorizeClient.exec();

showClient(authorizeClient);
AssertBuilder.authorizationResponse(authorizationResponse)
.status(302)
.check();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
* @author Yuriy Zabrovarnyy
* @author Javier Rojas Blum
* @version March 2, 2022
* @version March 17, 2022
*/

public enum RegisterRequestParam {
Expand Down Expand Up @@ -351,7 +351,9 @@ public enum RegisterRequestParam {

REDIRECT_URIS_REGEX("redirect_uris_regex"),

DEFAULT_PROMPT_LOGIN("default_prompt_login");
DEFAULT_PROMPT_LOGIN("default_prompt_login"),

AUTHORIZED_ACR_VALUES("authorized_acr_values");

/**
* Parameter name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/**
* @author Yuriy Zabrovarnyy
* @author Javier Rojas Blum
* @version March 2, 2022
* @version March 17, 2022
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class ClientAttributes implements Serializable {
Expand Down Expand Up @@ -93,8 +93,11 @@ public class ClientAttributes implements Serializable {
private String publicSubjectIdentifierAttribute;

@JsonProperty("redirectUrisRegex")
private String redirectUrisRegex ;

private String redirectUrisRegex;

@JsonProperty("jansAuthorizedAcr")
private List<String> authorizedAcrValues;

@JsonProperty("jansDefaultPromptLogin")
private Boolean defaultPromptLogin = false;

Expand Down Expand Up @@ -305,7 +308,18 @@ public String getRedirectUrisRegex() {

public void setRedirectUrisRegex(String redirectUrisRegex) {
this.redirectUrisRegex = redirectUrisRegex;
}
}

public List<String> getAuthorizedAcrValues() {
if (authorizedAcrValues == null) {
return Lists.newArrayList();
}
return authorizedAcrValues;
}

public void setAuthorizedAcrValues(List<String> authorizedAcrValues) {
this.authorizedAcrValues = authorizedAcrValues;
}

public Boolean getDefaultPromptLogin() {
if (defaultPromptLogin == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
* Implementation for request authorization through REST web services.
*
* @author Javier Rojas Blum
* @version March 15, 2022
* @version March 17, 2022
*/
@Path("/")
public class AuthorizeRestWebServiceImpl implements AuthorizeRestWebService {
Expand Down Expand Up @@ -313,11 +313,16 @@ private Response requestAuthorization(
Client client = authorizeRestWebServiceValidator.validateClient(clientId, state, isPar);
String deviceAuthzUserCode = deviceAuthorizationService.getUserCodeFromSession(httpRequest);
redirectUri = authorizeRestWebServiceValidator.validateRedirectUri(client, redirectUri, state, deviceAuthzUserCode, httpRequest);
checkAcrChanged(acrValuesStr, prompts, sessionUser); // check after redirect uri is validated

RedirectUriResponse redirectUriResponse = new RedirectUriResponse(new RedirectUri(redirectUri, responseTypes, responseMode), state, httpRequest, errorResponseFactory);
redirectUriResponse.setFapiCompatible(appConfiguration.isFapi());

if (!client.getAttributes().getAuthorizedAcrValues().isEmpty() &&
!client.getAttributes().getAuthorizedAcrValues().containsAll(acrValues)) {
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST,
"Restricted acr value request, please review the list of authorized acr values for this client");
}
checkAcrChanged(acrValuesStr, prompts, sessionUser); // check after redirect uri is validated

Set<String> scopes = scopeChecker.checkScopesPolicy(client, scope);

if (Boolean.TRUE.equals(appConfiguration.getForceSignedRequestObject()) && StringUtils.isBlank(request) && StringUtils.isBlank(requestUri)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
* @author Javier Rojas Blum
* @author Yuriy Zabrovarnyy
* @author Yuriy Movchan
* @version March 2, 2022
* @version March 17, 2022
*/
@Path("/")
public class RegisterRestWebServiceImpl implements RegisterRestWebService {
Expand Down Expand Up @@ -310,7 +310,7 @@ private Response registerClientImpl(String requestParams, HttpServletRequest htt

builder.entity(jsonObjectToString(jsonObject));

log.info("Client registered: clientId = {}, applicationType = {}, clientName = {}, redirectUris = {}, sectorIdentifierUri = {}, redirectUrisRegex = {}" ,
log.info("Client registered: clientId = {}, applicationType = {}, clientName = {}, redirectUris = {}, sectorIdentifierUri = {}, redirectUrisRegex = {}",
client.getClientId(), client.getApplicationType(), client.getClientName(), client.getRedirectUris(), client.getSectorIdentifierUri(), client.getAttributes().getRedirectUrisRegex());

oAuth2AuditLog.setClientId(client.getClientId());
Expand Down Expand Up @@ -853,6 +853,12 @@ private void updateClientFromRequestObject(Client client, RegisterRequest reques
client.getAttributes().setDefaultPromptLogin(requestObject.getDefaultPromptLogin());
}

List<String> authorizedAcrValues = requestObject.getAuthorizedAcrValues();
if (authorizedAcrValues != null && !authorizedAcrValues.isEmpty()) {
authorizedAcrValues = new ArrayList<>(new HashSet<>(authorizedAcrValues)); // Remove repeated elements
client.getAttributes().setAuthorizedAcrValues(authorizedAcrValues);
}

cibaRegisterClientMetadataService.updateClient(client, requestObject.getBackchannelTokenDeliveryMode(),
requestObject.getBackchannelClientNotificationEndpoint(), requestObject.getBackchannelAuthenticationRequestSigningAlg(),
requestObject.getBackchannelUserCodeParameter());
Expand Down

0 comments on commit 26e576a

Please sign in to comment.