Skip to content

Commit 95f403f

Browse files
authored
Merge pull request #12745 from ayoho/12409-introspectionRelax
PR for Issue 12409: Add config attributes for OAuth introspection claim requirements
2 parents 15f31e3 + 8381b10 commit 95f403f

File tree

6 files changed

+111
-27
lines changed

6 files changed

+111
-27
lines changed

dev/com.ibm.ws.security.openidconnect.client/resources/OSGI-INF/l10n/metatype.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
###############################################################################
2-
# Copyright (c) 2013 IBM Corporation and others.
2+
# Copyright (c) 2013, 2020 IBM Corporation and others.
33
# All rights reserved. This program and the accompanying materials
44
# are made available under the terms of the Eclipse Public License v1.0
55
# which accompanies this distribution, and is available at
@@ -165,7 +165,7 @@ headerName=Name of the header containing the inbound token
165165
headerName.desc=The name of the header which carries the inbound token in the request.
166166

167167
disableIssChecking=Disable issuer checking
168-
disableIssChecking.desc=Require the issuer claim to be absent when validating the json response for inbound token propagation.
168+
disableIssChecking.desc=Require the issuer claim to be absent when validating the OAuth token introspection response for inbound token propagation.
169169

170170
validationEndpointUrl=Endpoint URL for validation
171171
validationEndpointUrl.desc=The endpoint URL for validating the token inbound propagation. The type of endpoint is decided by the validationMethod.

dev/com.ibm.ws.security.openidconnect.client/resources/OSGI-INF/metatype/metatype.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
3-
Copyright (c) 2013 IBM Corporation and others.
3+
Copyright (c) 2013, 2020 IBM Corporation and others.
44
All rights reserved. This program and the accompanying materials
55
are made available under the terms of the Eclipse Public License v1.0
66
which accompanies this distribution, and is available at
@@ -134,6 +134,8 @@
134134
<AD id="useAccessTokenAsIdToken" name="internal" description="internal use only" required="false" type="Boolean" default="false"/>
135135
<AD id="tokenReuse" name="%tokenReuse" description="%tokenReuse.desc" required="false" type="Boolean" default="false" />
136136
<AD id="forwardLoginParameter" name="%forwardLoginParameter" description="%forwardLoginParameter.desc" required="false" type="String" cardinality="2147483647" />
137+
<AD id="requireExpClaimForIntrospection" name="internal" description="internal use only" required="false" type="Boolean" default="true" />
138+
<AD id="requireIatClaimForIntrospection" name="internal" description="internal use only" required="false" type="Boolean" default="true" />
137139
</OCD>
138140

139141
<Designate factoryPid="com.ibm.ws.security.openidconnect.client.oidcClientConfig">

dev/com.ibm.ws.security.openidconnect.client/src/com/ibm/ws/security/openidconnect/client/AccessTokenAuthenticator.java

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2016 IBM Corporation and others.
2+
* Copyright (c) 2016, 2020 IBM Corporation and others.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -632,8 +632,24 @@ protected boolean validateJsonResponse(JSONObject jobj, OidcClientConfig clientC
632632
return false;
633633
}
634634
// ToDo: check exp, iat
635-
Date currentDate = new Date();
636635

636+
if (!isExpValid(jobj, clientConfig)) {
637+
return false;
638+
}
639+
if (!isIatValid(jobj, clientConfig)) {
640+
return false;
641+
}
642+
if (!isIssuerValid(jobj, clientConfig)) {
643+
return false;
644+
}
645+
646+
// TODO see whether we need client id checking
647+
648+
return true;
649+
}
650+
651+
private boolean isExpValid(JSONObject jobj, OidcClientConfig clientConfig) {
652+
Date currentDate = new Date();
637653
Long exp = 0L;
638654
if (jobj.get("exp") != null && (exp = getLong(jobj.get("exp"))) != null) {
639655
if (tc.isDebugEnabled()) {
@@ -642,13 +658,16 @@ protected boolean validateJsonResponse(JSONObject jobj, OidcClientConfig clientC
642658
if (!verifyExpirationTime(exp, currentDate, clientConfig.getClockSkewInSeconds(), clientConfig)) {
643659
return false;
644660
}
645-
} else {
661+
} else if (clientConfig.requireExpClaimForIntrospection()) {
646662
// required field
647-
logError(clientConfig, "PROPAGATION_TOKEN_MISSING_REQUIRED_CLAIM_ERR", "exp", "iss, iat, exp"); // TODO
648-
// include
649-
// iss?
663+
logError(clientConfig, "PROPAGATION_TOKEN_MISSING_REQUIRED_CLAIM_ERR", "exp", "iss, iat, exp");
650664
return false;
651665
}
666+
return true;
667+
}
668+
669+
private boolean isIatValid(JSONObject jobj, OidcClientConfig clientConfig) {
670+
Date currentDate = new Date();
652671
Long iat = 0L;
653672
if (jobj.get("iat") != null && (iat = getLong(jobj.get("iat"))) != null) {
654673
if (tc.isDebugEnabled()) {
@@ -657,22 +676,16 @@ protected boolean validateJsonResponse(JSONObject jobj, OidcClientConfig clientC
657676
if (!checkIssueatTime(iat, currentDate, clientConfig.getClockSkewInSeconds(), clientConfig)) {
658677
return false;
659678
}
660-
} else {
679+
} else if (clientConfig.requireIatClaimForIntrospection()) {
661680
// required field
662681
logError(clientConfig, "PROPAGATION_TOKEN_MISSING_REQUIRED_CLAIM_ERR", "iat", "iss, iat, exp");
663682
return false;
664683
}
665-
/*
666-
* String issuer = null; String issuerIdentifier = null; if
667-
* (jobj.get("iss") != null) { issuer = (String)jobj.get("iss"); if
668-
* (issuer.isEmpty() || ((issuerIdentifier =
669-
* getIssuerIdentifier(clientConfig)) == null) ||
670-
* !issuer.equals(issuerIdentifier)) { logError(clientConfig,
671-
* "PROPAGATION_TOKEN_ISS_ERROR", issuerIdentifier, issuer); return
672-
* false; } } else { //required field logError(clientConfig,
673-
* "PROPAGATION_TOKEN_MISSING_REQUIRED_CLAIM_ERR", "iss",
674-
* "iss, iat, exp"); return false; }
675-
*/
684+
return true;
685+
}
686+
687+
private boolean isIssuerValid(JSONObject jobj, OidcClientConfig clientConfig) {
688+
Date currentDate = new Date();
676689
if (issuerChecking(jobj, clientConfig)) {
677690
Long nbf = 0L;
678691
if (jobj.get("nbf") != null && (nbf = getLong(jobj.get("nbf"))) != null) {
@@ -686,9 +699,6 @@ protected boolean validateJsonResponse(JSONObject jobj, OidcClientConfig clientC
686699
} else {
687700
return false;
688701
}
689-
690-
// TODO see whether we need client id checking
691-
692702
return true;
693703
}
694704

dev/com.ibm.ws.security.openidconnect.client/src/com/ibm/ws/security/openidconnect/client/internal/OidcClientConfigImpl.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ public class OidcClientConfigImpl implements OidcClientConfig {
156156
public static final String CFG_KEY_DISCOVERY_POLLING_RATE = "discoveryPollingRate";
157157
public static final String CFG_KEY_USE_SYSPROPS_FOR_HTTPCLIENT_CONNECTONS = "useSystemPropertiesForHttpClientConnections";
158158
public static final String CFG_KEY_FORWARD_LOGIN_PARAMETER = "forwardLoginParameter";
159+
public static final String CFG_KEY_REQUIRE_EXP_CLAIM = "requireExpClaimForIntrospection";
160+
public static final String CFG_KEY_REQUIRE_IAT_CLAIM = "requireIatClaimForIntrospection";
159161

160162
public static final String OPDISCOVERY_AUTHZ_EP_URL = "authorization_endpoint";
161163
public static final String OPDISCOVERY_TOKEN_EP_URL = "token_endpoint";
@@ -243,6 +245,8 @@ public class OidcClientConfigImpl implements OidcClientConfig {
243245
private String[] resources;
244246
private boolean useAccessTokenAsIdToken;
245247
private List<String> forwardLoginParameter;
248+
private boolean requireExpClaimForIntrospection = true;
249+
private boolean requireIatClaimForIntrospection = true;
246250

247251
private String oidcClientCookieName;
248252
private boolean authnSessionDisabled;
@@ -507,6 +511,8 @@ private void processConfigProps(Map<String, Object> props) {
507511
useAccessTokenAsIdToken = configUtils.getBooleanConfigAttribute(props, CFG_KEY_USE_ACCESS_TOKEN_AS_ID_TOKEN, useAccessTokenAsIdToken);
508512
tokenReuse = configUtils.getBooleanConfigAttribute(props, CFG_KEY_TOKEN_REUSE, tokenReuse);
509513
forwardLoginParameter = oidcConfigUtils.readAndSanitizeForwardLoginParameter(props, id, CFG_KEY_FORWARD_LOGIN_PARAMETER);
514+
requireExpClaimForIntrospection = configUtils.getBooleanConfigAttribute(props, CFG_KEY_REQUIRE_EXP_CLAIM, requireExpClaimForIntrospection);
515+
requireIatClaimForIntrospection = configUtils.getBooleanConfigAttribute(props, CFG_KEY_REQUIRE_IAT_CLAIM, requireIatClaimForIntrospection);
510516
// TODO - 3Q16: Check the validationEndpointUrl to make sure it is valid
511517
// before continuing to process this config
512518
// checkValidationEndpointUrl();
@@ -1843,4 +1849,14 @@ public HashMap<String, String> getJwkRequestParams() {
18431849
return jwkRequestParamMap;
18441850
}
18451851

1852+
@Override
1853+
public boolean requireExpClaimForIntrospection() {
1854+
return requireExpClaimForIntrospection;
1855+
}
1856+
1857+
@Override
1858+
public boolean requireIatClaimForIntrospection() {
1859+
return requireIatClaimForIntrospection;
1860+
}
1861+
18461862
}

dev/com.ibm.ws.security.openidconnect.client/test/com/ibm/ws/security/openidconnect/client/AccessTokenAuthenticatorTest.java

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -690,12 +690,14 @@ public void testValidateJsonResponse_TimeIsExpired() throws IOException {
690690
}
691691

692692
@Test
693-
public void testValidateJsonResponse_NotExpirationTime() throws IOException {
693+
public void testValidateJsonResponse_noExpirationTime() throws IOException {
694694
final String JSONSTRING = "{\"user\":\"user1\" , \"active\":true}";
695695
JSONObject jobj = JSONObject.parse(JSONSTRING);
696696

697697
mockery.checking(new Expectations() {
698698
{
699+
one(clientConfig).requireExpClaimForIntrospection();
700+
will(returnValue(true));
699701
allowing(clientConfig).getInboundPropagation();
700702
will(returnValue(REQUIRED));
701703
}
@@ -705,6 +707,30 @@ public void testValidateJsonResponse_NotExpirationTime() throws IOException {
705707
assertFalse("Expected to receive a false value but was received: " + isValid, isValid);
706708
}
707709

710+
@Test
711+
public void testValidateJsonResponse_noExpirationTime_doNotRequireExpClaim() throws IOException {
712+
final String JSONSTRING = "{\"user\":\"user1\" , \"active\":true}";
713+
JSONObject jobj = JSONObject.parse(JSONSTRING);
714+
Calendar cal = Calendar.getInstance();
715+
Long currentDate = cal.getTimeInMillis() / 1000;
716+
jobj.put("iat", currentDate);
717+
jobj.put("iss", GOOD_ISSUER);
718+
719+
mockery.checking(new Expectations() {
720+
{
721+
one(clientConfig).requireExpClaimForIntrospection();
722+
will(returnValue(false));
723+
one(clientConfig).disableIssChecking();
724+
will(returnValue(false));
725+
one(clientConfig).getIssuerIdentifier();
726+
will(returnValue(GOOD_ISSUER));
727+
}
728+
});
729+
730+
Boolean isValid = tokenAuth.validateJsonResponse(jobj, clientConfig);
731+
assertTrue("Response should have been considered valid, but was not.", isValid);
732+
}
733+
708734
@Test
709735
public void testValidateJsonResponse_BadIssueAtTime() throws IOException {
710736
Calendar cal = Calendar.getInstance();
@@ -728,7 +754,7 @@ public void testValidateJsonResponse_BadIssueAtTime() throws IOException {
728754
}
729755

730756
@Test
731-
public void testValidateJsonResponse_NotIssueAtTime() throws IOException {
757+
public void testValidateJsonResponse_noIssueAtTime() throws IOException {
732758
Calendar cal = Calendar.getInstance();
733759
Long expTime = cal.getTimeInMillis() / 1000;
734760

@@ -737,6 +763,8 @@ public void testValidateJsonResponse_NotIssueAtTime() throws IOException {
737763

738764
mockery.checking(new Expectations() {
739765
{
766+
one(clientConfig).requireIatClaimForIntrospection();
767+
will(returnValue(true));
740768
allowing(clientConfig).getInboundPropagation();
741769
will(returnValue(REQUIRED));
742770
}
@@ -746,6 +774,30 @@ public void testValidateJsonResponse_NotIssueAtTime() throws IOException {
746774
assertFalse("Expected to receive a false value but was received: " + isValid, isValid);
747775
}
748776

777+
@Test
778+
public void testValidateJsonResponse_noIssueAtTime_doNotRequireIatClaim() throws IOException {
779+
Calendar cal = Calendar.getInstance();
780+
Long expTime = cal.getTimeInMillis() / 1000;
781+
782+
final String JSONSTRING = getJSONObjectString(true, expTime);
783+
JSONObject jobj = JSONObject.parse(JSONSTRING);
784+
jobj.put("iss", GOOD_ISSUER);
785+
786+
mockery.checking(new Expectations() {
787+
{
788+
one(clientConfig).requireIatClaimForIntrospection();
789+
will(returnValue(false));
790+
one(clientConfig).disableIssChecking();
791+
will(returnValue(false));
792+
one(clientConfig).getIssuerIdentifier();
793+
will(returnValue(GOOD_ISSUER));
794+
}
795+
});
796+
797+
Boolean isValid = tokenAuth.validateJsonResponse(jobj, clientConfig);
798+
assertTrue("Response should have been considered valid, but was not.", isValid);
799+
}
800+
749801
@Test
750802
public void testValidateJsonResponse_IncompatibleIssuer() throws IOException {
751803
mockery.checking(new Expectations() {

dev/com.ibm.ws.security.openidconnect.clients.common/src/com/ibm/ws/security/openidconnect/clients/common/OidcClientConfig.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2013, 2018 IBM Corporation and others.
2+
* Copyright (c) 2013, 2020 IBM Corporation and others.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -77,4 +77,8 @@ public interface OidcClientConfig extends ConvergedClientConfig {
7777
@Override
7878
String getRedirectUrlWithJunctionPath(String redirect_url);
7979

80+
public boolean requireExpClaimForIntrospection();
81+
82+
public boolean requireIatClaimForIntrospection();
83+
8084
}

0 commit comments

Comments
 (0)