Requesting the user to enter a security question#
The``PipeSecQuestion`` procedure checks whether the user has a security question. If the question is not asked, the procedure prompts the user to enter it.
The following modifications must be made to the procedure before use:
in the
DOMAIN
constant, specify theURI
at which Blitz Identity Provider is accessible from the user’s browser;in the``CAN_SKIP`` constant, specify the display mode:
true
– the user can skip filling;false
– the user must set the value of the security question to complete authentication.
public class PipeSecQuestion implements Strategy {
private final Logger logger = LoggerFactory.getLogger("com.identityblitz.idp.flow.dynamic");
private final static String DOMAIN = "example.com";
private final static Boolean CAN_SKIP = true;
@Override public StrategyBeginState begin(final Context ctx) {
if ("login".equals(ctx.prompt())){
List<String> methods = new ArrayList<String>(Arrays.asList(ctx.availableMethods()));
methods.remove("cls");
return StrategyState.MORE(methods.toArray(new String[0]), true);
} else {
if(ctx.claims("subjectId") != null)
return StrategyState.ENOUGH();
else
return StrategyState.MORE(new String[]{});
}
}
@Override public StrategyState next(final Context ctx) {
Integer reqFactor = (ctx.user() == null) ? null : ctx.user().requiredFactor();
if (reqFactor == null || reqFactor.equals(ctx.justCompletedFactor())){
if(requireAddSecQsn(ctx)) return addSecQsn(ctx);
else return StrategyState.ENOUGH();
}
else return StrategyState.MORE(new String[]{});
}
private Boolean requireAddSecQsn(final Context ctx) {
String secQsn = (ctx.user() == null) ? null : ctx.user().securityQuestion();
Long agreedOn = (ctx.user() == null) ? null : ctx.user().userProps().numProp("pipes.addSecQsn.agreedOn");
Long disagreedOn = (ctx.user() == null) ? null : ctx.user().userProps().numProp("pipes.addSecQsn.disagreedOn");
if (secQsn != null) return false;
else if (disagreedOn == null) return true;
else {
long now = Instant.now().getEpochSecond();
return ((now - disagreedOn) > 1);
}
}
private StrategyState addSecQsn(final Context ctx) {
String uri = "https://"+DOMAIN+"/blitz/pipes/secQsn/start?canSkip="+CAN_SKIP+"&appId=_blitz_profile";
Set<String> claims = new HashSet<String>(){{
add("instanceId");
}};
Set<String> scopes = new HashSet<String>(){{
add("openid");
}};
return StrategyState.ENOUGH_BUILDER()
.withPipe(uri, "_blitz_profile", scopes, claims)
.build();
}
}