authenticate to SharePoint through OKTA from back-

2020-03-30 04:36发布

问题:

I have a need to programmatically connect to a customer's SharePoint server that uses OKTA for authentication. I saw this post which looked promising, but cannot seem to get a valid session cookie back from OKTA.

I can successfully call the /api/v1/authn endpoint and get back a sessionToken, but when I turn around and call /api/v1/sessions?additionalFields=cookieToken with that session token, I always received a 403 - Forbidden, with the following json:

{ 
"errorCode": "E0000005", 
"errorSummary": "Invalid Session", 
"errorLink": "E0000005", 
"errorId": "oaew0udr2ElRfCnZvBFt075SA", 
"errorCauses": [] 
}

Assuming I can get this resolved, I'm not sure of the URL I should call with the cookieToken. Is the url an OKTA endpoint that will redirect to SharePoint or is it an SharePoint endpoint that will setup the session with the cookie?

Update: I am able to call this okta endpoint -> /api/v1/sessions?additionalFields=cookieToken with my user credentials as json

{ 
"username": "user@email.com",
"password": "P@ssw0rd"
}

And am able to retrieve a one-time cookie token that can be used with this link to start a SAML session in a browser:

https://[mydomain].okta.com/login/sessionCookieRedirect?redirectUrl=[sharepoint site url]&token=[cookie token]

That works in a browser, the user is automatically authenticated and ends up in SharePoint. However, it seems that this session "setup" is at least partly achieved through javascript as executing the same link in a programmatic HTTP client (such as Apache HTTP Client) does not work. The http client is sent through a couple of redirects and ends up in the SharePoint site, but the user is not authenticated. The response is 403 - Forbidden with the following headers:

403 - FORBIDDEN

Content-Type -> text/plain; charset=utf-8
Server -> Microsoft-IIS/8.5
X-SharePointHealthScore -> 0
SPRequestGuid -> 0ecd7b9d-c346-9081-cac4-43e41f3b159a
request-id -> 0ecd7b9d-c346-9081-cac4-43e41f3b159a
X-Forms_Based_Auth_Required -> https://[sharepoint site]/_login/autosignin.aspx?ReturnUrl=/_layouts/15/error.aspx
X-Forms_Based_Auth_Return_Url -> https://[sharepoint site]/_layouts/15/error.aspx
X-MSDAVEXT_Error -> 917656; Access denied. Before opening files in this location, you must first browse to the web site and select the option to login automatically.
X-Powered-By -> ASP.NET
MicrosoftSharePointTeamServices -> 15.0.0.4709
X-Content-Type-Options -> nosniff
X-MS-InvokeApp -> 1; RequireReadOnly
Date -> Fri, 13 May 2016 15:02:38 GMT
Content-Length -> 13

I'm starting to wonder if this is a lost cause, that OKTA or SharePoint doesn't support programmatic authentication via SAML.

回答1:

It's possible.

Here is what I did. 1) Get your sessionToken from Okta. You'll need an okta authorization token for that.

2) Do a HttpGet(sharepointEmbeddedLink + "?onetimetoken=" + sessionToken) Also add this header: new BasicHeader(AUTHORIZATION, String.format("SSWS %s", OKTA_AUTHORIZATION_TOKEN);

3) Next you'll have to parse the html response and get the SAML Arguments: WRESULT, WCTX, WA

4) Next do this - take those 3 and create a string in this format "application/x-www-form-urlencoded". It will be something like this "wa=wsign1.0&wctx=somevalue&wresult=somevalue".

        byte[] out = theStringAbove.getBytes;
        int length = out.length;

        URL url = new URL("https://login.microsoftonline.com/login.srf");
        URLConnection con = url.openConnection();
        HttpURLConnection http = (HttpURLConnection) con;

        http.setRequestMethod("POST"); // PUT is another valid option
        http.setDoOutput(true);
        http.setInstanceFollowRedirects(true);
        http.setFixedLengthStreamingMode(length);
        http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        http.setRequestProperty("User-agent", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.215 Safari/535.1");
        http.connect();
        http.getOutputStream().write(out);

5) You'll have the saml Token in the response. You'll have to parse an html file again.

6) You'll get the sharepoint siteUrl in step3 or 4 and do this next :)

    HttpPost httpPost = new HttpPost(siteUrl + "_forms/default.aspx?wa=wsignin1.0");
    byte[] utf8TokenStringBytes = ("t=" + samlToken).getBytes(StandardCharsets.UTF_8);
    HttpEntity entity = new ByteArrayEntity(utf8TokenStringBytes);
    httpPost.setEntity(entity);
    httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
    httpPost.setHeader("User-agent", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.215 Safari/535.1");

    HttpResponse response = httpclient.execute(httpPost, httpContext);

If everyting is ok, you'll have some cookie headers that you can use :D