Question

I'm tried to implement SSO for SalesForce using OpenSAML. My code generates valid SAML assertion, which validated by salesforce SAML validator. But when I tried to send assertion to salesforce I always got this error:

{"error_uri":"https://na4.salesforce.comnull/setup/secur/SAMLValidationPage.apexp","error":"invalid_grant","error_description":"invalid assertion"}

I using folloving code to send request to salesforce:

    SAMLResponseGenerator responseGenerator = new SalesforceSAMLResponseGenerator(container, strIssuer, strNameID, strNameQualifier, sessionId);

    String samlAssertion = Base64.encodeBase64String(responseGenerator.generateSAMLAssertionString());
    try {
        HttpClient httpClient = createHttpClient();
        HttpPost httpPost = new HttpPost("https://login.salesforce.com/services/oauth2/token");
        MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
        entity.addPart("grant_type", new StringBody("assertion"));
        entity.addPart("assertion_type", new StringBody("urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser"));
        entity.addPart("assertion", new StringBody(samlAssertion));
        httpPost.setEntity(entity);
        HttpResponse httpResponse = httpClient.execute(httpPost);

        // Get the response
        BufferedReader rd = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
        StringBuffer buffer = new StringBuffer();
        String line = null;
        while ((line = rd.readLine()) != null) {
            buffer.append(line);
            buffer.append("\n");
        }
        rd.close();
        httpClient.getConnectionManager().shutdown();
        System.out.println(buffer.toString());
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

My generator generated valid SAML (If I can trust salesforce SAML validator results). Seems that salesforce can't decode assertion, because when I sent random data instead of samlAssertion I've recieved same error message.

I also tried to use Base64.encodeBase64URLSafeString() to encode but without positive results.

Can anyone help me with this issue?

Was it helpful?

Solution

Solution of my problem was very simple. Do not trust SalesForce's documents, trust only protocol specs :) According to specs I needs to send Base64 encoded SAML in SAMLResponse parameter. That is all.

I've using following code illustrated the solution:

    HttpClient httpClient = initHttpClient();
    HttpPost httpPost = new HttpPost("https://login.salesforce.com/");
    MultipartEntity entity = new MultipartEntity(HttpMultipartMode.STRICT);
    entity.addPart("SAMLResponse", new StringBody(Base64.encodeBase64String(samlAssertion)));
    httpPost.setEntity(entity);
    HttpResponse httpResponse = httpClient.execute(httpPost);

    Header location = httpResponse.getFirstHeader("Location");
    if (null != location) {
        System.out.println(location.getValue());
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top