Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Scout » OAuth Authentication
OAuth Authentication [message #1834544] Thu, 12 November 2020 08:08 Go to next message
Mark Ashworth is currently offline Mark AshworthFriend
Messages: 40
Registered: January 2012
Member
Good day,

Does Eclipse Scout support OAuth against an Identity Server like Google?

An if so, is there possibly guidelines or sample code or advise on how to get this to work?

Kind regards,
Mark Ashworth
Re: OAuth Authentication [message #1834597 is a reply to message #1834544] Fri, 13 November 2020 10:30 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 154
Registered: March 2010
Senior Member
There is a preliminary scout project in development, not yet released in open source. But I can attach here this preliminary code. Certainly without any warranty, support and other legal stuff....

The example is based on pac4j and demonstrates single sign on by AzureAD

In order to run the example, edit the following files to adapt to your local setup, assuming that your local test machine is "mywebapp.mydomain.local"

[config.properties]
1. scout.externalBaseUrl=...

2. scout.jetty.keyStorePath=...
3. scout.jetty.autoCreateSelfSignedCertificate=...
(This automatically generates a HTTPS SSL ceritificate for your webapp test (cool eh :-). Once the cert is generated, comment these 2 lines, copy the generated jks file to your workspace and enable the line scout.jetty.keyStorePath=classpath:/jetty-ssl.jks)
4. scout.pac4j...values according to your client app registration in Azure AD Active Directory

[logback.xml]
edit for detailed logging

[Running]
To run the sample use an eclipse Run config or an intelliJ service config.
Main Class: org.eclipse.scout.dev.jetty.JettyServer
Working Directory: Path to eclipse project/intelliJ module com.bsiag.scout.rt.pac4j.dev

[Feedback]
Please give us and the community feedback if this example worked for you.

[Updated on: Fri, 13 November 2020 10:31]

Report message to a moderator

Re: OAuth Authentication [message #1834615 is a reply to message #1834597] Fri, 13 November 2020 14:59 Go to previous messageGo to next message
Mark Ashworth is currently offline Mark AshworthFriend
Messages: 40
Registered: January 2012
Member
Good day Ivan,

Thank you very much for the assistance and the code :-)

I understand the no warranty, legal and support stuff :-)


Kind regards,
Mark Ashworth
Re: OAuth Authentication [message #1839336 is a reply to message #1834615] Fri, 19 March 2021 11:51 Go to previous messageGo to next message
Mark Ashworth is currently offline Mark AshworthFriend
Messages: 40
Registered: January 2012
Member
Good day Ivan,

I got most of the sample you sent to work, I am just stuck on the last part when Azure AD redirects to the callback URL which cannot be found.

It might have to do with the versions of the dependencies in the project since these were not in the zip file project, so I used the following.

Also, I am using the 11.0.12 version of scout.rt because the eventual application will use that version. I did have a look at the exclude URL list and I will update that according to the migration docs.

<properties>
    <pac4j.core.version>4.4.0</pac4j.core.version>
    <pac4j.jee.version>5.0.0</pac4j.jee.version>
  </properties>


https://localhost:8082/callback/AzureADClient

I had a look at PAC4J and the Azure Documentation, and it seems that the code is registring the AzureADClient and the Client correctly.

The weird thing is that the MyServlet is not be called with the callback so it does not go into the doCallback() method.

Do you have some suggestions?

Kind regards,
mark Ashworth




Re: OAuth Authentication [message #1840039 is a reply to message #1839336] Tue, 06 April 2021 04:48 Go to previous messageGo to next message
Mark Ashworth is currently offline Mark AshworthFriend
Messages: 40
Registered: January 2012
Member
Good morning Ivan,

I managed to resolve the issue and I have upgraded the code to use the pac4j Azure 2 AD Client and Configuration in the upcoming release.

I have also integrated the code into a Scout 11 application and the authentication is working except the Refresh Token is null on the profile when creating the Jwt token. This causes an issue later when Scout tries to create a signed token for the user and the custom property for the refresh token is null.

Caused by: java.lang.NullPointerException: null
	at org.eclipse.scout.rt.shared.servicetunnel.http.DefaultAuthToken.write(DefaultAuthToken.java:154)
	at org.eclipse.scout.rt.shared.servicetunnel.http.DefaultAuthTokenSigner.signature(DefaultAuthTokenSigner.java:130)
	at org.eclipse.scout.rt.shared.servicetunnel.http.DefaultAuthTokenSigner.sign(DefaultAuthTokenSigner.java:124)
	at org.eclipse.scout.rt.shared.servicetunnel.http.DefaultAuthTokenSigner.createDefaultSignedToken(DefaultAuthTokenSigner.java:75)
	at org.eclipse.scout.rt.shared.servicetunnel.http.HttpServiceTunnel.addSignatureHeader(HttpServiceTunnel.java:149)
	... 28 common frames omitted


It would seem that the Refresh token is meant to be requested by the pac4j workflow after receiving the access & id tokens as part of authentication but I have not quite confirmed this. I have the scope offline_access added as per the original code but still not refresh token.

Have you been able to get the refresh token?

Kind regards,
Mark Ashworth
Re: OAuth Authentication [message #1840052 is a reply to message #1840039] Tue, 06 April 2021 08:01 Go to previous messageGo to next message
Mark Ashworth is currently offline Mark AshworthFriend
Messages: 40
Registered: January 2012
Member
Hi,

After a bit more investigation, I found that I could get the refresh token when I set the OidcRedirectionActionBuilder to add the "offline_access"in the scopes in authorization params here.

    protected Map<String, String> buildParams(final WebContext webContext) {
        final var configContext = new OidcConfigurationContext(webContext, client.getConfiguration());

        final var authParams = new HashMap<String, String>();
        authParams.put(OidcConfiguration.SCOPE, configContext.getScope());
        authParams.put(OidcConfiguration.RESPONSE_TYPE, configContext.getResponseType());
        authParams.put(OidcConfiguration.RESPONSE_MODE, configContext.getResponseMode());
        authParams.putAll(configContext.getCustomParams());
        authParams.put(OidcConfiguration.CLIENT_ID, configContext.getConfiguration().getClientId());

        return new HashMap<>(authParams);
    }


However, this causes the header to be too large.

The server.app.dev application reports the following error:-

To shut the server down, type "shutdown" in the console.
 - MDC[]
2021-04-06 09:47:49,759 WARN  [qtp177140066-27] org.eclipse.jetty.http.HttpParser.parseFields(HttpParser.java:1126) - Header is too large 8193>8192 - MDC[]


The ui.html.app.dev application reports the following error:-

2021-04-06 09:47:49,765 INFO  [qtp2104973502-72] org.eclipse.scout.rt.ui.html.UiSession.dispose(UiSession.java:599) - Disposing UI session with ID 1:19knavrqigitg21k3qi15t08d58qtspp3ok3qtg051efpnhtn9ui... - MDC[principal=u@three60development.onmicrosoft.com, cid=FW8yU6fX6kg/1]
2021-04-06 09:47:49,767 ERROR [qtp2104973502-72] org.eclipse.scout.rt.ui.html.json.JsonMessageRequestHandler.handlePost(JsonMessageRequestHandler.java:133) - Error while initializing UI session - MDC[principal=u@three60development.onmicrosoft.com, cid=FW8yU6fX6kg/1]
org.eclipse.scout.rt.shared.servicetunnel.http.HttpServiceTunnelException: Service tunnel request failed with status code 431 [user=u@three60development.onmicrosoft.com, remote-service.name=org.eclipse.scout.rt.shared.cache.IRemoteCacheService, remote-service.operation=getAll, user=notification-authenticator, calling-thread=qtp2104973502-72, job=Starting ClientSession [sessionId=b3lvjbpmff4s0fatps5p3p7rlhk347ulpnt8voee8d2glna93rk]]
	at org.eclipse.scout.rt.shared.servicetunnel.http.RemoteServiceInvocationCallable.call(RemoteServiceInvocationCallable.java:83)
	at org.eclipse.scout.rt.shared.servicetunnel.http.RemoteServiceInvocationCallable.call(RemoteServiceInvocationCallable.java:1)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:227)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:227)
	at org.eclipse.scout.rt.platform.transaction.TransactionProcessor.runTxMandatory(TransactionProcessor.java:156)
	at org.eclipse.scout.rt.platform.transaction.TransactionProcessor.runTxRequired(TransactionProcessor.java:139)
	at org.eclipse.scout.rt.platform.transaction.TransactionProcessor.intercept(TransactionProcessor.java:78)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:222)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/javax.security.auth.Subject.doAs(Subject.java:423)
	at org.eclipse.scout.rt.platform.security.SubjectProcessor.intercept(SubjectProcessor.java:43)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:222)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain.call(CallableChain.java:170)
	at org.eclipse.scout.rt.platform.context.RunContext.call(RunContext.java:158)
	at org.eclipse.scout.rt.platform.context.RunContextRunner.intercept(RunContextRunner.java:38)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:222)
	at org.eclipse.scout.rt.platform.job.internal.CallableChainExceptionHandler.intercept(CallableChainExceptionHandler.java:33)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:222)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain.call(CallableChain.java:170)
	at org.eclipse.scout.rt.platform.job.internal.JobFutureTask.lambda$0(JobFutureTask.java:106)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.eclipse.scout.rt.platform.job.internal.JobFutureTask.run(JobFutureTask.java:175)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
	at org.eclipse.scout.rt.platform.job.internal.NamedThreadFactory$1.run(NamedThreadFactory.java:63)
	at org.eclipse.scout.rt.shared.servicetunnel.AbstractServiceTunnel.invokeService(AbstractServiceTunnel.java:64)
	at org.eclipse.scout.rt.shared.servicetunnel.AbstractServiceTunnel.invokeService(AbstractServiceTunnel.java:40)
	at org.eclipse.scout.rt.shared.servicetunnel.http.HttpServiceTunnel.invokeService(HttpServiceTunnel.java:192)
	at org.eclipse.scout.rt.shared.servicetunnel.ServiceTunnelProxyProducer.invoke(ServiceTunnelProxyProducer.java:51)
	at org.eclipse.scout.rt.platform.interceptor.DecoratingProxy.invokeImpl(DecoratingProxy.java:137)
	at org.eclipse.scout.rt.platform.interceptor.DecoratingProxy$P_InvocationHandler.invoke(DecoratingProxy.java:170)
	at com.sun.proxy.$Proxy20.getAll(Unknown Source)
	at org.eclipse.scout.rt.client.cache.RemoteCacheValueResolver.resolveAll(RemoteCacheValueResolver.java:45)
	at org.eclipse.scout.rt.platform.cache.BasicCache.getAll(BasicCache.java:112)
	at org.eclipse.scout.rt.platform.cache.AbstractCacheWrapper.getAll(AbstractCacheWrapper.java:49)
	at org.eclipse.scout.rt.shared.services.common.code.CodeService.getCodeTypeMap(CodeService.java:164)
	at org.eclipse.scout.rt.shared.services.common.code.CodeService.getCodeTypes(CodeService.java:142)
	at org.eclipse.scout.rt.shared.services.common.code.CODES.getCodeTypes(CODES.java:45)
	at org.eclipse.scout.rt.shared.services.common.code.CODES.getAllCodeTypes(CODES.java:98)
	at com.github.markash.micro.client.ClientSession.execLoadSession(ClientSession.java:28)
	at org.eclipse.scout.rt.client.AbstractClientSession$LocalClientSessionExtension.execLoadSession(AbstractClientSession.java:510)
	at org.eclipse.scout.rt.client.extension.ClientSessionChains$ClientSessionLoadSessionChain$1.callMethod(ClientSessionChains.java:57)
	at org.eclipse.scout.rt.client.extension.ClientSessionChains$ClientSessionLoadSessionChain$1.callMethod(ClientSessionChains.java:1)
	at org.eclipse.scout.rt.shared.extension.AbstractExtensionChain.callChain(AbstractExtensionChain.java:113)
	at org.eclipse.scout.rt.client.extension.ClientSessionChains$ClientSessionLoadSessionChain.execLoadSession(ClientSessionChains.java:60)
	at org.eclipse.scout.rt.client.AbstractClientSession.interceptLoadSession(AbstractClientSession.java:524)
	at org.eclipse.scout.rt.client.AbstractClientSession.start(AbstractClientSession.java:290)
	at org.eclipse.scout.rt.client.session.ClientSessionProvider.lambda$1(ClientSessionProvider.java:74)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:227)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:227)
	at org.eclipse.scout.rt.platform.transaction.TransactionProcessor.runTxMandatory(TransactionProcessor.java:156)
	at org.eclipse.scout.rt.platform.transaction.TransactionProcessor.runTxRequired(TransactionProcessor.java:139)
	at org.eclipse.scout.rt.platform.transaction.TransactionProcessor.intercept(TransactionProcessor.java:78)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:222)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/javax.security.auth.Subject.doAs(Subject.java:423)
	at org.eclipse.scout.rt.platform.security.SubjectProcessor.intercept(SubjectProcessor.java:43)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:222)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain.call(CallableChain.java:170)
	at org.eclipse.scout.rt.platform.context.RunContext.call(RunContext.java:158)
	at org.eclipse.scout.rt.platform.context.RunContextRunner.intercept(RunContextRunner.java:38)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:222)
	at org.eclipse.scout.rt.platform.job.internal.CallableChainExceptionHandler.intercept(CallableChainExceptionHandler.java:33)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain$Chain.continueChain(CallableChain.java:222)
	at org.eclipse.scout.rt.platform.chain.callable.CallableChain.call(CallableChain.java:170)
	at org.eclipse.scout.rt.platform.job.internal.JobFutureTask.lambda$0(JobFutureTask.java:106)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.eclipse.scout.rt.platform.job.internal.JobFutureTask.run(JobFutureTask.java:175)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
	at org.eclipse.scout.rt.platform.job.internal.NamedThreadFactory$1.run(NamedThreadFactory.java:63)


Kind regards,
Mark Ashworth

Re: OAuth Authentication [message #1840303 is a reply to message #1840052] Mon, 12 April 2021 07:49 Go to previous messageGo to next message
Mark Ashworth is currently offline Mark AshworthFriend
Messages: 40
Registered: January 2012
Member
Good morning,

I have extended the Pac4J OidcConfigurationContext to read the scope from the configuration instead of just defaulting it to 'openid profile email' when it is not found in the request scope.

This has the effect of using the values that are sconfigured in the config.properties in the ui.html.dev project with a scope of 'openid profile email offline_access' so that a refresh token is returned for the the creation of the JWT token.

The issue is that the scoutaccesstoken (which I think is the JWT token) is larger than the allows 8192KB for Jetty and I am not sure how to configure the server with a larger header size. I have Googled an none of the recommendations work with the JettyServer class used in Scout.

Any recommenadtions would be appreciated :-)

public class OidcConfigurationContext2 extends OidcConfigurationContext {

	private final WebContext webContext;
	
    public OidcConfigurationContext2(
    		final WebContext webContext,
    		final OidcConfiguration oidcConfiguration) {
        
    	super(webContext, oidcConfiguration);
    	
    	this.webContext = webContext;
    }

    public String getScope() {
    	
    	final String configuredScope = 
    			Optional.ofNullable(getConfiguration().getScope())
    				.orElse("openid profile email");
    	
        return (String) this.webContext.getRequestAttribute(OidcConfiguration.SCOPE)
        		.orElse(configuredScope);
    }
}


2021-04-12 09:38:28,914 DEBUG [qtp159475521-27] org.eclipse.jetty.http.HttpParser.setState(HttpParser.java:1907) - HEADER:x-scoutaccesstoken --> VALUE - MDC[]
2021-04-12 09:38:28,914 DEBUG [qtp159475521-27] org.eclipse.jetty.http.HttpParser.setState(HttpParser.java:1907) - HEADER:x-scoutaccesstoken --> IN_VALUE - MDC[]
2021-04-12 09:38:28,917 DEBUG [qtp159475521-27] org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1492) - parseNext s=HEADER HeapByteBuffer@4dcecfdf[p=0,l=2642,c=8192,r=2642]={<<<a446a304a4c49366d4e324c6f...\xCd\xB1\xEa\xAc\x83\xBc\x98\x84m\xFb\xDd\xE4\xBeXth\xD1\xFd\x17\xD7\xA7XX>>>4622d4971...614a774} - MDC[]
2021-04-12 09:38:28,918 WARN  [qtp159475521-27] org.eclipse.jetty.http.HttpParser.parseFields(HttpParser.java:1126) - Header is too large 8193>8192 - MDC[]
2021-04-12 09:38:28,923 DEBUG [qtp159475521-27] org.eclipse.jetty.http.HttpParser.badMessage(HttpParser.java:1637) - Parse exception: HttpParser{s=HEADER,0 of -1} for HttpChannelOverHttp@58c643d7{s=HttpChannelState@5cf9dc17{s=IDLE rs=BLOCKING os=OPEN is=IDLE awp=false se=false i=true al=0},r=0,c=false/false,a=IDLE,uri=null,age=0} - MDC[]
org.eclipse.jetty.http.BadMessageException: 431: null
	at org.eclipse.jetty.http.HttpParser.parseFields(HttpParser.java:1129)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1517)
	at org.eclipse.jetty.server.HttpConnection.parseRequestBuffer(HttpConnection.java:364)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:261)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
	at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:135)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:773)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:905)
	at java.base/java.lang.Thread.run(Thread.java:834)
2021-04-12 09:38:28,923 DEBUG [qtp159475521-27] org.eclipse.jetty.http.HttpParser.setState(HttpParser.java:1900) - HEADER --> CLOSE - MDC[]


Kind regards,
Mark Ashworth
Re: OAuth Authentication [message #1840315 is a reply to message #1840303] Mon, 12 April 2021 10:52 Go to previous message
Mark Ashworth is currently offline Mark AshworthFriend
Messages: 40
Registered: January 2012
Member
Good day,

In the interim, I have overloaded the JettyServer so that I can set the request headers to 16kb from the 8kb default.

The code is now working :-)

public class MicroJettyServer extends org.eclipse.scout.dev.jetty.JettyServer {
	private static final Logger LOG = LoggerFactory.getLogger(MicroJettyServer.class);

	public static void main(String[] args) {
		new MicroJettyServer().start();
	}

	@Override
	protected ServerConnector createHttpServerConnector(
			final int port) {
		
		HttpConfiguration httpConfig = new HttpConfiguration();
		httpConfig.setSendServerVersion(false);
		httpConfig.setSendDateHeader(false);
		httpConfig.setRequestHeaderSize(1024 * 16);

		ServerConnector http = new ServerConnector(m_server, new HttpConnectionFactory(httpConfig));
		http.setPort(port);
		return http;
	}

	@Override
	protected ServerConnector createHttpsServerConnector(
			final int port) {
		SslContextFactory sslContextFactory = createSslContextFactory();
		HttpConfiguration httpsConfig = new HttpConfiguration();
		httpsConfig.addCustomizer(new SecureRequestCustomizer());
		httpsConfig.setSendServerVersion(false);
		httpsConfig.setSendDateHeader(false);
		httpsConfig.setRequestHeaderSize(1024 * 16);

		ServerConnector https = new ServerConnector(m_server,
				new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
				new HttpConnectionFactory(httpsConfig));
		https.setPort(port);
		return https;
	}
}


Kind regards,
Mark Ashworth
Previous Topic:Filechooser: how to get the directory containing the file(s)
Next Topic:Errors while using CodeType
Goto Forum:
  


Current Time: Wed Feb 21 13:08:35 GMT 2024

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

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

Back to the top