lvr123 lvr123 - 2 months ago 37x
Java Question

Getting a OneNote token with Java

I fail to get a valid OneNote token from Java (in a desktop application).

I think I may not understand the whole process of authorization through an application. But I can't find information that clears this up.

Here is the Java code I use:

HttpsURLConnection refreshTokenConnection;
refreshTokenConnection = (HttpsURLConnection) (new URL(TOKEN_REQUEST_URL)).openConnection();
refreshTokenConnection.setRequestProperty("Content-Type", TOKEN_REFRESH_CONTENT_TYPE);

String redirect = URLEncoder.encode(TOKEN_REFRESH_REDIRECT_URL, "UTF-8");

try (OutputStream refreshTokenRequestStream = refreshTokenConnection.getOutputStream()) {
String requestBody = MessageFormat.format(TOKEN_REFRESH_REQUEST_BODY,
Constants.CLIENTID, redirect, ACCESS_SCOPE);
} catch (Exception ex) {
System.err.println("while writing request body");

if (refreshTokenConnection.getResponseCode() == 200) {
return parseRefreshTokenResponse(refreshTokenConnection);
else {
throw new Exception("The attempt to refresh the access token failed");

The response I get is an html reponse telling me that "Microsoft account is experiencing technical problems. Please try again later" !

<!-- ServerInfo: BL2IDSLGN1H030 2015. Live1 ExclusiveNew LocVer:0 -->
<!-- PreprocessInfo: BTSA007:RR1BLDF009, -- Version: 16,0,26014,0 -->
<html dir="ltr">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<base href=""/>

<title>Microsoft account</title>
<meta name="PageID" content="i4400">
<meta name="SiteID" content="38936">
<meta name="ReqLC" content="1033">
<meta name="LocLC" content=" ">
<style type="text/css">
body {
background-color: #fff;
color: #000;
font-family: "Segoe UI","Segoe UI Web Regular","Segoe UI Symbol","Helvetica Neue","BBAlpha Sans","S60 Sans",Arial,sans-serif;
font-weight: 400;
font-size: 15px;
line-height: 20px;
h1 {
line-height: 56px;
font-weight: 200;
margin: 20px 0;
h2 {
font-size: 34px;
font-weight: 200;
line-height: 40px;
padding: 3.18px 0;
p {
margin: 12px 0;
padding: 0.22px 0;
.header, .content {
width: 90%;
margin: 0 auto;
.logo {
vertical-align: middle;
.site-identifier {
line-height: 23px;
font-size: 17px;
margin-left: 15px;
padding-left: 15px;
border-left: 1px solid #aaa;
color: #aaa
.footer {
margin-top: 100px;
<script type="text/javascript">
function EndPPCRL(rs, u)
if (external)
if (rs)
external.RequestStatus = rs;
external.WebFlowUrl = u;
external._cW(); external.BrowseToAuthUI();
catch (e) { }
function BodyLoad()
<script type="text/javascript">
WizardExternalHelper = function(){ };
WizardExternalHelper.prototype =
setProperty: function(key, value)
window.external.Property(key) = value;
catch (e) { }
finalNext: function()
catch (e) { }
<script type="text/javascript">
var channelMessage =
type: "event",
name: "CloudExperienceHost.done",
data: "fail"
} catch (e) {};
var externalHelper = new WizardExternalHelper();
externalHelper.setProperty("ExtendedErrorString", "");
externalHelper.setProperty("ErrorCode", parseInt(1));
externalHelper.setProperty("ErrorString", "This service isn't available right now—please try again later.");
} catch (e) {};
function OnBack() {};
function OnNext() {};
<body onLoad="BodyLoad()">
<div class="header" id="idHeaderTD9">
<img src="images/ms-logo-v2.jpg" class="logo" alt=" " />
<span class="site-identifier">Account</span>
<div class="content">
<h2>We're unable to complete your request</h2>
<p>Microsoft account is experiencing technical problems. Please try again later.</p>
<!-- _i-Agent:Java/1.8.0_45 -->

Although If I'm using the same url directly in a browser, I'm redirected to a page where I must log-on and the accept the requested rights. From there, I received the tolken I'm looking for.

This is this latter step I'm failing to understand how to programmaticaly achieve : requiring the acceptance from the user.

== EDIT : OkHttp version ==

The code that brings me a step further:

private final String ACCESS_SCOPE = "office.onenote";
private final String TOKEN_REQUEST_URL = "";
private final String TOKEN_REFRESH_REDIRECT_URL = "";

HttpUrl base = HttpUrl.parse(TOKEN_REQUEST_URL);

HttpUrl hurl;
HttpUrl.Builder urlBuilder = new HttpUrl.Builder();

// response_type=token&client_id={0}&redirect_uri={1}&scope={2}
urlBuilder.addQueryParameter("response_type", "token");
urlBuilder.addQueryParameter("client_id", Constants.CLIENTID);
urlBuilder.addQueryParameter("redirect_url", TOKEN_REFRESH_REDIRECT_URL);
urlBuilder.addQueryParameter("scope", ACCESS_SCOPE);
hurl =;

Request request = new Request.Builder().url(hurl).build();

Response response = client.newCall(request).execute();

The response's body:

<!DOCTYPE html><!-- ServerInfo: BL2IDSLGN3C026 2015. Live1 Unknown LocVer:0 -->
<!-- PreprocessInfo: BTSA007:RR1BLDF009, - Version: 16,0,26014,0 -->
<!-- RequestLCID: 1033, Market:EN-US, PrefCountry: US, LangLCID: 1033, LangISO: EN -->
<html dir="ltr" lang="EN-US"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=Edge"/><base href=""/><script type="text/javascript">var PROOF = {};PROOF.Type = {SQSA: 6, CSS: 5, DeviceId: 4, Email: 1, AltEmail: 2, SMS: 3, HIP: 8, Birthday: 9, TOTPAuthenticator: 10, RecoveryCode: 11, StrongTicket: 13, TOTPAuthenticatorV2: 14, Voice: -3};</script><noscript><meta http-equiv="Refresh" content="0; URL="/>Microsoft account requires JavaScript to sign in. This web browser either does not support JavaScript, or scripts are being blocked.<br /><br />To find out whether your browser supports JavaScript, or to allow scripts, see the browser's online help.</noscript><title>Sign in to your Microsoft account</title><meta name="PageID" content="i5030"/><meta name="SiteID" content="279469"/><meta name="ReqLC" content="1033"/><meta name="LocLC" content="1033"/><link rel="shortcut icon" href="" />
<link rel="stylesheet" title="R3CSS" type="text/css" href=""/><style type="text/css"></style><style type="text/css">body{display:none;}</style><script type="text/javascript">if (top != self){try{top.location.replace(self.location.href);}catch (e){}}else{document.write(unescape('%3C%73') + 'tyle type="text/css">body{display:block !important;}</style>');}</script><noscript><style type="text/css">body{display:block !important;}</style></noscript><script type="text/javascript">var g_iSRSFailed=0,g_sSRSSuccess="";function SRSRetry(a,f,b){var e=1,d=unescape('%3Cscript type="text/javascript" src="'),c=unescape('"%3E%3C/script%3E');if(g_sSRSSuccess.indexOf(a)!=-1)return;if(typeof window[a]=="undefined"){g_iSRSFailed=1;b<=e&&document.write(d+f+c)}else g_sSRSSuccess+=a+"|"+b+","}
var g_dtFirstByte=new Date();var g_objPageMode = null;</script><link rel="image_src" href="" / >
<script type="text/javascript">var ServerData = {aU:',,urn:federation:MSFT|,,Test IDCRL Federation Partner',urlSwitch:'',aV:"Sign in to .",Bf:1000,AR:false,sCBUpTxt1:'',Bh:'',aX:"Use the primary phone number you\'ve associated with your Microsoft account. <a href=\"\" id=\"idPaneHelpOTCInfoLink9\" target=\"_blank\">Learn more</a>",m:true,AT:0,AU:{},sCBUpTxt2:'',Bi:'',n:false,o:'Pass',AW:'',p:'',q:true,AX:'',sFedQS:'wa=wsignin1.0&wtrealm=uri:WindowsLiveID&wctx=response_type%3Dtoken%26client_id%3D000000004017D35F%26redirect_url%3D',A:true,v:'',B:false,ab:'',urlPost:'',C:true,html:[],ad:'',D:1,str:[],a0:'4c7c1337346b4a0fb64b97945c57a0f4',F:'',Ab:{'Logo':'','LogoAltText':'','LogoText':'','ShowWLHeader':true},a1:'',BA:false,sErrTxt:'',ag:true,a2:'',a3:'',H:'',BC:true,a4:'',A0:true,BD:false,I:false,Ae:false,a5:'',oPost:{},urlFed:'',J:'response_type=token&client_id=000000004017D35F&redirect_url=',Af:0,A1:false,a6:'',BF:"Sign in",K:3,Ah:'',a7:'',A3:false,M:'',BI:'',A5:true,Ak:false,Al:1,P:'',Am:'##li16####B##Hotmail##/B####BR##The smart way to do email - fast, easy and reliable##li8####B##Messenger##/B####BR##Stay in touch with the most important people in your life##li10####B##SkyDrive##/B####BR##Free, password-protected online storage',A9:'',urlLogin:'',Ap:'',av:"#~#partnerdomain#~# does\'t use this service. Please sign in with a Microsoft account or create a new account. <a href=\"#~#WLPaneHelpInviteBlockedURL_LS#~#\" id=\"idPaneHelpInviteBlockedLink9\">Learn More</a>",V:'',ax:"A single-use code lets you sign in without entering your password. This helps protect your account when you\'re using someone else\'s PC. <a href=\"\" id=\"idPaneHelpOTCInfoLink9\" target=\"_blank\">Learn more</a>",aD:'',urlFedConvertRename:'',ay:"Your session has timed out. To request a single use code, please <a href=\"javascript:NewOTCRequest()\">refresh the page</a>.",Y:true,Av:{},AA:{},aE:'',aF:2,Ax:'',Ay:'',aI:true,AE:false,AF:"&copy;2016 Microsoft",sFTTag:'<input type="hidden" name="PPFT" id="i0327" value="DU2pRBKzRt7SzTHFM8igJwfODysa55R!ae1QZKYjexw1LLykan8u*bWZY83DjD37TbjlzVYQFFtP0PKHJ8up07drqwdOKsxwVDsn9n4be5u0oCzUyAEI1srL!hJNzzLCNCSTCyQA0oPQUd*R4!TP6Vfkc5TDWdTxKEV9aGCxstqeQFB28eikXz1M!gVZ7FyK2Q$$"/>',AG:'',sPOST_NewUser:'',AH:0,aL:true,b:'',aO:0,e:'',aP:1033,AM:'sign up',Ba:'',f:'',aS:'',Bc:false,AO:'',Bd:true};</script><script type="text/javascript" src=""></script>
<script type="text/javascript" src=""></script>
<script type="text/javascript">SRSRetry("__Login_Strings", "", 1);SRSRetry("__Login_Core", "", 1);</script><script type="text/javascript">SRSRetry("__Login_Strings", "", 2);SRSRetry("__Login_Core", "", 2);</script></head>
<body onload="evt_Login_onload(event);" uiTheme="Web">

And my app's API Settings:

Mobile or desktop client app:


Restrict JWT issuing:


Enhanced redirection security:


Target domain:

Redirect URLs:


The fact is that the authentication process requires a user interaction. It cannot be done by calling directly the url but by loading the url in a browser.

Here is illustrated the 2 steps authentification :

1) Get a temporary code, through user interaction;

2) Get a tolken with that code.

This example uses OkHttp for direct Http calls, Gson for json manipulation. And MozSwing as browser.

private final static Pattern PATTERN_EXTRACT = Pattern.compile(".*code=(.*)$", Pattern.CASE_INSENSITIVE);
private final static String GETCODE_URL = "";

* Step (1) : get a valide code through user interaction
public void requestCode() {

    SwingUtilities.invokeLater(() -> {
        String url = String.format(GETCODE_URL, _the_application_id_);

* Called when the browser triggers an event locationChanged()
public void locationChanged() {
    final String location = browser.getUrl();
    Matcher m = PATTERN_EXTRACT.matcher(location);
    if (m.matches() && m.groupCount() == 1) {

* Step (2) : get a valid tolken based on the newly aquired code
void setCode(String code) {
    try {

        RequestBody formBody = new FormEncodingBuilder()
                .add("client_id", _the_application_id_)
                .add("redirect_url", TOKEN_REFRESH_REDIRECT_URL)
                .add("client_secret", _the_application_secret_)
                .add("code", code)
                .add("grant_type", "authorization_code")

        Request.Builder reqBuilder = new Request.Builder();

        Request request =;

        final Call call = client.newCall(request);

        // exécution en synchrone
        Response response = call.execute();

        JsonObject refreshTokenResponse = UrlHelper.parseResponse(response);
        final JsonPrimitive at = refreshTokenResponse.getAsJsonPrimitive("access_token");
        if (at != null) {
            return true;

    } catch (Exception ex) {
        // TODO : add some error handling

 * Parse a OneNote HTTP reponse and returns its data as a JSonObject
 * @param response
 * @return
public static JsonObject parseResponse(Response response) {
    final String body;

    try {
        body = response.body().string();
    } catch (IOException ex) {
        throw new InvalidOnenoteContentExcepion("Unable to retrieve response content", ex);

    if (!response.isSuccessful()) {
        if (response.body().contentType().toString().startsWith("application/json")) {
            JsonObject message = ZJsonReader.getInstance().from(body);
            throw new ApiException(message, response.code(), response.message());
        else {
            throw new HttpException(response.code(), response.message());


    if (response.body().contentType().toString().startsWith("application/json")) {
        JsonObject refreshTokenResponse = ZJsonReader.getInstance().from(body);
        return refreshTokenResponse;
    throw new InvalidOnenoteContentExcepion("Invalid response content :\"" + response.body().contentType().toString() + "\"");