Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Scout » ServerAccessControlService is called twice in production code(ServerAccessControlService is called twice)
ServerAccessControlService is called twice in production code [message #1857121] Wed, 18 January 2023 14:09 Go to next message
J D is currently offline J DFriend
Messages: 99
Registered: February 2021
Member
Hi there everyone,

I am a bit confused about how the ServerAccessControlService class works.

I enabled the login screen to test certain features, and I noticed that the ServerAccessControlService class is called twice to retrieve permissions. This is in the Eclipse IDE.

Firstly, with the DevelopmentAccessController before user login and then a second time after user authentication.

Is that normal? Ideally the DevelopmentAccessController should not be active in production code, so how do I disable it in production code?

The console log is shown below:
2023-01-18 13:00:50,056 WARN  [qtp1668016508-19] org.eclipse.scout.rt.server.commons.authentication.DevelopmentAccessController.handle(DevelopmentAccessController.java:66) - +++ Development access control with user jd - MDC[]
2023-01-18 13:00:58,910 WARN  [qtp1668016508-19] org.eclipse.scout.apps.ygapp.server.security.ServerAccessControlService.execLoadPermissions(ServerAccessControlService.java:51) - jd was granted all permissions - MDC[principal=jd, cid=4f5ef05e-d9b6-41d1-b9ad-06a5286323b1]
2023-01-18 13:01:50,232 INFO  [qtp1668016508-19] org.eclipse.scout.rt.dataobject.DataObjectInventory.init(DataObjectInventory.java:109) - Registry initialized, found 71 IDoEntity implementations with @TypeName annotation and 0 implementations with @TypeVersion annotation. - MDC[principal=jd, cid=4f5ef05e-d9b6-41d1-b9ad-06a5286323b1]
2023-01-18 13:01:52,189 INFO  [qtp1668016508-19] org.eclipse.scout.apps.ygapp.server.security.RestAuthenticationService.verify(RestAuthenticationService.java:55) - User Admin with ID 1 logged in successfully. Server message: You successfully connected to the REST server - MDC[principal=jd, cid=4f5ef05e-d9b6-41d1-b9ad-06a5286323b1]
2023-01-18 13:02:15,564 INFO  [qtp1668016508-26] org.eclipse.scout.apps.ygapp.server.ServerSession.execLoadSession(ServerSession.java:44) - created a new session for 1/Admin - MDC[principal=admin, cid=wz8bK5Ek5Xw/1]
2023-01-18 13:02:15,567 INFO  [qtp1668016508-26] org.eclipse.scout.rt.server.AbstractServerSession.start(AbstractServerSession.java:190) - Server session started [session=org.eclipse.scout.apps.ygapp.server.ServerSession@6d94ed47[id = 1lllebrh00b1i6j3ej2hm0qhrq7gqnfk37kmj32cfjhqdfqmamqk], user=admin] - MDC[principal=admin, cid=wz8bK5Ek5Xw/1]
2023-01-18 13:02:43,578 WARN  [qtp1668016508-26] org.eclipse.scout.apps.ygapp.server.security.ServerAccessControlService.execLoadPermissions(ServerAccessControlService.java:51) - admin was granted all permissions - MDC[principal=admin, scoutSession=1lllebrh00b1i6j3ej2hm0qhrq7gqnfk37kmj32cfjhqdfqmamqk, cid=wz8bK5Ek5Xw/1]


My modified UIServletFilter class is
public class UiServletFilter implements Filter {

  private TrivialAccessController m_trivialAccessController;
  private FormBasedAccessController m_formBasedAccessController;
  // private DevelopmentAccessController m_developmentAccessController;

  // private RestAccessController m_restAccessController;

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    m_trivialAccessController = BEANS.get(TrivialAccessController.class)
        .init(new TrivialAuthConfig()
            .withExclusionFilter(filterConfig.getInitParameter("filter-exclude"))
            .withLoginPageInstalled(true));
    m_formBasedAccessController = BEANS.get(FormBasedAccessController.class)
        .init(new FormBasedAuthConfig().withCredentialVerifier(
            BEANS.get(RestCredentialVerifier.class  /* ConfigFileCredentialVerifier.class */)));
    // m_developmentAccessController = BEANS.get(DevelopmentAccessController.class).init();
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    final HttpServletRequest req = (HttpServletRequest) request;
    final HttpServletResponse resp = (HttpServletResponse) response;

    if (m_trivialAccessController.handle(req, resp, chain)) {
      return;
    }

    if (m_formBasedAccessController.handle(req, resp, chain)) {
      return;
    }

    // if (m_developmentAccessController.handle(req, resp, chain)) {
    // return;
    // }

    BEANS.get(ServletFilterHelper.class).forwardToLoginForm(req, resp);
  }

  @Override
  public void destroy() {
    // m_developmentAccessController.destroy();
    m_formBasedAccessController.destroy();
    m_trivialAccessController.destroy();
  }
}


I assumed just commenting out DevelopmentAccessController related code in the UIServletFilter class above was enough.

My unmodified ServerServletFiler class is
public class ServerServletFilter implements Filter {

  private TrivialAccessController m_trivialAccessController;
  private ServiceTunnelAccessTokenAccessController m_tunnelAccessController;
  private DevelopmentAccessController m_developmentAccessController;

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    m_trivialAccessController =
        BEANS.get(TrivialAccessController.class).init(new TrivialAuthConfig()
            .withExclusionFilter(filterConfig.getInitParameter("filter-exclude")));
    m_tunnelAccessController = BEANS.get(ServiceTunnelAccessTokenAccessController.class).init();
    m_developmentAccessController = BEANS.get(DevelopmentAccessController.class).init();
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    final HttpServletRequest req = (HttpServletRequest) request;
    final HttpServletResponse resp = (HttpServletResponse) response;

    if (m_trivialAccessController.handle(req, resp, chain)) {
      return;
    }

    if (m_tunnelAccessController.handle(req, resp, chain)) {
      return;
    }

    if (m_developmentAccessController.handle(req, resp, chain)) {
      return;
    }

    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
  }

  @Override
  public void destroy() {
    // m_developmentAccessController.destroy();
    m_tunnelAccessController.destroy();
    m_trivialAccessController.destroy();
  }
}


Thanks a lot for your assistance.

Cheers,

JD
Re: ServerAccessControlService is called twice in production code [message #1857293 is a reply to message #1857121] Sat, 28 January 2023 17:47 Go to previous messageGo to next message
J D is currently offline J DFriend
Messages: 99
Registered: February 2021
Member
Hi there everyone,

Is there nobody that can help me figure this out?

I just discovered that if I try to login using any other username apart from admin, login fails and I get the following message on the Eclipse IDE console

No UserAgent set on calling context; include default in service-request

2023-01-28 18:17:45,280 WARN  [qtp1624820151-19] org.eclipse.scout.rt.shared.servicetunnel.AbstractServiceTunnel.interceptRequest(AbstractServiceTunnel.java:84) - No UserAgent set on calling context; include default in service-request - MDC[]


My credential verifier is as shown below:

package org.eclipse.scout.apps.ygapp.shared.security;

public class RestCredentialVerifier implements ICredentialVerifier {
  private static final Logger LOG = LoggerFactory.getLogger(RestCredentialVerifier.class);

  @Override
  public int verify(String username, char[] passwordPlainText) throws IOException {
    LOG.debug("Method \"verify\" in RestCredentialVerifier. User " + username);

    // Test for missing username or password
    if (StringUtility.isNullOrEmpty(username) || passwordPlainText == null
        || passwordPlainText.length == 0) {
      throw new VetoException(TEXTS.get("MissingUsernameOrPassword")); 
    }

    // Test for non-conforming password
    // Password MUST have between 8 to 20 characters with a minimum of one uppercase, one lowercase,
    // one number, one special character and without spaces
    if ((passwordPlainText.length < 8) || (passwordPlainText.length > 20)) {
      throw new VetoException(TEXTS.get("ThePasswordMustHaveBetween820Characters"));  
    }

    Subject subject = new Subject();
    subject.getPrincipals().add(new SimplePrincipal("system"));
    subject.setReadOnly();  
   
    RunContext runContext = RunContexts.empty().withLocale(Locale.getDefault()); // OK
    // RunContext runContext = RunContexts.copyCurrent(true).withSubject(subject);  // Fails

    Map<String, String> result = runContext.call(new Callable<Map<String, String>>() {
      @Override
      public Map<String, String> call() throws Exception {
        return BEANS.get(IRestAuthenticationService.class).verify(username, passwordPlainText));
      }
    });

    LOG.debug("Leaving method \"verify\" in RestCredentialVerifier. User " + username);
    if (result.containsKey("message")
        && result.get("message").equals(TEXTS.get("YouAreNowConnectedToTheServer"))) {
      return AUTH_OK;
    } else {
      return AUTH_FAILED;
    }
  }
}


I'm using Scout 22.

Can anyone please help me out? Thanks for your kind assistance.

JD

[Updated on: Sat, 28 January 2023 18:24]

Report message to a moderator

Re: ServerAccessControlService is called twice in production code [message #1857346 is a reply to message #1857293] Wed, 01 February 2023 10:19 Go to previous message
Stephan Merkli is currently offline Stephan MerkliFriend
Messages: 40
Registered: April 2012
Member
Hi JD

DevelopmentAccessController is disabled in production mode, see DevelopmentAccessController#init: withEnabled
Double call of ServerAccessControlService: once for your user (jd), once for a user admin. Seems that you login twice, second time with a different user (and some seconds passed in between).

The message "No UserAgent set on calling context; include default in service-request" is only a warning and shouldn't prevent a login. If login fails, there must be another reason. By default the UserAgent is available via browser and used to detect if mobile, table or desktop mode is preferred (among others).
When working with an own run context (as in your code with RunContext.empty(), there is no UserAgent available which will set a default one instead.

It seems that you require a backend server call from you credential verifier. You might try to annotate IRestAuthenticationService with @RemoteServiceWithoutAuthorization (or at least the called methods) so that there is no need to wrap it in an own run context. But in the backend server implementation you might still need some form of a run context, otherwise you might not be able to run DB calls or something similar. See the Contacts App and the class/usages of SuperUserRunContextProducer. Not completely sure though if this is required/will work, give it a try.

Regards
Stephan
Previous Topic:Scout 22 with Java 19?
Next Topic:Create own bean
Goto Forum:
  


Current Time: Fri Apr 26 12:05:28 GMT 2024

Powered by FUDForum. Page generated in 0.04272 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top