Unable to invoke @ValidationMethod on the class [class io.fusionauth.app.action.oauth2.CompleteRegistrationAction]



  • Hi there, I'm receiving the following exception when trying to log in using OAuth2 (through the Fusionauth managed login form). For some reason, FusionAuth Prompts the user to complete their registration although the registration was already completed (I did manage to log in once, only after login out and loging in again the problem appeared). I'm using FusionAuth 1.28 from the Docker image. The URL FusionAuth is redirecting me to is:

    /oauth2/complete-registration?client_id=63c1bf74-34d9-4480-8662-61a96722f043&redirect_uri=https%3A%2F%2Flocalhost%3A4343%2Fapi%2Fauth%2Fcallback%2Ffusionauth&response_type=code&scope=offline_access&state=eba8480af10f0ad7c70e74df54d6d25aa60acd85a62556332cd8afb7b351c746&tenantId=f20182e0-7d48-668e-4349-52a0955b0f7f

    The stack trace from STDOUT is:
    fusionauth_1 | 2021-06-08 3:11:22.950 PM ERROR io.fusionauth.app.primeframework.error.ExceptionExceptionHandler - An unhandled exception was thrown fusionauth_1 | org.primeframework.mvc.PrimeException: Unable to invoke @ValidationMethod on the class [class io.fusionauth.app.action.oauth2.CompleteRegistrationAction] fusionauth_1 | at org.primeframework.mvc.validation.DefaultValidationProcessor.validate(DefaultValidationProcessor.java:79) fusionauth_1 | at org.primeframework.mvc.validation.DefaultValidationWorkflow.perform(DefaultValidationWorkflow.java:46) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.security.DefaultSecurityWorkflow.perform(DefaultSecurityWorkflow.java:60) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.parameter.DefaultPostParameterWorkflow.perform(DefaultPostParameterWorkflow.java:50) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.content.DefaultContentWorkflow.perform(DefaultContentWorkflow.java:52) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.parameter.DefaultParameterWorkflow.perform(DefaultParameterWorkflow.java:57) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.parameter.DefaultURIParameterWorkflow.perform(DefaultURIParameterWorkflow.java:102) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.scope.DefaultScopeRetrievalWorkflow.perform(DefaultScopeRetrievalWorkflow.java:58) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.message.DefaultMessageWorkflow.perform(DefaultMessageWorkflow.java:44) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.action.DefaultActionMappingWorkflow.perform(DefaultActionMappingWorkflow.java:126) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.workflow.StaticResourceWorkflow.perform(StaticResourceWorkflow.java:97) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.parameter.RequestBodyWorkflow.perform(RequestBodyWorkflow.java:91) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at org.primeframework.mvc.security.DefaultSavedRequestWorkflow.perform(DefaultSavedRequestWorkflow.java:64) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at io.fusionauth.app.primeframework.CORSFilter.doFilter(CORSFilter.java:262) fusionauth_1 | at io.fusionauth.app.primeframework.CORSRequestWorkflow.perform(CORSRequestWorkflow.java:49) fusionauth_1 | at org.primeframework.mvc.workflow.SubWorkflowChain.continueWorkflow(SubWorkflowChain.java:51) fusionauth_1 | at io.fusionauth.app.primeframework.FusionAuthMVCWorkflow.perform(FusionAuthMVCWorkflow.java:86) fusionauth_1 | at org.primeframework.mvc.workflow.DefaultWorkflowChain.continueWorkflow(DefaultWorkflowChain.java:44) fusionauth_1 | at org.primeframework.mvc.servlet.FilterWorkflowChain.continueWorkflow(FilterWorkflowChain.java:50) fusionauth_1 | at org.primeframework.mvc.servlet.PrimeFilter.doFilter(PrimeFilter.java:78) fusionauth_1 | at com.inversoft.maintenance.servlet.MaintenanceModePrimeFilter.doFilter(MaintenanceModePrimeFilter.java:63) fusionauth_1 | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) fusionauth_1 | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) fusionauth_1 | at com.inversoft.servlet.UTF8Filter.doFilter(UTF8Filter.java:27) fusionauth_1 | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) fusionauth_1 | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) fusionauth_1 | at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) fusionauth_1 | at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) fusionauth_1 | at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:544) fusionauth_1 | at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) fusionauth_1 | at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) fusionauth_1 | at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) fusionauth_1 | at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:353) fusionauth_1 | at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:616) fusionauth_1 | at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) fusionauth_1 | at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831) fusionauth_1 | at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1629) fusionauth_1 | at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) fusionauth_1 | at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) fusionauth_1 | at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) fusionauth_1 | at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) fusionauth_1 | at java.base/java.lang.Thread.run(Thread.java:832) fusionauth_1 | Caused by: org.primeframework.mvc.parameter.el.InvalidExpressionException: The expression string [c6f83-639f-48bc-a9f3-f00e4d783e57']] is invalid. fusionauth_1 | at org.primeframework.mvc.parameter.el.Expression.parse(Expression.java:246) fusionauth_1 | at org.primeframework.mvc.parameter.el.Expression.<init>(Expression.java:56) fusionauth_1 | at org.primeframework.mvc.parameter.el.DefaultExpressionEvaluator.getValue(DefaultExpressionEvaluator.java:95) fusionauth_1 | at io.fusionauth.app.service.user.DefaultRegistrationFrontendService.getValue(DefaultRegistrationFrontendService.java:386) fusionauth_1 | at io.fusionauth.app.service.user.DefaultRegistrationFrontendService.missingRequired(DefaultRegistrationFrontendService.java:439) fusionauth_1 | at io.fusionauth.app.service.user.DefaultRegistrationFrontendService.lambda$registrationComplete$5(DefaultRegistrationFrontendService.java:225) fusionauth_1 | at java.base/java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90) fusionauth_1 | at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) fusionauth_1 | at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) fusionauth_1 | at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) fusionauth_1 | at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) fusionauth_1 | at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1601) fusionauth_1 | at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127) fusionauth_1 | at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502) fusionauth_1 | at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488) fusionauth_1 | at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) fusionauth_1 | at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230) fusionauth_1 | at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196) fusionauth_1 | at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) fusionauth_1 | at java.base/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:528) fusionauth_1 | at io.fusionauth.app.service.user.DefaultRegistrationFrontendService.registrationComplete(DefaultRegistrationFrontendService.java:225) fusionauth_1 | at io.fusionauth.app.action.oauth2.CompleteRegistrationAction.validateGet(CompleteRegistrationAction.java:121) fusionauth_1 | at jdk.internal.reflect.GeneratedMethodAccessor147.invoke(Unknown Source) fusionauth_1 | at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) fusionauth_1 | at java.base/java.lang.reflect.Method.invoke(Method.java:564) fusionauth_1 | at org.primeframework.mvc.util.ReflectionUtils.invoke(ReflectionUtils.java:414) fusionauth_1 | at org.primeframework.mvc.validation.DefaultValidationProcessor.validate(DefaultValidationProcessor.java:77) fusionauth_1 | ... 53 common frames omitted

    I also have one webhook set up for registration verified and email verified events; none of these events where fired when this error occurred (they did fired after I verified the email and completed successfully).

    I also have registration verification turned on at the tenant and application level.



  • Hi @alessandrojcm,

    Thanks for taking the time to post! I don't have an immediate answer, but let's see if we can work on a few troubleshooting steps together.

    I did manage to log in once, only after login out and loging in again the problem appeared

    Do you happen to know the state of the user when this happened? Did they show registered to the application?

    FusionAuth Prompts the user to complete their registration although the registration was already completed

    Similar to above If you query the user, what does that user look like? Do they show a registration prior to relogging in?

    /oauth2/complete-registration?

    Nothing strikes me immediately as abnormal about the content of this redirect URL.

    org.primeframework.mvc.PrimeException: Unable to invoke @ValidationMethod on the class [class io.fusionauth.app.action.oauth2.CompleteRegistrationAction

    This validation error seems telling, informative.

    I also have registration verification turned on at the tenant and application level.

    You mean, you have email verification toggled "on" on the Tenant and verify registration turned on in the application?
    Perhaps more details on what you have enabled and the end goal would be helpful.

    I also have one webhook set up for registration verified and email verified events; none of these events where fired when this error occurred (they did fired after I verified the email and completed it successfully).

    This could be expected behavior but might need more information to be sure.

    Other questions:

    • Is this a one-off or are you able to faithfully recreate this error?
    • If you have recreate steps (ie - set this, do this, unset this) I can try and troubleshoot this locally
    • Have you modified the freemarker templates / theme pages that are provided with the FusionAuth?
    • Are you following any guides or tutorials (FusionAuth or otherwise) when setting up this OAuth workflow?
    • Any other details about what you are trying to accomplish with this app (IE - just register users and have a verification flow?) might be helpful.

    Thanks for the info and let us know.

    Thanks,
    Josh



  • Hi @joshua, thank you very much for your response; to your questions:

    Do you happen to know the state of the user when this happened? Did they show registered to the application?

    Similar to above If you query the user, what does that user look like? Do they show a registration prior to relogging in?

    Yes, the user shows up in the admin panel as registered on the application and verified; the custom metadata that my webhook added to user.data is also present.

    You mean, you have email verification toggled "on" on the Tenant and verify registration turned on in the application?
    Perhaps more details on what you have enabled and the end goal would be helpful.

    Yes, that's correct; I also have the unverified behavior set to gated, but, as I said above, the user is able to verify their account correctly via the email link.

    Is this a one-off or are you able to faithfully recreate this error?

    Just tried registering another user and ended up having the same error.

    Have you modified the freemarker templates / theme pages that are provided with the FusionAuth?

    No, all the themes and templates are the default ones; with the exception of the registration form (customized using the advanced forms feature).

    Are you following any guides or tutorials (FusionAuth or otherwise) when setting up this OAuth workflow?

    The app is using next-auth and the FusionAuth guide to set OAuth2 for web applications.

    Any other details about what you are trying to accomplish with this app (IE - just register users and have a verification flow?) might be helpful.

    Right now just registering new users and login in.

    If you have recreate steps (ie - set this, do this, unset this) I can try and troubleshoot this locally

    Hm, I don't think I'm doing anything special; but this is what I have so far.

    At the tenant level:

    • Set the email verification settings on the tenant to clickable link, and the unverified behavior to gated
    • Set a password policy
    • Turn on user.registration.verified and user.email.verified webhooks

    At the system level:

    • Create a single value consent
    • Create a custom registration form:
      • Username field (user.username)
      • Email (user.email)
      • Password (user.password)
      • Country (This is a select field with 2 string options stored on user.data.country)
      • Terms of use (This is a consent)

    At the application level:

    • Create an application
    • Set generate refresh token
    • Set Authorization Code, Password, and Refresh Token grants
    • Set require registration to on
    • Set the templates for email verification (the default ones in this case)
    • Verification strategy same as tenant (this is probably unnecessary but I did it just to see if it made a difference)
    • Enable self-service registration
    • Set the custom registration form

    After that, just try to sign up and sign in using the normal OAuth2 flow.

    What my webhook does is just create a record in our database and adds that generated id to the user.data object. It also adds those custom fields (country and a boolean flag) to the registration.data object; but as I said above, this metadata shows on the admin UI just fine.

    Many thanks



  • @alessandrojcm

    Thanks for the detailed feedback and steps!

    I was able to recreate this bug/error on my local machine. My preliminary findings - without the consents, everything works as it should. With consents added to the advanced registration form, it fails. We will have to investigate to determine why this is occuring.

    Let me review further - I should have an update soon!

    Tracking this under a bug report - https://github.com/FusionAuth/fusionauth-issues/issues/1255

    Thanks,
    Josh



  • Great @joshua thanks for your help! We can do without the consent for now.



  • @alessandrojcm,

    Sounds good. I have logged a bug report; we should have this one squashed soon!

    Thanks,
    Josh