Skip to main content



      Home
Home » Eclipse Projects » Eclipse Scout » REST API access without login
REST API access without login [message #1868979] Sat, 27 July 2024 05:26 Go to next message
Eclipse UserFriend
I am testing access to Scout application via REST API.
Following the example in the Technical guide I created ExampleResource and ExampleDo.
Calling
localhost:8082/api/example/1
first displays the login dialog (the application uses FormBasedAccessController). After logging in, when I call the url again, I get the correct response (JSON with the content of the specific object).

I would need access via the REST API to not require a login, but normal access to the application does.

Can anyone advise me how to configure this?
Thank you very much.

Scout version: 24.1.15

Edit:
When I call the url from another REST API client, I get this response:
{"error":{"code":10,"message":"The session has expired, please reload the page."}}

[Updated on: Sat, 27 July 2024 05:37] by Moderator

Re: REST API access without login [message #1868997 is a reply to message #1868979] Mon, 29 July 2024 02:30 Go to previous messageGo to next message
Eclipse UserFriend
Hi Miloslav

To exclude /api from authentication, you can add that URL prefix (e.g. "/api/*") to the #getFilterExcludes in your UiServletContributors class. That way requests to /api will not be handled by the FormBasedAccessController but by TrivialAccessController instead.

Additionally, you might want to send a HTTP status code 401 instead a redirect to the login form in UiServletFilter#doFilter at the end. Override UiServletFilter to do that and use you new class in UiAuthFilterContributor#contribute.

Regards
Stephan
Re: REST API access without login [message #1869018 is a reply to message #1868997] Mon, 29 July 2024 08:59 Go to previous messageGo to next message
Eclipse UserFriend
This works fine! Thank you very much.
Re: REST API access without login [message #1869024 is a reply to message #1869018] Mon, 29 July 2024 10:15 Go to previous messageGo to next message
Eclipse UserFriend
Stephan, thanks,

but if I try to call the service from the server, it gives me an error:
java.lang.NullPointerException: Cannot invoke "org.eclipse.scout.rt.platform.context.RunContext.copy()" because the return value of "java.lang.ThreadLocal.get()" is null

Can you still advise me how to include context in the REST API call and call server services?

Thank you.
Re: REST API access without login [message #1869027 is a reply to message #1869024] Mon, 29 July 2024 11:12 Go to previous messageGo to next message
Eclipse UserFriend
As compared to a regular interaction by the user, the code within the UI server in your REST resource doesn't run within a run context. To call a backend server via service tunnel, you need to run within a run context. See Docs: RunContext for one possible solution (might require @RemoteServiceWithoutAuthorization as described below too).

Another way to do that is create a run context manually (with a technical subject) and make sure to use the annotation @RemoteServiceWithoutAuthorization on all service methods called from that run context (because otherwise the backend server will not allow the call). Just make sure that you're aware what you expose without authorization.

RunContext runContext = ClientRunContexts.empty()
        .withSubject("technical-user")
        .withUserAgent(UserAgents.createDefault());

runContext.run(...)


Try that and see if it works.

Another approach would be to have all REST resources in the backend server, use a REST Proxy in the UI server (a subclass of AbstractRestProxyRequestHandler) and run the code in your REST resource within a superuser run context (or use ServerRunContextFilter as an additional filter for /api/*) within ServerServletContributors.

There are various approaches, check what suits you best.

Regards
Stephan
Re: REST API access without login [message #1869033 is a reply to message #1869027] Mon, 29 July 2024 18:39 Go to previous messageGo to next message
Eclipse UserFriend
Stephan, thank you for your advice.
Looks like I'm comfortable with the second way. But I had to modify your code slightly.
I created a method in RESTUtils class:
	public static RunContext getRunContext() {
		Subject subject = new Subject();
		subject.getPrincipals().add(new BasicUserPrincipal(IRESTService.API_TECHNICAL_USER));
		return ClientRunContexts.empty()
		        .withSubject(subject)  // String argument not accepted here
		        .withUserAgent(UserAgents.createDefault());
	}

and then I use it like this:

	 RESTUtils.getRunContext().run(() -> {
	 	...
	 	...
	 });

That works the way I need it to.

Thank you again.
Re: REST API access without login [message #1870437 is a reply to message #1869027] Wed, 28 August 2024 05:11 Go to previous messageGo to next message
Eclipse UserFriend
Hi, can you show me how to do this? All my resources are in ui.html project, can I have them in server project? Tnx

Stephan Merkli wrote on Mon, 29 July 2024 15:12
As compared to a regular interaction by the user, the code within the UI server in your REST resource doesn't run within a run context. To call a backend server via service tunnel, you need to run within a run context. See Docs: RunContext for one possible solution (might require @RemoteServiceWithoutAuthorization as described below too).

Another way to do that is create a run context manually (with a technical subject) and make sure to use the annotation @RemoteServiceWithoutAuthorization on all service methods called from that run context (because otherwise the backend server will not allow the call). Just make sure that you're aware what you expose without authorization.

RunContext runContext = ClientRunContexts.empty()
        .withSubject("technical-user")
        .withUserAgent(UserAgents.createDefault());

runContext.run(...)


Try that and see if it works.

Another approach would be to have all REST resources in the backend server, use a REST Proxy in the UI server (a subclass of AbstractRestProxyRequestHandler) and run the code in your REST resource within a superuser run context (or use ServerRunContextFilter as an additional filter for /api/*) within ServerServletContributors.

There are various approaches, check what suits you best.

Regards
Stephan

Re: REST API access without login [message #1870740 is a reply to message #1870437] Fri, 06 September 2024 05:31 Go to previous message
Eclipse UserFriend
Some hints on how to have the REST resources in the backend server with a proxy on UI server to forward the requests, based on Technical guide 24 - REST with the necessary modifications.

The example is based on a Scout Classic application with version 24.2.2.


  1. Add the dependencies as stated in Dependency Management to the pom.xml in .server.app
  2. Add the ApiServletContributor to ServerServletContributors as described in REST Resource Registration
  3. Add the REST resource to the module .server module as described in REST Resource Provider. No run context will be available in this example, make sure to run the method body within an own run context if required.
  4. Exclude "/api/*" in UiAuthFilterContributor (#getFilterExcludes). Beware: no authentication will be applied, make sure to add your own one if required.
  5. Add a class RestProxyRequestHandler to .ui.html with the following code:

@Order(4600)
public class RestProxyRequestHandler extends AbstractRestProxyRequestHandler {

  @Override
  protected String getRemoteBaseUrl() {
    return BEANS.get(ServiceTunnelTargetUrlProperty.class).getValue().replace("/process", "");
  }

  @Override
  protected String getLocalContextPathPrefix() {
    return "/api/";
  }

  @Override
  @PostConstruct
  protected void initialize() {
    super.initialize();

    // Remove the cookie headers. The cookie is managed by the server running this proxy, not by the remote server.
    getProxy().withRequestHeaderFilter(new HttpHeaderNameFilter("Cookie"));
    getProxy().withResponseHeaderFilter(new HttpHeaderNameFilter("Set-Cookie"));
  }

  @Override
  protected HttpProxyRequestOptions createHttpProxyRequestOptions(HttpServletRequest req, HttpServletResponse resp) {
    return addSignatureHeader(new HttpProxyRequestOptions());
  }

  protected HttpProxyRequestOptions addSignatureHeader(HttpProxyRequestOptions options) {
    DefaultAuthToken token = BEANS.get(DefaultAuthTokenSigner.class).createDefaultSignedToken(DefaultAuthToken.class);
    if (token != null) {
      options.withCustomRequestHeader(HttpServiceTunnel.TOKEN_AUTH_HTTP_HEADER, token.toString());
    }
    return options;
  }
}


Regards
Stephan
Previous Topic:Too many server sessions
Next Topic:Set form dirty
Goto Forum:
  


Current Time: Thu Jun 12 12:31:18 EDT 2025

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

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

Back to the top