Hi and thanks for taking this time to look,
I've recently been asked to investigate integration using CRM Online 2015, I've come across some issues trying to Authenticate using Raw SOAP requests.
While I know there's other ways to authenticate, predominantly the using the CRM SDK, my iron will is pushing me to find a solution using Raw SOAP.
I came across a very helpful blog by Jason Lattimer: http://jlattimer.blogspot.co.uk/2015/02/soap-only-authentication-using-c.html
Following this sample, I successfully authenticated with a Trial CRM account using RAW SOAP... Great... Done... I was wrong.
As soon as I pointed this sample at the CRM development environment I got a SOAP error:
<?xml version="1.0" encoding="utf-8" ?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:psf="http://schemas.microsoft.com/Passport/SoapServices/SOAPFault">
<S:Body>
<S:Fault>
<S:Code>
<S:Value>S:Sender</S:Value>
<S:Subcode>
<S:Value>wst:FailedAuthentication</S:Value>
</S:Subcode>
</S:Code>
<S:Reason>
<S:Text xml:lang="en-US">Authentication Failure</S:Text>
</S:Reason>
<S:Detail>
<psf:error>
<psf:value>0x80048821</psf:value>
<psf:internalerror>
<psf:code>0x80047860</psf:code>
<psf:text>Direct login to WLID is not allowed for this federated namespace</psf:text>
</psf:internalerror>
</psf:error>
</S:Detail>
</S:Fault>
</S:Body>
</S:Envelope>
The only difference I can think between the Trial version which worked and the development environment is that the development environment setup uses ADFS / AD On-Premises.
Fiddler logs show that Jason's Sample goes straight to login.microsoftonline.com whereas CRM SDK (which works) goes to dynamicscrmemea.accesscontrol.windows.net.
So I believe this is the problem area!
I've been around in circles on stack overflow/other sources, I have a feeling it will a relatively small change required to the SOAP request but I've reached the point where I need some fresh eyes/advice.
Has anyone had experience with this setup? Can anyone gently push me in the right direction?
Many Thanks
Gareth
We experienced a similar issue, attempting to create a BizTalk integration. Eventually we resolved the issue by using a Windows Live/Office 365 account to actually connect with, rather than one that authenticated against the actual AD. CRM determines authentication types by User, not by org, so you can mix and match...
Related
Im completely new to Salesforce and API's.
Im trying to make a Merge record call using SOAP API . Using Postman for the same .
I have imported the WSDL to my local , Called Login method to get the serverURL and sessionId.
Using these parameters to make subsequent merge calls .
During the login , I have used username and password to authenticate .
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<login xmlns="urn:enterprise.soap.sforce.com">
<username>username</username>
<password>password+auth_token</password>
</login>
</soap:Body>
</soap:Envelope>
and getting the below response:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:enterprise.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<loginResponse>
<result>
<metadataServerUrl>https://**company_name**--dev.my.salesforce.com/services/Soap/m/54.0/00D0Q0000000QP8</metadataServerUrl>
<passwordExpired>false</passwordExpired>
<sandbox>true</sandbox>
<serverUrl>https://**company_name**--dev.my.salesforce.com/services/Soap/c/54.0/00D0Q0000000QP8/0DF0Q0000004Ct6</serverUrl>
<sessionId>**masked**</sessionId>
<userId>xxx</userId>
<userInfo>
.....
</userInfo>
</result>
</loginResponse>
</soapenv:Body>
</soapenv:Envelope>
Later im making the Merge call using the session ID returned from the above .
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com"> xmlns:sobject="urn:sobject.enterprise.soap.sforce.com">
<soap:Header>
<urn:SessionHeader>
<urn:sessionId>**masked**</urn:sessionId>
</urn:SessionHeader>
</soap:Header>
<soap:Body>
<merge xmlns="urn:enterprise.soap.sforce.com">
<request>
<masterRecord xsi:type="sobject:Account" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Id xmlns="urn:sobject.enterprise.soap.sforce.com">0010Q00001abcdefgh</Id>
</masterRecord>
<recordToMergeIds>0010Q00001ijklmnop</recordToMergeIds>
</request>
</merge>
</soap:Body>
</soap:Envelope>
and able to merge the records.
My question is - what should the body be if i donot want to use username and password but use Bearer token.
Can i call the login method without passing username and password?
You might be a victim of XY problem. You can't do it in SOAP API, will REST API be an option?
SOAP API's login call demands username and password (+ optional "security token", extra thing you add to password if you log in from untrusted IP). There are no other ways around it.
REST API has more options for logging in but it'd help if you read up about OAuth2 a bit before diving in. You call login and (similar to SOAP API) get back endpoint to use from now on and access_token. That access_token acts like SOAP APIs session id, you use it in next requests. Most of the time they should be interchangeable, access_token obtained via REST should be good to use in SOAP API calls.
If you already have session id / access token (will look like "00D...!....", first part is org id which you can see in Setup -> Company information for example) - you don't need login call. Call the SOAP API's merge directly and pass that value in <urn:sessionId>.
If you don't have session id, want to log in but without hardcoding username and password in your application... You have LOTS of options. Selecting right method is an art and it depends what are you making. A website, a mobile app? For internal users or community? Will it hold some credentials (for example if it needs sysadmin powers, working in background without human interaction) or will it show users the SF login screen and redirect back to the app? There's even "Internet of Things" stuff for pieces of equipment reporting their status to SF or logging in on device without keyboard (TV, fridge) where you initiate process there and finish on laptop or phone...
If you've never heard about OAuth2 before it's a big topic, "login with Google/Facebook/Twitter/LinkedIn" is just a piece of it. You'll be better off reading some blogs, checking out https://trailhead.salesforce.com/en/content/learn/trails/build-integrations-using-connected-apps or even studying to the Identity and Access Manager certification. Clicking through https://openidconnect.herokuapp.com/ might help too.
There's "username-password flow" which looks almost like SOAP API's login.
There's web server flow and user-agent flow for websites & mobile apps to send user to SF login screen (can be really SF, can be some single sign-on, doesn't matter) and back to the app. So your app doesn't see the password, doesn't see any credentials
There's refresh token option in some of these flows (you logged in once with another method, your app received access_token but also refresh_token. When access expires - app can use refresh_token to silently get back to the system without asking user to log in again. For 60 days for example). So you could still have initial "human authorises connection between the apps" but then it can just work in the background
There's JWT flow which you'll have hard time trying in Postman but there are examples such as this and this. You establish trust between SF and your app by uploading a certificate to Salesforce, marking user as allowed to use this method and then the app sends a special request just with username, no password needed.
We are integrating the Sonos API.
We chose not to implement token refresh and so our tokens last for 1 year until when the user has to reauthorize again.
During my tests, I successfully get the reauthorize popup when the AuthTokenExpired fault is returned while browsing (in response to getMetadata).
But every time the Fault is returned from a call to getMediaMetadata, I get the default error message "Unable to play the radio station". I would expect to see the reauthorize popup instead.
Quoting from Sonos documentation about authentication tokens :
If you do not implement refresh tokens, when the token expires, return the Client.AuthTokenExpired fault to indicate the user must manually log in and authenticate again. The Log-Message is a string placed in the log messages for this fault code.
Here is the problematic dialog between our SMAPI server and Sonos application/speaker :
31/03/2020 14:24:27 641 SonosApi Request http://www.sonos.com/Services/1.1#getMediaMetadata "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<credentials xmlns="http://www.sonos.com/Services/1.1">
<deviceId>78-28-CA-9F-86-8E:8</deviceId>
<deviceProvider>Sonos</deviceProvider>
<loginToken>
<token>1fa35465a-6bbc-4cf4-b46f-0e12be5b3216</token>
<householdId>Sonos_W6VyCDwgI8ZadAWceKQ1avPrtd</householdId>
</loginToken>
</credentials>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://dev8.local.st-corp.fr:8001/SonosService.svc</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.sonos.com/Services/1.1#getMediaMetadata</Action>
</s:Header>
<s:Body>
<getMediaMetadata xmlns="http://www.sonos.com/Services/1.1">
<id>14740</id>
</getMediaMetadata>
</s:Body>
</s:Envelope>"
31/03/2020 14:24:27 875 SonosApi Reply "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<s:Fault>
<faultcode>s:Client.AuthTokenExpired</faultcode>
<faultstring xml:lang="fr-FR">The token is expired</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>"
Edit:
Refering to the updated documentation and your answer, I should only return AuthTokenExpired fault in calls to getMetadata and getMediaUri.
But what should I answer to a call to getMediaMetadata knowing that the access token is expired ?
Looking at my messages logs, I see that when a user click on a streamable item, the following calls are made in the following order :
getMediaMetadata (what would be the answer here knowing the token is already expired ?)
getMediaUri (AutTokenExpired should be handled here)
Correct me if I am wrong, but in order to build the call to getMediaUri, the Sonos client use the id returned from the last call to getMediaMetadata, which I can't provide because the token is already expired. Wouldn't it be better to handle AuthTokenExpired first in getMediaMetadata ?
Regards
The browse (getMetadata) and getMediaURI calls will respect the AuthTokenExpired fault. The re-authorization flow for these calls work as described in the Refresh expired authentication tokens section of the Use authentication tokens documentation. I'll update the documentation to reflect this.
If this does not work, submit a diagnostic to debug it. See support.sonos.com/s/article/141 for instructions. Copy your diagnostic number and email it to developer-feedback#sonos.com along with the time window, Sonos household ID, and your StackOverflow username.
You mentioned that when you send a fault in response to getMediaURI, you get an error message, but your example shows a getMediaMetadata call.
Sonos does not launch the re-authorization wizard when your server returns an AuthTokenExpired fault for getLastUpdate. When the Sonos speaker makes a getMediaMetadata call and it fails, it does not start playback. The user will also see that playback failed.
I'm using Yodlee SOAP API endpoints and in my error logs I'm getting Site Refresh Status as LOGIN_FAILURE with error code 0 (which as I understand is not an error according to Yodlee docs). I was wondering what could be the cause of this? Is it an expected behavior? I'm assuming this is not a successful login.
Here is the returned xml:
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns21:getSiteRefreshInfoResponse xmlns:ns21="http://refresh.refresh.core.soap.yodlee.com">
<getSiteRefreshInfoReturn><siteRefreshStatus>LOGIN_FAILURE</siteRefreshStatus>
<siteRefreshMode>NORMAL_REFRESH_MODE</siteRefreshMode>
<code>0</code>
</getSiteRefreshInfoReturn>
</ns21:getSiteRefreshInfoResponse>
</soapenv:Body></soapenv:Envelope>
Thanks,
I contacted Yodlee Support and I got the answer that it is expected behaviour and users need to login again to get the instant refresh and refreshing sites should work again.
I created a demo to demonstrates a problem (cache?) in PDP API on WSO2 IS.
My demo creates a policy and two tests to validate, and result OK (first test PERMIT and second DENY)
On first run, the results are displayed correctly (OK).
Via Carbon web interface, I delete all policies in PAP (and PDP), and ran again my Python demo, and the result is wrong (two tests result DENY).
My demo (see the README file for environment and configuration details):
https://github.com/welkson/WSO2-PDP-CacheTest
I've tried to disable caching of WSO2, but had no effect.
Tested with WSO2 IS 5.3 and 5.4.0-alpha2.
Looks like its the same issue as that is reported
in https://wso2.org/jira/browse/IDENTITY-5603. I have increased the priority so that this will be addressed in the next immediate release.
You can follow up with JIRA for the the progress of the fix.
Possible Workaround:
Clear the cache using the EntitlementAdminService
https://localhost:9443/services/EntitlementService?wsdl
Follow [1] to get an idea on how to invoke admin services.
Request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://org.apache.axis2/xsd">
<soapenv:Header/>
<soapenv:Body>
<xsd:clearPolicyCache/>
</soapenv:Body>
</soapenv:Envelope>
[1] https://docs.wso2.com/display/IS530/Entitlement+using+SOAP+Service
I've gone through the steps shown here https://developer.intuit.com/docs/0100_quickbooks_online/0100_essentials/000300_your_first_request/first_request_with_postman#/Configuring_the_Postman_Authorization_header-1500 to use Quickbook's API Collection for Postman.
In Postman, I was successfully able to get a new access token. I also updated the {{baseurl}} to be "sandbox-quickbooks.api.intuit.com", and updated the {{companyid}} (aka the "RealmId") to be the appropriate value as shown in the "Manage Sandboxes" page of the developer site (i.e. https://developer.intuit.com/v2/ui#/sandbox).
BUT when I click "send" on the "Customer-ReadById" query (or any other query in the collection), I get the following Authentication error:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3" time="2017-08-16T11:52:00.611-07:00">
<Fault type="AuthenticationFault">
<Error code="100">
<Message>General Authentication Error</Message>
<Detail>AuthenticationErrorGeneral: SRV-110-Authentication Failure , statusCode: 401</Detail>
</Error>
</Fault>
</IntuitResponse>
My next step was to verify that I can query my sandbox using the OAuth 2.0 Playground tool on the developers site, which I can indeed do.
My questions then are: why am I getting this authentication error in Postman? Am I missing a step? Or has something changed in the Quickbooks Online API that has not yet been documented?
EDIT: I've managed to resolve my own issue after a decent amount of trial and error, and with a hint based on a response in the Quickbooks Online help area.
For those who may find this useful, my solution was to request a new access token (click "Get New Access Token" in Postman) and updated the "Scope" section to include "openid" such that the space delimited list read:
com.intuit.quickbooks.accounting openid profile email phone address
Using this new token with the updated scope allowed me to get the desired results.
I had the same problem but I resolved it differently. My issue was that in the requested token, the default to "Add token to" is URL, but it seems that the API requires the token to be in an Authorization header. Changing this to "Header" does just that.
For the "Customer-ReadById" endpoint, the only scope that should be necessary is com.intuit.quickbooks.accounting. My guess is you changed it to Header in your trial and error.