Hi,
I’m trying to implement Application Tiers Scenario to obtain a server side BackOffice (innwork) application and a client mobile oriented PWA (innwork-mobile). But I get an error on login process.
I had follow the Sperating Application Tiers Example and follow the
jmix-separate-tiers-sample.
I had create:
InnworkMobileSecurityConfiguration
RestLoginSupport
package com.company.innworkmobile.security;
import com.vaadin.flow.server.VaadinServletRequest;
import io.jmix.core.security.ClientDetails;
import io.jmix.restds.auth.RestAuthenticationToken;
import io.jmix.security.model.SecurityScope;
import io.jmix.securityflowui.authentication.LoginViewSupport;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import java.util.Locale;
import java.util.TimeZone;
// tag::auth-token[]
@Primary
@Component
public class RestLoginViewSupport extends LoginViewSupport {
@Override
protected Authentication createAuthenticationToken(String username, String password, Locale locale, TimeZone timeZone) {
RestAuthenticationToken authenticationToken = new RestAuthenticationToken(username, password);
// ...
// end::auth-token[]
VaadinServletRequest request = VaadinServletRequest.getCurrent();
ClientDetails clientDetails = ClientDetails.builder()
.locale(locale != null ? locale : getDefaultLocale())
.scope(SecurityScope.UI)
.sessionId(request.getSession().getId())
.timeZone(timeZone == null ? getDeviceTimeZone() : timeZone)
.build();
authenticationToken.setDetails(clientDetails);
// tag::auth-token[]
return authenticationToken;
}
}
RestUserRepository
package com.company.innworkmobile.security;
import com.company.innworkmobile.entity.User;
import io.jmix.restds.auth.AbstractRestUserRepository;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.Collection;
@Primary
@Component("UserRepository")
public class RestUserRepository extends AbstractRestUserRepository<User> {
@Override
protected Class<User> getUserClass() {
return User.class;
}
@Override
protected void initSystemUser(final User systemUser) {
final Collection<GrantedAuthority> authorities = getGrantedAuthoritiesBuilder()
.addResourceRole(FullAccessRole.CODE)
.build();
systemUser.setAuthorities(authorities);
}
@Override
protected void initAnonymousUser(final User anonymousUser) {
}
}
fetch-plans.xml
<fetchPlans xmlns="http://jmix.io/schema/core/fetch-plans">
<fetchPlan class="com.company.innworkmobile.entity.User" name="user" extends="_base">
</fetchPlan>
</fetchPlans>
In my project I’m having this problem:
if I login with a wrong username or password I get right answer (error in login data), but if I login with right user like admin admin I get an error, in particular the problem is in AbstractRestUserRepository.class, row 91 where in the method:
private T loadUser(RestInvoker restInvoker, String username) {
String json = restInvoker.userInfo();
the result of restInvoker is null
The client app has only user entity, this is the configuration:
innwork
spring.security.oauth2.authorizationserver.client.mobile.registration.authorization-grant-types=password,refresh_token
spring.security.oauth2.authorizationserver.client.mobile.registration.client-id=mobile-app
spring.security.oauth2.authorizationserver.client.mobile.registration.client-secret={noop}frontend123
spring.security.oauth2.authorizationserver.client.mobile.registration.client-authentication_methods=client_secret_basic
spring.security.oauth2.authorizationserver.client.mobile.token.access-token-format=reference
spring.security.oauth2.authorizationserver.client.mobile.token.access-token-time-to-live=1h
spring.security.oauth2.authorizationserver.client.mobile.token.refresh-token-time-to-live=24h```
innwork-mobile
jmix.core.additional-stores=innwork
jmix.core.store-descriptor-innwork=restds_RestDataStoreDescriptor
innwork.baseUrl = http://localhost:8080
innwork.clientId = mobile-app
innwork.clientSecret = frontend123
innwork.authenticator = restds_RestPasswordAuthenticator
jmix.restds.authentication-provider-store=innwork
server.port=8090
innwork-mobile User
@Store(name = "innwork")
@JmixEntity(annotatedPropertiesOnly = true)
public class User implements JmixUserDetails, HasTimeZone {
@JmixProperty
@JmixId
@JmixGeneratedValue
private UUID id;
@JmixProperty
@Version
private Integer version;
@JmixProperty
protected String username;
@JmixProperty
@Secret
@SystemLevel
protected String password;
@JmixProperty
protected String firstName;
@JmixProperty
protected String lastName;
@JmixProperty
@Email
protected String email;
@JmixProperty
protected Boolean active = true;
@JmixProperty
protected String timeZoneId;
@JmixProperty
private Integer onboardingStatus;
@Transient
protected Collection<? extends GrantedAuthority> authorities;
public UUID getId() {
return id;
}
public void setId(final UUID id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(final Integer version) {
this.version = version;
}
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public Boolean getActive() {
return active;
}
public void setActive(final Boolean active) {
this.active = active;
}
public void setPassword(final String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(final String email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities != null ? authorities : Collections.emptyList();
}
@Override
public void setAuthorities(final Collection<? extends GrantedAuthority> authorities) {
this.authorities = authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return Boolean.TRUE.equals(active);
}
@InstanceName
@DependsOnProperties({"firstName", "lastName", "username"})
public String getDisplayName() {
return String.format("%s %s [%s]", (firstName != null ? firstName : ""),
(lastName != null ? lastName : ""), username).trim();
}
@Override
public String getTimeZoneId() {
return timeZoneId;
}
public void setTimeZoneId(final String timeZoneId) {
this.timeZoneId = timeZoneId;
}
The Error
java.lang.IllegalArgumentException: argument "content" is null
at com.fasterxml.jackson.databind.ObjectMapper._assertNotNull(ObjectMapper.java:5060)
at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3278)
at io.jmix.restds.auth.AbstractRestUserRepository.loadUser(AbstractRestUserRepository.java:115)
at io.jmix.restds.auth.AbstractRestUserRepository.loadUserByUsername(AbstractRestUserRepository.java:104)
at io.jmix.restds.impl.RestAuthenticationProvider.authenticate(RestAuthenticationProvider.java:44)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182)
at io.jmix.securityflowui.authentication.LoginViewSupport.authenticate(LoginViewSupport.java:204)
at com.company.innworkmobile.view.login.LoginView.onLogin(LoginView.java:90)
at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:239)
at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:488)
at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:298)
at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:473)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:473)
at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:62)
at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:73)
at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:504)
at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$5(ServerRpcHandler.java:485)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:485)
at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:354)
at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:134)
at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:63)
at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1593)
at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:398)
at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:106)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:632)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:408)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:303)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:267)
at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:142)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:178)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:51)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:547)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at io.jmix.core.impl.logging.LogMdcFilter.doFilterInternal(LogMdcFilter.java:28)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108)
at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:365)
at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:145)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:101)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:151)
at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:129)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82)
at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191)
at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113)
at org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$3(HandlerMappingIntrospector.java:195)
at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113)
at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74)
at org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:230)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:384)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.base/java.lang.Thread.run(Thread.java:842)