jaas/src/main/java/com/yubico/jaas/YubikeyLoginModule.java
private List<String> get_tokens(NameCallback nameCb) {
		MultiValuePasswordCallback mv_passCb = new MultiValuePasswordCallback("Enter authentication tokens: ", false);
		List<String> result = new ArrayList<String>();

		try {
			/* Fetch a password using the callbackHandler */
			callbackHandler.handle(new Callback[] { nameCb, mv_passCb });

			for (char[] c : mv_passCb.getSecrets()) {
				String s = new String(c);
				/* Check that OTP is at least 32 chars before we verify it. User might have entered
				 * some other password instead of an OTP, and we don't want to send that, possibly
				 * in clear text, over the network.
				 */
				if (s.length() < 32) {
					log.debug("Skipping token, not a valid YubiKey OTP (too short, {} < 32)", s.length());
				} else {
					result.add(s);
				}
			}
		} catch (UnsupportedCallbackException ex) {
			log.error("Callback type not supported", ex);
		} catch (IOException ex) {
			log.error("CallbackHandler failed", ex);
		}
		
		if (jacc) {
			// This is JACC specific mechanism
			try {
				HttpServletRequest request = (HttpServletRequest) PolicyContext
						.getContext(JACC_ATTR_WEB_REQUEST_KEY);
				String j_otp = request.getParameter(HTTP_REQUEST_ATTR_TOTP);
				
				if (j_otp == null || j_otp.length() < 32) {
					log.debug("Skipping token from j_otp, not a valid YubiKey OTP (too short, {} < 32)", j_otp == null ? 0 : j_otp.length());
				} else {
					result.add(j_otp);
				}
				log.debug("OTP from j_otp token : {}", j_otp);
			} catch (PolicyContextException e) {
				log.debug("No OTP from j_otp token)");
			}
		}

		return result;
	}
private List<String> get_tokens(NameCallback nameCb) {
		MultiValuePasswordCallback mv_passCb = new MultiValuePasswordCallback("Enter authentication tokens: ", false);
		List<String> result = new ArrayList<String>();

		try {
			/* Fetch a password using the callbackHandler */
			callbackHandler.handle(new Callback[] { nameCb, mv_passCb });

			for (char[] c : mv_passCb.getSecrets()) {
				String s = new String(c);
				/* Check that OTP is at least 32 chars before we verify it. User might have entered
				 * some other password instead of an OTP, and we don't want to send that, possibly
				 * in clear text, over the network.
				 */
				if (s.length() < 32) {
					log.debug("Skipping token, not a valid YubiKey OTP (too short, {} < 32)", s.length());
				} else {
					result.add(s);
				}
			}
		} catch (UnsupportedCallbackException ex) {
			log.error("Callback type not supported", ex);
		} catch (IOException ex) {
			log.error("CallbackHandler failed", ex);
		}
		
		if (jacc) {
			// This is JACC specific mechanism
			try {
				HttpServletRequest request = (HttpServletRequest) PolicyContext
						.getContext(JACC_ATTR_WEB_REQUEST_KEY);
				String j_otp = request.getParameter(HTTP_REQUEST_ATTR_TOTP);
				
				if (j_otp == null || j_otp.length() < 32) {
					log.debug("Skipping token from j_otp, not a valid YubiKey OTP (too short, {} < 32)", j_otp == null ? 0 : j_otp.length());
				} else {
					result.add(j_otp);
				}
				log.debug("OTP from j_otp token : {}", j_otp);
			} catch (PolicyContextException e) {
				log.debug("No OTP from j_otp token)");
			}
		}

		return result;
	}
Get username and token(s) from the application, using the
javax.security.auth.callback.CallbackHandler passed to our initialize()
function.

The tokens returned have been identified as plausible YubiKey OTPs.

@param nameCb
@return list of possible YubiKey OTPs