Reputation: 271
here is my problem :
Entierely from back-end, I want to use the Yammer API, without any real user action. To do that, first of all I have to retrieve a token.
To retrieve the token I have to login. From back-end side I use the com.meterware.httpunit pacakge to send http requests and receive responses.
So I emit the GET request to retrieve the yammer login page. Then, programmatically I fill and submit the login form.
You can have a exemple of the implementation here : Yammer-Java-SDK.
It looks like :
WebResponse resp = wc.getResponse(String.format(OAUTH_GET_ACCESS_TOKEN_URL, applicationKey));
// Retrieve, fill and submit Yammer login form
WebForm form = findLoginForm(resp.getForms());
form.setParameter("login", username);
form.setParameter("password", password);
resp = form.submit();
Unfortunately, the Yammer project I'm targeting is emmbeded into Office365. So when I submit the original yammer login form, I have as response, the Office365 login page. It could have been all right: retrieve the office365 form, fill and submit it... but it's not !!!
The office365 login form is build thanks to the JavaScript engine. In an ordinary internet browser there is no problem. But when I'm at the back-end side, the Javascript engine I have from the org.mozilla.rhino (v1.7.10) is unable to execute properly the script... The script is not executed -> the form is not built -> I can't post it -> I can't retrieve the token-> I can't post things on yammer from my server... :(
Of crouse I've enabled the scripting into my HttpUnitOptions :
HttpUnitOptions.setScriptingEnabled(true);
And there, the error I got from the office365 login page :
Caused by: com.meterware.httpunit.ScriptException: Script 'webpackJsonp([77],{"6Tns":function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){};i.redirectPatterns=["/uploaded_files/"],i.prototype={threadRegex:new RegExp("threadId=([0-9A-Za-z]+={0,3})","i"),isForeignRegex:new RegExp("foreign=true","i"),redirectIfNecessary:function(e){""!==e.hash&&(this.isForeign(e)?this.redirectToForeign(e):this.redirectWithPatterns(e))},redirectWithPatterns:function(e){for(var t=i.redirectPatterns,r=0,n=t.length;r1)}},t.default=i},8:function(e,t,r){e.exports=r("vP7g")},Jpbm:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){};i.prototype={redirectIfNecessary:function(e){window.top!=window&&window.top.location.replace(e.href)}},t.default=i},vP7g:function(e,t,r){"use strict";var i=o(r("Jpbm")),n=o(r("6Tns"));function o(e){return e&&e.__esModule?e:{default:e}}(new i.default).redirectIfNecessary(window.location),(new n.default).redirectIfNecessary(window.location)}},[8]);' failed: org.mozilla.javascript.EcmaError: TypeError: Impossible dappeler la méthode "{1}" de {0}
Here the function where the root exception is catched and rethrown :
from : com.meterware.httpunit.javascript.ScriptingEngineImpl
public String runScript( String language, String script ) {
if (!supportsScriptLanguage( language )) return "";
try {
script = script.trim();
if (script.startsWith( "<!--" )) {
script = withoutFirstLine( script );
if (script.endsWith( "-->" )) script = script.substring( 0, script.lastIndexOf( "-->" ));
}
Context context = Context.enter();
context.initStandardObjects( null );
context.evaluateString( this, script, "httpunit", 0, null );
return getDocumentWriteBuffer();
} catch (Exception e) {
handleScriptException( e, "Script '" + script + "'" );
return "";
} finally {
discardDocumentWriteBuffer();
Context.exit();
}
}
The Context object comes from : org.mozilla.javascript.Context, and here is its javadoc :
This class represents the runtime context of an executing script. Before executing a script, an instance of Context must be created and associated with the thread that will be executing the script. The Context will be used to store information about the executing of the script such as the call stack. Contexts are associated with the current thread using the call(ContextAction) or enter() methods.
Different forms of script execution are supported. Scripts may be evaluated from the source directly, or first compiled and then later executed. Interactive execution is also supported.
Some aspects of script execution, such as type conversions and object creation, may be accessed directly through methods of Context.
In the back-end side, I tried to simulate the post request that the office365 login page emit, but so far... so bad...
I really need your help. I would like to solve at least one of those 3 statements :
Thank you in advance, Stephane
Upvotes: 1
Views: 401
Reputation: 861
Yammer access tokens are "long-lived" and will not expire unless explicitly revoked. (link, see section C). This means you can simply store one access token and just use that against the API.
When you view the app's registration page you should be able to generate a developer token on one of the settings pages. Use that.
For an example of how I used the Yammer APIs in a back-end context, check this out: https://derekgusoff.wordpress.com/2017/10/31/create-a-yammer-group-with-microsoft-flow/
Upvotes: 1