Skip to content

Commit b0034ec

Browse files
authored
feat(jans-auth-server): specify minimum acr for clients #343 (#3083)
* feat(jans-auth-server): specify minimum acr for clients #343 * feat(jans-auth-server): added minimum acr properties to dynamic registration #343 * doc(jans-auth-server): added docs and updated swagger with new minimum acr related properties #343
1 parent 7c077b9 commit b0034ec

File tree

11 files changed

+469
-15
lines changed

11 files changed

+469
-15
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
tags:
3+
- administration
4+
- client
5+
- configuration
6+
---
7+
8+
# Client Configuration
9+
10+
## ACR client configuration
11+
12+
There are 4 client configuration properties related to ACR:
13+
14+
- `default_acr_values` - string array, default acr values which are set when `acr_values` is missed in authorization request.
15+
- `minimumAcrLevel` - integer value which sets minimum acr level.
16+
- `minimumAcrLevelAutoresolve` - boolean value, if `false` and `minimumAcrLevel` is higher then current `acr_values` then reject request. If `true` - resolve acr according to either client's `minimumAcrPriorityList` or AS `auth_level_mapping`
17+
- `minimumAcrPriorityList` - string array, enables client to specify the acr order of preference, rather then just the next lowest integer value
18+
19+
AS process properties in following order:
20+
1. if `acr_values` is absent, set `acr_values` from `default_acr_values`
21+
2. Otherwise if present, checking minimum acr level:
22+
- check `minimumAcrLevel`, if current acr level is higher or equals to `minimumAcrLevel` then proceed request processing without changes
23+
- if `minimumAcrLevel` is less then current acr level and `minimumAcrLevelAutoresolve=false` -> reject request (return bad request error)
24+
- if `minimumAcrLevel` is less then current acr level and `minimumAcrLevelAutoresolve=true` -> pickup value from `minimumAcrPriorityList` or if it's empty take nearest acr value that satisfy `minimumAcrLevel`
25+
26+
For example, given:
27+
1. `minimumAcrLevel` = 14
28+
1. `default_acr_values` = "basic"
29+
1. `minimumAcrPriorityList` = ["u2f", "passkey", "usb_fido_key", "super_gluu"]
30+
1. OP `auth_level_mapping` :
31+
```
32+
"auth_level_mapping": {
33+
"1": ["basic"],
34+
"5": ["otp"],
35+
"10": ["u2f"],
36+
"11": ["super_gluu"],
37+
"20": ["passkey"],
38+
"30": ["usb_fido_key"]
39+
}
40+
```
41+
42+
- if current `acr_values=u2f` and `minimumAcrLevelAutoresolve=false` -> request is rejected
43+
- if current `acr_values=u2f` and `minimumAcrLevelAutoresolve=true` -> `acr_values` set to `acr_values=passkey` and request continue processing
44+
- if current `acr_values=usb_fido_key` -> current acr is higher then minimum. Thus nothing to do.
45+
46+
If `minimumAcrPriorityList` is missing, then the AS can pick the next highest acr in the `auth_level_mapping`. In the example above, that would be `passkey`.

jans-auth-server/client/src/main/java/io/jans/as/client/RegisterRequest.java

+70
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ public class RegisterRequest extends BaseRequest {
104104
private SignatureAlgorithm tokenEndpointAuthSigningAlg;
105105
private Integer defaultMaxAge;
106106
private List<String> defaultAcrValues;
107+
private Integer minimumAcrLevel;
108+
private Boolean minimumAcrLevelAutoresolve;
109+
private List<String> minimumAcrPriorityList;
107110
private String initiateLoginUri;
108111
private List<String> groups;
109112
private List<String> postLogoutRedirectUris;
@@ -154,6 +157,7 @@ public RegisterRequest() {
154157
this.grantTypes = new ArrayList<>();
155158
this.contacts = new ArrayList<>();
156159
this.defaultAcrValues = new ArrayList<>();
160+
this.minimumAcrPriorityList = new ArrayList<>();
157161
this.postLogoutRedirectUris = new ArrayList<>();
158162
this.groups = new ArrayList<>();
159163
this.requestUris = new ArrayList<>();
@@ -1039,6 +1043,60 @@ public void setDefaultMaxAge(Integer defaultMaxAge) {
10391043
this.defaultMaxAge = defaultMaxAge;
10401044
}
10411045

1046+
/**
1047+
* Gets minimum acr level
1048+
*
1049+
* @return minimum acr level
1050+
*/
1051+
public Integer getMinimumAcrLevel() {
1052+
return minimumAcrLevel;
1053+
}
1054+
1055+
/**
1056+
* Sets minimum acr level
1057+
*
1058+
* @param minimumAcrLevel minimum acr level
1059+
*/
1060+
public void setMinimumAcrLevel(Integer minimumAcrLevel) {
1061+
this.minimumAcrLevel = minimumAcrLevel;
1062+
}
1063+
1064+
/**
1065+
* Gets minimum acr level auto resolve
1066+
*
1067+
* @return minimum acr level auto resolve
1068+
*/
1069+
public Boolean getMinimumAcrLevelAutoresolve() {
1070+
return minimumAcrLevelAutoresolve;
1071+
}
1072+
1073+
/**
1074+
* Sets minimum acr level auto resolve
1075+
*
1076+
* @param minimumAcrLevelAutoresolve minimum acr level auto resolve
1077+
*/
1078+
public void setMinimumAcrLevelAutoresolve(Boolean minimumAcrLevelAutoresolve) {
1079+
this.minimumAcrLevelAutoresolve = minimumAcrLevelAutoresolve;
1080+
}
1081+
1082+
/**
1083+
* Gets minimum acr priority list
1084+
*
1085+
* @return minimum acr priority list
1086+
*/
1087+
public List<String> getMinimumAcrPriorityList() {
1088+
return minimumAcrPriorityList;
1089+
}
1090+
1091+
/**
1092+
* Sets minimum acr priority list
1093+
*
1094+
* @param minimumAcrPriorityList minimum acr priority list
1095+
*/
1096+
public void setMinimumAcrPriorityList(List<String> minimumAcrPriorityList) {
1097+
this.minimumAcrPriorityList = minimumAcrPriorityList;
1098+
}
1099+
10421100
/**
10431101
* Returns the Default requested Authentication Context Class Reference values.
10441102
*
@@ -1379,6 +1437,9 @@ public static RegisterRequest fromJson(JSONObject requestObject) throws JSONExce
13791437
result.setPostLogoutRedirectUris(extractListByKey(requestObject, POST_LOGOUT_REDIRECT_URIS.toString()));
13801438
result.setGroups(extractListByKey(requestObject, GROUPS.toString()));
13811439
result.setDefaultAcrValues(extractListByKey(requestObject, DEFAULT_ACR_VALUES.toString()));
1440+
result.setMinimumAcrLevel(integerOrNull(requestObject, MINIMUM_ACR_LEVEL.toString()));
1441+
result.setMinimumAcrLevelAutoresolve(requestObject.optBoolean(MINIMUM_ACR_LEVEL_AUTORESOLVE.toString()));
1442+
result.setMinimumAcrPriorityList(extractListByKey(requestObject, MINIMUM_ACR_PRIORITY_LIST.toString()));
13821443
result.setFrontChannelLogoutUri(requestObject.optString(FRONT_CHANNEL_LOGOUT_URI.toString()));
13831444
result.setFrontChannelLogoutSessionRequired(requestObject.optBoolean(FRONT_CHANNEL_LOGOUT_SESSION_REQUIRED.toString()));
13841445
result.setBackchannelLogoutUris(extractListByKey(requestObject, BACKCHANNEL_LOGOUT_URI.toString()));
@@ -1588,6 +1649,15 @@ public void getParameters(BiFunction<String, Object, Void> function) {
15881649
if (defaultAcrValues != null && !defaultAcrValues.isEmpty()) {
15891650
function.apply(DEFAULT_ACR_VALUES.toString(), toJSONArray(defaultAcrValues));
15901651
}
1652+
if (minimumAcrLevel != null) {
1653+
function.apply(MINIMUM_ACR_LEVEL.toString(), minimumAcrLevel.toString());
1654+
}
1655+
if (minimumAcrLevelAutoresolve != null) {
1656+
function.apply(MINIMUM_ACR_LEVEL_AUTORESOLVE.toString(), minimumAcrLevelAutoresolve.toString());
1657+
}
1658+
if (minimumAcrPriorityList != null) {
1659+
function.apply(MINIMUM_ACR_PRIORITY_LIST.toString(), toJSONArray(minimumAcrPriorityList));
1660+
}
15911661
if (StringUtils.isNotBlank(initiateLoginUri)) {
15921662
function.apply(INITIATE_LOGIN_URI.toString(), initiateLoginUri);
15931663
}

jans-auth-server/common/src/test/resources/testng.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
22

33
<suite name="oxAuthCommon" parallel="false">
4-
<test name="Audience Test" enabled="true">
4+
<test name="Unit Tests" enabled="true">
55
<classes>
66
<class name="io.jans.as.common.AudienceTest"/>
77
<class name="io.jans.as.common.util.RedirectUriTest"/>
8+
<class name="io.jans.as.common.model.registration.ClientSerializationTest"/>
89
<class name="io.jans.as.common.service.common.UserServiceTest"/>
910
<class name="io.jans.as.common.service.common.InumServiceTest"/>
1011
</classes>

jans-auth-server/docs/swagger.yaml

+37-1
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,18 @@ paths:
12741274
processing requests from the Client.
12751275
items:
12761276
type: string
1277+
minimum_acr_level:
1278+
type: integer
1279+
description: Integer value which sets minimum acr level.
1280+
example: 10
1281+
minimum_acr_level_autoresolve:
1282+
type: boolean
1283+
description: boolean value, if false and minimum_acr_level is higher then current acr_values then reject request. If true - resolve acr according to either client's minimum_acr_priority_list or AS auth_level_mapping
1284+
minimum_acr_priority_list:
1285+
type: array
1286+
description: enables client to specify the acr order of preference, rather then just the next lowest integer value
1287+
items:
1288+
type: string
12771289
groups:
12781290
type: array
12791291
description: Array of client's groups.
@@ -1614,6 +1626,18 @@ paths:
16141626
processing requests from the Client.
16151627
items:
16161628
type: string
1629+
minimum_acr_level:
1630+
type: integer
1631+
description: Integer value which sets minimum acr level.
1632+
example: 10
1633+
minimum_acr_level_autoresolve:
1634+
type: boolean
1635+
description: boolean value, if false and minimum_acr_level is higher then current acr_values then reject request. If true - resolve acr according to either client's minimum_acr_priority_list or AS auth_level_mapping
1636+
minimum_acr_priority_list:
1637+
type: array
1638+
description: enables client to specify the acr order of preference, rather then just the next lowest integer value
1639+
items:
1640+
type: string
16171641
initiate_login_uri:
16181642
type: string
16191643
description: Specifies the URI using the https scheme that the authorization server can call to initiate a login at the client.
@@ -1956,6 +1980,18 @@ paths:
19561980
processing requests from the Client.
19571981
items:
19581982
type: string
1983+
minimum_acr_level:
1984+
type: integer
1985+
description: Integer value which sets minimum acr level.
1986+
example: 10
1987+
minimum_acr_level_autoresolve:
1988+
type: boolean
1989+
description: boolean value, if false and minimum_acr_level is higher then current acr_values then reject request. If true - resolve acr according to either client's minimum_acr_priority_list or AS auth_level_mapping
1990+
minimum_acr_priority_list:
1991+
type: array
1992+
description: enables client to specify the acr order of preference, rather then just the next lowest integer value
1993+
items:
1994+
type: string
19591995
initiate_login_uri:
19601996
type: string
19611997
description: Specifies the URI using the https scheme that the authorization server can call to initiate a login at the client.
@@ -4282,7 +4318,7 @@ paths:
42824318
- SSA
42834319
summary: Create SSA.
42844320
description: Create `SSA` for the organization with `expiration` (optional).
4285-
operationId: post-register
4321+
operationId: post-register-ssa
42864322
security:
42874323
- bearer: [ ]
42884324
requestBody:

jans-auth-server/model/src/main/java/io/jans/as/model/register/RegisterRequestParam.java

+18
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,24 @@ public enum RegisterRequestParam {
226226
*/
227227
DEFAULT_ACR_VALUES("default_acr_values"),
228228

229+
/**
230+
* Integer value which sets minimum acr level.
231+
*/
232+
MINIMUM_ACR_LEVEL("minimum_acr_level"),
233+
234+
/**
235+
* Boolean value,
236+
* - if false and minimumAcrLevel is higher then current acr_values then reject request
237+
* - if true - resolve acr according to either client's minimumAcrPriorityList or AS auth_level_mapping
238+
*/
239+
MINIMUM_ACR_LEVEL_AUTORESOLVE("minimum_acr_level_autoresolve"),
240+
241+
/**
242+
* Array of strings,
243+
* - enables client to specify the acr order of preference, rather then just the next lowest integer value
244+
*/
245+
MINIMUM_ACR_PRIORITY_LIST("minimum_acr_priority_list"),
246+
229247
/**
230248
* URI using the https scheme that the Authorization Server can call to initiate a login at the Client.
231249
*/

jans-auth-server/persistence-model/src/main/java/io/jans/as/persistence/model/ClientAttributes.java

+38
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,41 @@ public class ClientAttributes implements Serializable {
107107
@JsonProperty("allowOfflineAccessWithoutConsent")
108108
private Boolean allowOfflineAccessWithoutConsent;
109109

110+
@JsonProperty("minimumAcrLevel")
111+
private Integer minimumAcrLevel = -1;
112+
113+
@JsonProperty("minimumAcrLevelAutoresolve")
114+
private Boolean minimumAcrLevelAutoresolve;
115+
116+
@JsonProperty("minimumAcrPriorityList")
117+
private List<String> minimumAcrPriorityList;
118+
119+
public Boolean getMinimumAcrLevelAutoresolve() {
120+
return minimumAcrLevelAutoresolve;
121+
}
122+
123+
public void setMinimumAcrLevelAutoresolve(Boolean minimumAcrLevelAutoresolve) {
124+
this.minimumAcrLevelAutoresolve = minimumAcrLevelAutoresolve;
125+
}
126+
127+
public List<String> getMinimumAcrPriorityList() {
128+
if (minimumAcrPriorityList == null) minimumAcrPriorityList = new ArrayList<>();
129+
return minimumAcrPriorityList;
130+
}
131+
132+
public void setMinimumAcrPriorityList(List<String> minimumAcrPriorityList) {
133+
this.minimumAcrPriorityList = minimumAcrPriorityList;
134+
}
135+
136+
public Integer getMinimumAcrLevel() {
137+
if (minimumAcrLevel == null) minimumAcrLevel = -1;
138+
return minimumAcrLevel;
139+
}
140+
141+
public void setMinimumAcrLevel(Integer minimumAcrLevel) {
142+
this.minimumAcrLevel = minimumAcrLevel;
143+
}
144+
110145
public Boolean getAllowOfflineAccessWithoutConsent() {
111146
return allowOfflineAccessWithoutConsent;
112147
}
@@ -378,6 +413,9 @@ public String toString() {
378413
", publicSubjectIdentifierAttribute=" + publicSubjectIdentifierAttribute +
379414
", redirectUrisRegex=" + redirectUrisRegex +
380415
", allowOfflineAccessWithoutConsent=" + allowOfflineAccessWithoutConsent +
416+
", minimumAcrLevel=" + minimumAcrLevel +
417+
", minimumAcrLevelAutoresolve=" + minimumAcrLevelAutoresolve +
418+
", minimumAcrPriorityList=" + minimumAcrPriorityList +
381419
", defaultPromptLogin=" + defaultPromptLogin +
382420
'}';
383421
}

jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthorizeRestWebServiceImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ private ResponseBuilder authorize(AuthzRequest authzRequest) throws AcrChangedEx
331331
authorizeRestWebServiceValidator.validate(authzRequest, responseTypes, client);
332332
authorizeRestWebServiceValidator.validatePkce(authzRequest.getCodeChallenge(), authzRequest.getRedirectUriResponse());
333333

334-
authzRequestService.setDefaultAcrsIfNeeded(authzRequest, client);
334+
authzRequestService.setAcrsIfNeeded(authzRequest);
335335

336336
checkOfflineAccessScopes(responseTypes, prompts, client, scopes);
337337
checkResponseType(authzRequest, responseTypes, client);

0 commit comments

Comments
 (0)