apereo/cas · warning

Device registration is disabled for

Error message

Device registration is disabled for [{}]

What it means

This is a warning logged by OneTimeTokenAccountSaveRegistrationAction.doExecuteInternal when a user attempts to save a new OTP device account while device registration is disabled in the MFA webflow configuration. The action short-circuits and returns the error event instead of registering the device. It is thrown when MultifactorAuthenticationWebflowUtils.isMultifactorDeviceRegistrationEnabled evaluates to false for the current request context.

Solutions

  1. Enable device registration in configuration (set cas.authn.mfa.device-registration-enabled=true or the equivalent feature toggle) if self-registration should be allowed.
  2. If registration should stay disabled, remove/hide the registration link and navigation to the OTP registration flow so users do not reach this action.
  3. Verify the request context/screen overrides (per-service or per-tenant MFA settings) are not unintentionally disabling registration for this user.

Example fix

// before: cas.properties
cas.authn.mfa.device-registration-enabled=false
// after
cas.authn.mfa.device-registration-enabled=true
Defensive patterns

Strategy: validation

Validate before calling

boolean registrationEnabled = casProperties.getAuthn().getMfa().getDeviceRegistrationEnabled();
if (!registrationEnabled) { /* hide registration flow before invoking action */ }

Prevention

When it happens

Trigger: A user hits the OTP registration flow (OneTimeTokenAccountSaveRegistrationAction.execute) while the cas.authn.mfa.core... device-registration-enabled (mfa device registration feature) is disabled in configuration.

Common situations: Deployments that pre-provision devices out-of-band but leave the registration webflow reachable; environment-specific config where registration was disabled for production but users still navigate to the registration URL; stale SSO session landing users in the registration flow after an operator disabled registration.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/5e44174a529f5364. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-otp-mfa-core/src/main/java/org/apereo/cas/otp/web/flow/OneTimeTokenAccountSaveRegistrationAction.java:73

            .validationCode(currentAcct.getValidationCode())
            .scratchCodes(currentAcct.getScratchCodes())
            .name(accountName)
            .tenant(tenantExtractor.extract(requestContext).map(TenantDefinition::getId).orElse(StringUtils.EMPTY))
            .build();
    }

    protected T getCandidateAccountFrom(final RequestContext requestContext) {
        return (T) requestContext.getFlowScope()
            .get(OneTimeTokenAccountCreateRegistrationAction.FLOW_SCOPE_ATTR_ACCOUNT, OneTimeTokenAccount.class);
    }

    @Override
    protected @Nullable Event doExecuteInternal(final RequestContext requestContext) {
        try {
            val currentAcct = getCandidateAccountFrom(requestContext);
            val deviceRegistrationEnabled = MultifactorAuthenticationWebflowUtils.isMultifactorDeviceRegistrationEnabled(requestContext);
            if (!deviceRegistrationEnabled) {
                LOGGER.warn("Device registration is disabled for [{}]", currentAcct.getUsername());
                return getErrorEvent(requestContext);
            }

            if (!isMultipleDeviceRegistrationEnabled(requestContext)
                && repository.count(currentAcct.getUsername()) > 0) {
                LOGGER.warn("Unable to register multiple devices for [{}]", currentAcct.getUsername());
                return getErrorEvent(requestContext);
            }
            val account = (T) buildOneTimeTokenAccount(requestContext);
            if (!validate(account, requestContext)) {
                LOGGER.error("Unable to validate account [{}]", account);
                return getErrorEvent(requestContext);
            }

            val validate = requestContext.getRequestParameters().getBoolean(REQUEST_PARAMETER_VALIDATE);
            if (validate == null || !validate) {
                LOGGER.trace("Storing account [{}]", account);
                MultifactorAuthenticationWebflowUtils.putOneTimeTokenAccount(requestContext, repository.save(account));

View on GitHub (pinned to e7288fc434)