Polarion OSLC consumer implementation

Hello, I’m trying to implement an OSLC consumer for Polarion without success.
I’m not sure if I should use Lyo 4.0.0 or Lyo 2.4.0. I tried both for now.
I have 2 issues. The first one is that a new token is generate when I call lookupServiceProviderUrl the second time.
The second issue is that I can’t have a successful authentication. I think I’m missing one step but I can’t figure out what. When I post with Postman to http://serveur/polarion/j_security_check, it works.
Here is my code, and the original post is here : Eclipse Community Forums: Lyo » Polarion oslc consumer oauth .

public class Main {
	private static final Logger logger = Logger.getLogger(Main.class.getName());

	public static void main(String[] args) throws RootServicesException, IOException, OAuthException, URISyntaxException, ResourceNotFoundException, InterruptedException, InvalidCredentialsException  {
		String webContextUrl = "http://serveur/polarion/oslc";
		String securityUrl = "http://serveur/polarion/j_security_check";
		String user = "admin";
		String password = "psw";
		String projectArea = "playground";
	
		JazzRootServicesHelper helper = new JazzRootServicesHelper(webContextUrl, OSLCConstants.OSLC_RM_V2);
		
		HttpClient client = HttpClient.newHttpClient();
		HttpRequest request = HttpRequest.newBuilder()
			      .uri(URI.create(helper.getRequestConsumerKeyUrl()))
			      .timeout(Duration.ofMinutes(1))
			      .header("Content-Type", "application/json")
			      .POST(BodyPublishers.ofFile(Paths.get("D:\\Softwares\\eclipse 2019-03\\workspaceLyoClient\\lyo.client\\oslc-java-client\\src\\main\\java\\org\\eclipse\\lyo\\client\\test\\id.json")))
			      .build();
		
		HttpResponse<String> responseKey = client.send(request, BodyHandlers.ofString());
		if(responseKey.statusCode() == 200) {
			JsonParser parser = new JsonParser();
			JsonObject obj = parser.parse(responseKey.body()).getAsJsonObject();
			String key = obj.get("key").getAsString();
			System.out.println(key);
			
			OslcOAuthClient clientOslc = helper.initOAuthClient(key, "somesecret");

			try {
				String res = clientOslc.lookupServiceProviderUrl(helper.getCatalogUrl(), projectArea);	
			}
			catch (OAuthRedirectException oauthE) {
				HttpPost formPost = new HttpPost(securityUrl);
				List<NameValuePair> nvps = new ArrayList<NameValuePair>();
				nvps.add(new BasicNameValuePair("j_username", user));
				nvps.add(new BasicNameValuePair("j_password", password));
				formPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

				org.apache.http.HttpResponse formResponse = clientOslc.getHttpClient().execute(formPost);
				Header location = formResponse.getFirstHeader("Location");
				
				System.out.println("Status : " + formResponse.getStatusLine().getStatusCode());//print 302
				System.out.println("location : " + location);	//print http://serveur/polarion
				HttpEntity entity = formResponse.getEntity();
				String responseString = EntityUtils.toString(entity, "UTF-8");
				System.out.println("Body : " + responseString);	//print blank
				EntityUtils.consume(formResponse.getEntity());
				
				//Third GET
				HttpGet request4 = new HttpGet(location.getValue());
				HttpClientParams.setRedirecting(request4.getParams(), false);
				org.apache.http.HttpResponse responseThird = clientOslc.getHttpClient().execute(request4);

				System.out.println("Status : " + responseThird.getStatusLine().getStatusCode()); //print 302
				System.out.println("location : " + location); //print http://serveur/polarion
			    entity = responseThird.getEntity();
				responseString = EntityUtils.toString(entity, "UTF-8");
				System.out.println("Body : " + responseString); //print blank
				EntityUtils.consume(responseThird.getEntity());
				
				//Since location is http://serveur/polarion this does not work
			/*	Map<String,String> oAuthMap = getQueryMap(location.getValue());
				System.out.println(oAuthMap.toString());
				String oauthToken = oAuthMap.get("oauth_token");
				String oauthverifier = oAuthMap.get("oauth_verifier");*/
				
				// The server requires an authentication: Create the login form
				HttpPost formPost2 = new HttpPost(oauthE.getRedirectURL() + "?oauth_token=" + oauthE.getAccessor().requestToken);
				formPost2.getParams().setParameter("oauth_token", oauthE.getAccessor().requestToken);
				formPost2.getParams().setParameter("oauth_verifier", "");
				formPost2.getParams().setParameter("authorize", "true");
				formPost2.addHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");

				formResponse = clientOslc.getHttpClient().execute(formPost2);
				
				System.out.println("Status : " + formResponse.getStatusLine().getStatusCode());
				System.out.println("location : " + location);
				entity = formResponse.getEntity();
				responseString = EntityUtils.toString(entity, "UTF-8");
				System.out.println("Body : " + formResponse);
				EntityUtils.consume(formResponse.getEntity());

				Header header = formResponse.getFirstHeader("Content-Length");
				if ((header!=null) && (!("0".equals(header.getValue())))) {
					// The login failed
					throw new InvalidCredentialsException("Authentication failed");
				} else {
					// The login succeed
					// Step (3): Request again the protected resource
					EntityUtils.consume(formResponse.getEntity());
					String res = clientOslc.lookupServiceProviderUrl(helper.getCatalogUrl(), projectArea);	
					System.out.println(res);
				}
			}
		}
	}

You may find it helpful to explore the samples here: https://github.com/OSLC/lyo-samples/tree/master/oslc-java-samples/src/main/java/org/eclipse/lyo/client/oslc/samples and here: https://github.com/OSLC/lyo-samples/tree/master/oslc4j-client-samples/src/main/java/org/eclipse/lyo/oslc4j/client/samples

Hello, thanks for the links but I already tried to adapt them for my needs. I think the DoorsOauthSample.java seems to be the one that I should inspire my code on.
My understanding of the steps is this :
1 - send a request to /polarion/oslc/rootservices to get the oauth services (helper = new JazzRootServicesHelper)
2 - send a request to /polarion/oslc/services/oauth/requestKey (helper.getRequestConsumerKeyUrl()) with a secret
3 - init one OslcOAuthClient with the requested key of 2) and the secret
4 - Look for the service provider with clientOslc.lookupServiceProviderUrl(helper.getCatalogUrl(), “nameOfProject”); An error is throw “Enter this URL in a browser and run again:”
4a - Log in to /polarion/j_security_check with a post request
4b - send a request to /polarion/oslc/services/oauth/authorize with the url throw in 4
4c - retry 4

My issues is that when I retry 4 I get an exception “Enter this URL in a browser and run again:” but with a different token. Also I’m not able to log in to /polarion/j_security_check, but I can log in with Postman.

Can you confirm the procedure steps ?

You appear to be mixing OAuth and JEE Forms authentication. You first have to determine what Polarion supports. Then try to get the samples working against your Polarion server. Once you get them working, clone the code pattern in your application.

Thanks for your advices.

I wanted to use OAuth but the exception “Enter this URL in a browser and run again: /polarion/oslc/services/oauth/authorize?oauth_token=80ba005f-856d-4dea-8416” is throw and this url is protected by a JEE form.
In the DoorsOauthSample.java the method validateTokens seems to do what I’m looking for but I was not able to adapt it, so I was not sure about the steps.

Anyway I can access the catalogue after I log in with the JEE authentication in Postman so I guess, I’ll try to use this instead of OAuth for now.

Hello, I was able to connect to Polarion with the help of the CMSample.java.

Unfortunately it seems that Polarion is not offering queries or previews ui yet.

I’m now trying to use a delegated ui but I’m not sure how to do it with Lyo.
I found the lookupCreationFactory but does Lyo have a method to look for Selection delegated ui ?

Hi

Did you try to do what the message tell you? Run the request in a browser and rerun your client code
/polarion/oslc/services/oauth/authorize?oauth_token=80ba005f-856d-4dea-8416

I assume this partial url is more complete and should lead you to a page on the Polarion server.

The client wants you (the human) to approve the Polarion friendship before it can proceed.

I will try to explain some more details in a later post, but good to know first what this leads to.

Hi again

Are you familiar with oauth 1.0? You seem to be stuck in establishing a friendship between your client and Polarion. I find oauth tricky to deal with, and it does not help having a blackbox polarion, and not knowing what they are expecting (not so much documentation).

But here are some tips that I hope you find useful. I’ll try to guess how Polarion is working, making it less of a blackbox.

I am myself familiar with using Polarion as an OSLC client, connecting to other OSLC servers. This is unlike your need where Polarion is the OSLC server. But given that Polarion is using Lyo (2.1.0 for Polarion 18), I am pretty sure its the same code base for both Client and Server part.

If you dig into their plugins folder, one can see that they are using many Lyo libraries. In particular for you, they seem to be using the oauth-webapp library. This library handles the REST services that deal with the oauth handshaking.
So, clone the repo https://github.com/eclipse/lyo.server, and import its 3 oauth maven projects. (I’d take the branch r-2.4.0 to be on safe side, since it’s probably closest to 2.1.0 that Polarion uses.)
Have in particular a look at this class, which contains almost all relevant REST calls. The other relevant class is the syster class ConsumersService.java. https://github.com/eclipse/lyo.server/blob/master/oauth-webapp/src/main/java/org/eclipse/lyo/server/oauth/webapp/services/OAuthService.java

Through a webbrowser, have a look at the Polarion rootservices document. http://your-polarion-servername/polarion/oslc/rootservices
See how these URLs match the ones in the class OAuthService.java above?

Now, you seem to be stuck when your client code is making a call to …/services/oauth/requestKey. That the oauthRequestConsumerKeyUrl in the rootservices document. It’s the step in oauth when the Polarion server needs to give the consumer (your client) a key that identify the application itself. The closest I can find to explain this step is this documentation. But in your case, the roles are reversed.
https://almdemo.polarion.com/polarion/help/topic/com.polarion.xray.doc.user/guide/xid1551488.html?resultof=“oslc”%20

So, I’m pretty sure that if you follow my suggestion above, (and enter that URL you got in the exception message), Polarion will make you a friend.

And then you can proceed with the other steps of oauth, which I don’t promise they will be easier.
But I hope the link between the URLs in the rootservices document and the code Polarion uses, might help you guess what Polarion needs.

Hello, thanks a lot for your help jad.

I never used oauth before but I read about it before trying. I also used JWT server side.
All the URLs I used are more complete when used.

When I enter the URL in a browser, I have to log in then I can accept the requestedToken.

About the requested Key, I tried many combination.
I tried to ask for a key with /polarion/oslc/services/oauth/requestKey everytime I launch the application.
I also tried to launch the application once to generate a key and then manually approve the key in /polarion/oslc/services/oauth/approveKey after logging in and then always use this approved key.
I tried to use the key generated from the page /administration/linkeddata/friends where I put http://serveur/polarion/oslc/rootservices as URI. But I noticed that this way was intended for connection with another provider and the key generated was also in /polarion/oslc/services/oauth/approveKey.

Every time I launch the application (even if I use the same requested key that is active in /polarion/oslc/services/oauth/approveKey), the message asking me to go to /polarion/oslc/services/oauth/authorize with a browser show a different generated requestedToken.
Also I wanted to authorize the token from my application and not the browser, that’s why I mixed JEE auth with oauth.

I also tried all the steps with Postman with an active key. After receiving the requested token I go to polarion/oslc/services/oauth/authorize with the key, got 200 it shows the page where I must log in.
If I have to log in to use oauth everytime, I don’t think it’s much better than using JEE auth for my application.

Finally, I was able to access the catalog using only JEE auth. I’m now struggling to use Lyo to access the delegated UI services.

Regards,

Hi.

So you have two problems: oauth & access to delegateUI.
Oauth1.0 is hell to work with, but if you can proceed without it (using JEE auth), let’s put that to the side now, and focus on the second problem - delegatedUI.

Unfortunately it seems that Polarion is not offering queries or previews ui yet.

That’s true. Polarion seems only to provide selectionDUI, creationDUI & CreatioFactory.
Do you know how to work out what services are available? On a webbrowser, get http://localhost/polarion/oslc/services/catalog. Pick a serviecProvider, and get that URI. You can then see the RDF representaiton of the ServiecProvider.

I’m now trying to use a delegated ui but I’m not sure how to do it with Lyo.
I found the lookupCreationFactory but does Lyo have a method to look for Selection delegated ui ?

LyoClient seems only to have methods to lookup Query and CreationFactory. I don’t know why only these 2 are supported. But you don’t really need these methods. You can just create your own. Just copy/paste the code for one of them, and adjust it to get access to teh DelegatedUI part of the provider?
All you need really is the first 2 lines of code from these methods. namely

Response response = getResource(serviceProviderUrl,OSLCConstants.CT_RDF);
ServiceProvider serviceProvider = response.readEntity(ServiceProvider.class);

Once you have that serviceProvider instance, you can also access all its methods serviceProvider.getServices()
service.getSelectionDialogs()

1 Like

I assume you have access to the lyo.client code https://github.com/eclipse/lyo.client

@jamsden would be good to improve the client based on Jad’s feedback!

Hello,

Thanks Jad, I was able to implement getSelectionDialogs() and use it with your advices.

There is still some things I’m trying to figure out.
Should I implement a custom OslcClient with all the methods I need then?
If I do how can I be more precise in what I want. Sometimes it seems like the description for different services are the same. For example I have these 2 factories in my service provider :

<oslc:creationFactory>
	<oslc:CreationFactory>
		<oslc:creation rdf:resource="http://serveur/polarion/oslc/services/projects/playground/workitems/softwarerequirement"/>
		<dcterms:title rdf:parseType="Literal">Create Software Requirement</dcterms:title>
		<oslc:label>softwarerequirement</oslc:label>
	</oslc:CreationFactory>
</oslc:creationFactory>

<oslc:creationFactory>
	<oslc:CreationFactory>
		<oslc:creation rdf:resource="http://serveur/polarion/oslc/services/projects/playground/workitems/systemrequirement"/>
		<dcterms:title rdf:parseType="Literal">Create System Requirement</dcterms:title>
		<oslc:label>systemrequirement</oslc:label>
	</oslc:CreationFactory>
</oslc:creationFactory>

If I filter with the label, that means that my client will not be able to consume an other Oslc provider if they don’t have the same label. So what’s the best way to select the one I want ?

Finally does the line <oslc:domain rdf:resource=“http://open-services.net/ns/rm#”/> applies to everything under it ? The first two services don’t have a line with oslc: domain on top of them.

I typically create a MyAdaptorClient for MyAdaptor that takes an OslcClient as a constructor argument and has adaptor-specific methods to do the exact operations I need. But in your example above, I think you hit a point which should be supported by Lyo Client out of the box. We will discuss this with @jamsden further. If you are interested to make a pull request for the client, we will be happy to work with you to get it tested and merged.

oslc:creationFactory is an RDF property and oslc:CreationFactory is an RDF class. In other words, the property oslc:creationFactory points to an RDF resource of type oslc:CreationFactory.

RDF/XML is very hard to understand. If you are using a fresh version of Lyo server SDK, just request text/turtle MIME type. Otherwise, use a tool like EasyRdf to convert RDF/XML to Turtle. This should make the structure of the document easy for you to understand. The oslc:domain property is typically added to the oslc:ServiceProviderCatalog resource.

Thanks Andrew, I’ll try EasyRdf & turle format.

I would love to try to make a pull request. I’m not sure if I can with the firewall here sadly…

I edited this part of my post because I had the wrong indentation, my question make more sense now.

Michael, we would love to help you with the tech problems. If you are behind an enterprise proxy, please use the repo over HTTPS as it’s usually impossible to push over SSH. Or are you talking about the permission to make an open-source contribution from your management? Let’s start by opening an issue under Issues · eclipse/lyo.client · GitHub and describing what the pull request needs to change.

And I’m happy to support testing and any Lyo-related questions. (I have not yet read the derails of your latest questions)

Just to be sure, are you working with 4.0.0-snapshot or 2.4.0? I would suggest the former.

I’m working with 4.0.0 , I could switch for 2.4.0. Does 2.4.0 offers more features ?

I think both will be an issue, I’ll have to ask about it.

concerning 2.4.0 vs. 4.0.0, 4.0.0 is the most updated and I’d recommend you use that.
But to be aware of the difference, please refer to section 2 under http://oslc.github.io/developing-oslc-applications/eclipse_lyo/setup-an-oslc-provider-consumer-application.html

1 Like

@Michael.C! I am just wondering about your progress with Polarion. Hope it has progressed well?
FYI, I have also started some effort to develop OSLC consumer for Polarion.

1 Like