[java-idp-plugin-duo] branch main updated: JDUO-56 - Audit the Duo 'factor' used when authenticating
Phil Smart
philip.smart at jisc.ac.uk
Fri Mar 25 12:31:25 UTC 2022
This is an automated email from the git hooks/post-receive script.
philsmart pushed a commit to branch main
in repository java-idp-plugin-duo.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-duo.git;a=commit;h=1588b9962c704660ac80c0789284f1034bea935c
The following commit(s) were added to refs/heads/main by this push:
new 1588b99 JDUO-56 - Audit the Duo 'factor' used when authenticating
1588b99 is described below
commit 1588b9962c704660ac80c0789284f1034bea935c
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Mar 25 12:30:39 2022 +0000
JDUO-56 - Audit the Duo 'factor' used when authenticating
- Add to factor used to the process log on authn success.
https://shibboleth.atlassian.net/browse/JDUO-56
---
.../idp/plugin/authn/duo/DuoOIDCAuthAPI.java | 6 +
.../impl/ValidateDuoTokenAuthenticationResult.java | 34 +++-
.../plugin/authn/duo/impl/ValidateTokenClaims.java | 1 -
.../authn/duo/impl/AbstractDuoActionTest.java | 209 ++++++++++++++++++++-
.../ValidateDuoTokenAuthenticationResultTest.java | 62 +++++-
5 files changed, 290 insertions(+), 22 deletions(-)
diff --git a/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DuoOIDCAuthAPI.java b/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DuoOIDCAuthAPI.java
index 0448dbd..00e82c6 100644
--- a/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DuoOIDCAuthAPI.java
+++ b/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DuoOIDCAuthAPI.java
@@ -52,6 +52,12 @@ public final class DuoOIDCAuthAPI {
/** The name of the JSON authentication result object.*/
@Nonnull @NotEmpty public static final String DUO_AUTH_RESULT_JSON_OBJECT = "auth_result";
+ /** The name of the JSON authentication context object.*/
+ @Nonnull @NotEmpty public static final String DUO_AUTH_CONTEXT_JSON_OBJECT = "auth_context";
+
+ /** The name of the JSON authentication factor object.*/
+ @Nonnull @NotEmpty public static final String DUO_AUTH_FACTOR_JSON_OBJECT = "factor";
+
/** The name of the JSON result status property.*/
@Nonnull @NotEmpty public static final String DUO_AUTH_RESULT_STATUS_JSON_OBJECT = "status";
diff --git a/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResult.java b/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResult.java
index 2a91e6c..0da17a4 100644
--- a/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResult.java
+++ b/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResult.java
@@ -183,7 +183,8 @@ public class ValidateDuoTokenAuthenticationResult extends AbstractValidationActi
final String authResultStatusMsg = (String)statusMsgObj;
if (DuoOIDCAuthAPI.DUO_AUTH_RESULT_ALLOW.equalsIgnoreCase(authResultStatus)){
- log.info("{} Duo 2FA authentication succeeded for '{}'",getLogPrefix(),duoContext.getUsername());
+ log.info("{} Duo 2FA authentication succeeded for '{}', using second-factor '{}'",
+ getLogPrefix(),duoContext.getUsername(), extractFactor());
//must build authentication before recording success. recordSuccess runs
//the cleanup hook which removes the Duo context and prevents useful operation
//of the contextToPrincipalMappingStrategy.
@@ -211,10 +212,34 @@ public class ValidateDuoTokenAuthenticationResult extends AbstractValidationActi
recordFailure(profileRequestContext);
return;
}
-
-
-
+
+ }
+
+ /**
+ * Extract the second-factor use for authentication. Taken from the auth_context. Will return
+ * {@literal 'unspecified'} if not found.
+ *
+ * @return the second-factor used, or {@literal 'unspecified'} if not found. Should always be found.
+ */
+ @Nonnull private String extractFactor() {
+ String factor = "unspecified";
+ try {
+ final Map<String, Object> authnContextClaimObj =
+ claimsSet.getJSONObjectClaim(DuoOIDCAuthAPI.DUO_AUTH_CONTEXT_JSON_OBJECT);
+
+ if (authnContextClaimObj != null) {
+ final Object factorClaimObj =
+ authnContextClaimObj.get(DuoOIDCAuthAPI.DUO_AUTH_FACTOR_JSON_OBJECT);
+ if (factorClaimObj instanceof String) {
+ factor = (String)factorClaimObj;
+ }
+ }
+ } catch (final ParseException e) {
+ // Do nothing, just return unknown
+ }
+ return factor;
+
}
/** {@inheritDoc} */
@@ -257,6 +282,7 @@ public class ValidateDuoTokenAuthenticationResult extends AbstractValidationActi
public static class DuoOIDCCleanupHook implements Consumer<ProfileRequestContext> {
/** {@inheritDoc} */
+ @Override
public void accept(@Nullable final ProfileRequestContext input) {
if (input != null) {
final AuthenticationContext authnCtx = input.getSubcontext(AuthenticationContext.class);
diff --git a/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateTokenClaims.java b/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateTokenClaims.java
index 0d9614e..0f34834 100644
--- a/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateTokenClaims.java
+++ b/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateTokenClaims.java
@@ -37,7 +37,6 @@ import net.shibboleth.idp.plugin.authn.duo.AbstractDuoAuthenticationAction;
import net.shibboleth.idp.plugin.authn.duo.DuoException;
import net.shibboleth.idp.plugin.authn.duo.context.DuoOIDCAuthenticationContext;
import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
-import net.shibboleth.oidc.jwt.claims.JWTClaimsValidation;
import net.shibboleth.oidc.jwt.claims.JWTValidationException;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
diff --git a/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/AbstractDuoActionTest.java b/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/AbstractDuoActionTest.java
index 0f625f0..0a009e9 100644
--- a/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/AbstractDuoActionTest.java
+++ b/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/AbstractDuoActionTest.java
@@ -139,7 +139,7 @@ public abstract class AbstractDuoActionTest {
}
/**
- * Create a dummy Duo plain (no sig or enc) JWT token with no auth_result.
+ * Create a dummy Duo plain (no sig or enc) JWT token with no factor in the auth_context.
*
* @param authResult the authentication result e.g. allow.
* @param authResultMessage a user friendly result message.
@@ -148,16 +148,83 @@ public abstract class AbstractDuoActionTest {
* @param iat issued at.
* @param authTime the auth time.
* @param apiHost the api host
- * @param factor the duo factor
* @return the duo auth token.
*/
- protected JWT createPlainDummyTokenNoAuthResult(@Nonnull final String authResult,
+ protected JWT createPlainDummyTokenNoAuthFactor(@Nonnull final String authResult,
@Nonnull final String authResultMessage, @Nonnull final String aud,
+ @Nonnull final Instant exp, @Nonnull final Instant iat,
+ @Nonnull final Instant authTime, @Nonnull final String apiHost) {
+
+ final String jwtJson = createJWTJsonWithNoAuthFactor(authResult,authResultMessage,aud,
+ exp, iat, authTime, apiHost);
+
+ try {
+
+ final JWT jwt = new PlainJWT(new PlainHeader().toBase64URL(),
+ new Base64URL(Base64Support.encodeURLSafe(jwtJson.getBytes())));
+ //test the claims exist by calling it
+ jwt.getJWTClaimsSet();
+ return jwt;
+ } catch (final EncodingException | ParseException e) {
+ fail("Error creating the Mock JWT",e);
+ }
+ fail();
+ return null;
+ }
+
+ /**
+ * Create a dummy Duo plain (no sig or enc) JWT token with no auth_result.
+ *
+ * @param aud audience
+ * @param exp expiration time.
+ * @param iat issued at.
+ * @param authTime the auth time.
+ * @param apiHost the api host
+ * @param factor the duo factor
+ * @return the duo auth token.
+ */
+ protected JWT createPlainDummyTokenNoAuthResult(@Nonnull final String aud,
@Nonnull final Instant exp, @Nonnull final Instant iat,
@Nonnull final Instant authTime, @Nonnull final String apiHost,
@Nonnull final String factor) {
- final String jwtJson = createJWTJsonWithNoAuthResult(authResult,authResultMessage,aud,
+ final String jwtJson = createJWTJsonWithNoAuthResult(aud,
+ exp, iat, authTime, apiHost, factor);
+
+ try {
+
+ final JWT jwt = new PlainJWT(new PlainHeader().toBase64URL(),
+ new Base64URL(Base64Support.encodeURLSafe(jwtJson.getBytes())));
+ //test the claims exist by calling it
+ jwt.getJWTClaimsSet();
+ return jwt;
+ } catch (final EncodingException | ParseException e) {
+ fail("Error creating the Mock JWT",e);
+ }
+ fail();
+ return null;
+ }
+
+ /**
+ * Create a dummy Duo plain (no sig or enc) JWT token with no auth_result status claim.
+ *
+ * @param authResultMessage a user friendly result message.
+ * @param aud audience
+ * @param exp expiration time.
+ * @param iat issued at.
+ * @param authTime the auth time.
+ * @param apiHost the api host
+ * @param factor the duo factor
+ * @return the duo auth token.
+ */
+ protected JWT createPlainDummyTokenNoResultStatus(
+ @Nonnull final String authResultMessage,
+ @Nonnull final String aud,
+ @Nonnull final Instant exp, @Nonnull final Instant iat,
+ @Nonnull final Instant authTime, @Nonnull final String apiHost,
+ @Nonnull final String factor) {
+
+ final String jwtJson = createJWTJsonWithNoAuthStatus(authResultMessage, aud,
exp, iat, authTime, apiHost, factor);
try {
@@ -435,7 +502,8 @@ public abstract class AbstractDuoActionTest {
}
/**
- * Create a JWT token in JSON without the auth_result element.
+ * Create a JWT token in JSON using the claims arguments, but without a factor claim
+ * in the auth_context.
*
* @param authResult the authentication result e.g. allow.
* @param authResultMessage a user friendly result message.
@@ -444,11 +512,74 @@ public abstract class AbstractDuoActionTest {
* @param iat issued at.
* @param authTime the auth time.
* @param apiHost the api host.
- * @param factor the factor.
* @return the duo auth token.
*/
- private String createJWTJsonWithNoAuthResult(@Nonnull final String authResult,
+ private String createJWTJsonWithNoAuthFactor(@Nonnull final String authResult,
@Nonnull final String authResultMessage, @Nonnull final String aud,
+ @Nonnull final Instant exp, @Nonnull final Instant iat,
+ @Nonnull final Instant authTime, @Nonnull final String apiHost) {
+ final String jwtJson = "{\n" +
+ " \"iss\": \"https://"+apiHost+"/oauth/v1/token\",\n" +
+ " \"sub\": \"jdoe\",\n" +
+ " \"preferred_username\": \"jdoe\",\n" +
+ " \"aud\": \""+aud+"\",\n" +
+ " \"exp\": "+Math.toIntExact(exp.getEpochSecond()) +",\n" +
+ " \"iat\": "+(double)iat.getEpochSecond()+",\n" +
+ " \"auth_time\": "+authTime.getEpochSecond()+",\n" +
+ " \"auth_result\": {\n" +
+ " \"status_msg\": \""+authResultMessage+"\",\n" +
+ " \"status\": \""+authResult+"\",\n" +
+ " \"result\": \""+authResult+"\"\n" +
+ " },\n" +
+ " \"auth_context\": {\n" +
+ " \"result\": \"success\",\n" +
+ " \"timestamp\": 1599749128,\n" +
+ " \"auth_device\": {\n" +
+ " \"ip\": \"1.1.1.1\",\n" +
+ " \"name\": \"+44 999999\",\n" +
+ " \"location\": {\n" +
+ " \"state\": \"State\",\n" +
+ " \"city\": \"City\",\n" +
+ " \"country\": \"Country\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"txid\": \"1684599c-bb16-4250-af85-904291bfe7cc\",\n" +
+ " \"event_type\": \"authentication\",\n" +
+ " \"reason\": \"user_approved\",\n" +
+ " \"access_device\": {\n" +
+ " \"hostname\": null,\n" +
+ " \"ip\": \"1.1.1.1\",\n" +
+ " \"location\": {\n" +
+ " \"state\": \"State\",\n" +
+ " \"city\": \"City\",\n" +
+ " \"country\": \"Country\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"application\": {\n" +
+ " \"key\": \"DIU6GEFWG5LIUTVV2M3N\",\n" +
+ " \"name\": \"Shibboleth Integration Testing\"\n" +
+ " },\n" +
+ " \"user\": {\n" +
+ " \"key\": \"DUGL8U46QGJSOUJWG59W\",\n" +
+ " \"name\": \"jdoe\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ return jwtJson;
+ }
+
+ /**
+ * Create a JWT token in JSON without the auth_result element.
+ *
+ * @param aud audience
+ * @param exp expiration time.
+ * @param iat issued at.
+ * @param authTime the auth time.
+ * @param apiHost the api host.
+ * @param factor the factor.
+ * @return the duo auth token.
+ */
+ private String createJWTJsonWithNoAuthResult(@Nonnull final String aud,
@Nonnull final Instant exp, @Nonnull final Instant iat,
@Nonnull final Instant authTime, @Nonnull final String apiHost,
@Nonnull final String factor) {
@@ -498,6 +629,70 @@ public abstract class AbstractDuoActionTest {
return jwtJson;
}
+ /**
+ * Create a JWT token in JSON without the auth_result element.
+ *
+ * @param authResultMessage a user friendly result message
+ * @param aud audience
+ * @param exp expiration time.
+ * @param iat issued at.
+ * @param authTime the auth time.
+ * @param apiHost the api host.
+ * @param factor the factor.
+ * @return the duo auth token.
+ */
+ private String createJWTJsonWithNoAuthStatus(@Nonnull final String authResultMessage,
+ @Nonnull final String aud,
+ @Nonnull final Instant exp, @Nonnull final Instant iat,
+ @Nonnull final Instant authTime, @Nonnull final String apiHost,
+ @Nonnull final String factor) {
+ final String jwtJson = "{\n" +
+ " \"iss\": \"https://"+apiHost+"/oauth/v1/token\",\n" +
+ " \"sub\": \"jdoe\",\n" +
+ " \"preferred_username\": \"jdoe\",\n" +
+ " \"iat\": "+(double)iat.getEpochSecond()+",\n" +
+ " \"auth_time\": "+authTime.getEpochSecond()+",\n" +
+ " \"auth_result\": {\n" +
+ " \"status_msg\": \""+authResultMessage+"\"\n" +
+ " },\n" +
+ " \"auth_context\": {\n" +
+ " \"result\": \"success\",\n" +
+ " \"timestamp\": 1599749128,\n" +
+ " \"auth_device\": {\n" +
+ " \"ip\": \"1.1.1.1\",\n" +
+ " \"name\": \"+44 999999\",\n" +
+ " \"location\": {\n" +
+ " \"state\": \"State\",\n" +
+ " \"city\": \"City\",\n" +
+ " \"country\": \"Country\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"txid\": \"1684599c-bb16-4250-af85-904291bfe7cc\",\n" +
+ " \"event_type\": \"authentication\",\n" +
+ " \"reason\": \"user_approved\",\n" +
+ " \"access_device\": {\n" +
+ " \"hostname\": null,\n" +
+ " \"ip\": \"1.1.1.1\",\n" +
+ " \"location\": {\n" +
+ " \"state\": \"State\",\n" +
+ " \"city\": \"City\",\n" +
+ " \"country\": \"Country\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"application\": {\n" +
+ " \"key\": \"DIU6GEFWG5LIUTVV2M3N\",\n" +
+ " \"name\": \"Shibboleth Integration Testing\"\n" +
+ " },\n" +
+ " \"factor\": \""+factor+"\",\n" +
+ " \"user\": {\n" +
+ " \"key\": \"DUGL8U46QGJSOUJWG59W\",\n" +
+ " \"name\": \"jdoe\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ return jwtJson;
+ }
+
/**
* Create a JWT token in JSON using the claims arguments present, but missing the 'aud' and
* 'exp' claims.
diff --git a/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResultTest.java b/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResultTest.java
index a976fea..afc68c6 100644
--- a/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResultTest.java
+++ b/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResultTest.java
@@ -84,7 +84,7 @@ public class ValidateDuoTokenAuthenticationResultTest extends AbstractDuoActionT
}
/**
- * Test successful execution.
+ * Test unsuccessful execution when there is no auth_result claim.
*
* @throws ComponentInitializationException on error.
*/
@@ -93,16 +93,55 @@ public class ValidateDuoTokenAuthenticationResultTest extends AbstractDuoActionT
addDuoContext();
addDuoIntegrationToContext();
addAttemptedFlow("authn/DuoOIDC");
- dc.setAuthToken(createPlainDummyTokenNoAuthResult(DuoOIDCAuthAPI.DUO_AUTH_RESULT_ALLOW,"Login Succesful",CLIENT_ID,
+ dc.setAuthToken(createPlainDummyTokenNoAuthResult(CLIENT_ID,
Instant.now().plus(1,ChronoUnit.MINUTES),Instant.now(), Instant.now(), "api.duosecurity.com", "duo_push"));
dc.setUsername("jdoe");
action.initialize();
final Event event = action.execute(src);
- // success here is a null event
assertEventId(event, AuthnEventIds.AUTHN_EXCEPTION);
}
+ /**
+ * Test unsuccessful execution when there is no auth_result status claim.
+ *
+ * @throws ComponentInitializationException on error.
+ */
+ @Test
+ public void testExecuteNoAuthStatus() throws ComponentInitializationException {
+ addDuoContext();
+ addDuoIntegrationToContext();
+ addAttemptedFlow("authn/DuoOIDC");
+ dc.setAuthToken(createPlainDummyTokenNoResultStatus("Login Succesful", CLIENT_ID,
+ Instant.now().plus(1,ChronoUnit.MINUTES),Instant.now(), Instant.now(), "api.duosecurity.com", "duo_push"));
+ dc.setUsername("jdoe");
+ action.initialize();
+
+ final Event event = action.execute(src);
+ assertEventId(event, AuthnEventIds.AUTHN_EXCEPTION);
+ }
+
+ /**
+ * Test successful execution, but there is no 'factor' to log.
+ *
+ * @throws ComponentInitializationException on error.
+ */
+ @Test
+ public void testExecuteNoAuthContextFactor() throws ComponentInitializationException {
+ addDuoContext();
+ addDuoIntegrationToContext();
+ addAttemptedFlow("authn/DuoOIDC");
+ dc.setAuthToken(createPlainDummyTokenNoAuthFactor(DuoOIDCAuthAPI.DUO_AUTH_RESULT_ALLOW,
+ "Login Succesful", CLIENT_ID,
+ Instant.now().plus(1,ChronoUnit.MINUTES),Instant.now(), Instant.now(), "api.duosecurity.com"));
+ dc.setUsername("jdoe");
+ action.initialize();
+
+ final Event event = action.execute(src);
+ // success here is a null event
+ assertNull(event);
+ }
+
/**
* Test the correct invalid authentication state is signalled when no Duo context is supplied.
*
@@ -133,7 +172,8 @@ public class ValidateDuoTokenAuthenticationResultTest extends AbstractDuoActionT
action.setClassifiedMessages(classifiedMessages);
dc.setAuthToken(createPlainDummyToken(DuoOIDCAuthAPI.DUO_AUTH_RESULT_DENY,"Account locked",CLIENT_ID,
- Instant.now().plus(1,ChronoUnit.MINUTES),Instant.now(), Instant.now(), "api.duosecurity.com", "duo_push"));
+ Instant.now().plus(1,ChronoUnit.MINUTES),Instant.now(), Instant.now(),
+ "api.duosecurity.com", "duo_push"));
dc.setUsername("jdoe");
action.initialize();
@@ -173,7 +213,8 @@ public class ValidateDuoTokenAuthenticationResultTest extends AbstractDuoActionT
addAttemptedFlow("authn/DuoOIDC");
//made up fail message, will terminate on the duo site in reality.
dc.setAuthToken(createPlainDummyToken(DuoOIDCAuthAPI.DUO_AUTH_RESULT_DENY,"Login Failed",CLIENT_ID,
- Instant.now().plus(1,ChronoUnit.MINUTES),Instant.now(), Instant.now(), "api.duosecurity.com", "duo_push"));
+ Instant.now().plus(1,ChronoUnit.MINUTES),Instant.now(), Instant.now(),
+ "api.duosecurity.com", "duo_push"));
dc.setUsername("jdoe");
action.initialize();
@@ -192,16 +233,17 @@ public class ValidateDuoTokenAuthenticationResultTest extends AbstractDuoActionT
addDuoIntegrationToContext();
addAttemptedFlow("authn/DuoOIDC");
dc.setAuthToken(createPlainDummyToken(DuoOIDCAuthAPI.DUO_AUTH_RESULT_ALLOW,"Login Succesful",CLIENT_ID,
- Instant.now().plus(1,ChronoUnit.MINUTES),Instant.now(), Instant.now(), "api.duosecurity.com", "duo_push"));
+ Instant.now().plus(1,ChronoUnit.MINUTES),Instant.now(), Instant.now(),
+ "api.duosecurity.com", "duo_push"));
dc.setUsername("jdoe");
action.setContextToPrincipalMappingStrategy(prc ->{
- DuoOIDCAuthenticationContext duoContext =
+ final DuoOIDCAuthenticationContext duoContext =
prc.getSubcontext(AuthenticationContext.class).getSubcontext(DuoOIDCAuthenticationContext.class);
final List<Principal> p = new ArrayList<>();
try {
- if ("duo_push".equals((String)duoContext.getAuthToken().getJWTClaimsSet()
+ if ("duo_push".equals(duoContext.getAuthToken().getJWTClaimsSet()
.getJSONObjectClaim("auth_context").get("factor"))){
p.add(new AuthnContextClassRefPrincipal("http://example.com/duoPush"));
}
@@ -239,11 +281,11 @@ public class ValidateDuoTokenAuthenticationResultTest extends AbstractDuoActionT
action.setContextToPrincipalMappingStrategy(prc ->{
- DuoOIDCAuthenticationContext duoContext =
+ final DuoOIDCAuthenticationContext duoContext =
prc.getSubcontext(AuthenticationContext.class).getSubcontext(DuoOIDCAuthenticationContext.class);
final List<Principal> p = new ArrayList<>();
try {
- if ("sms".equals((String)duoContext.getAuthToken().getJWTClaimsSet()
+ if ("sms".equals(duoContext.getAuthToken().getJWTClaimsSet()
.getJSONObjectClaim("auth_context").get("factor"))){
p.add(new AuthnContextClassRefPrincipal("http://example.com/sms"));
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list