Salesforce Server-to-Server integration without any user involved - salesforce

I am working on a integration with Salesforce using REST APIs and, as part of the project, I need to send updates to Salesforce and these updates are not user triggered, they are system triggered.
Because of that, what I expect to see on Salesforce Field History is not a user name but the name of our Connected App (the app that made the update).
What I see today is the user name because the way the integration was made initially using OAuth Authorization Code flow.
To change that part of the project, I followed the link (OAuth 2.0 JWT Bearer Flow for Server-to-Server Integration): https://help.salesforce.com/articleView?id=sf.remoteaccess_oauth_flows.htm&type=5
Making that, I was expeting to generate a token for a System, not for a User, but that's not what happened: when I used the token generate from the JWT Bearer Flow and ran the update, the Field History still shows the user name.
What could I do then?
Which are the options in Salesforce to achieve the behavior I'm expecting?
The most important, in my opinion, is to have a Token for our system, not for a user.
Thanks!

Everybody is an user in Salesforce. Even if you access unauthenticated pages (some contact us form? case or lead capture) - it gets tracked under special Guest User.
It sounds stupid but gives you unified interface to control permissions (Profiles/Permission sets). You want guests to access only FAQ articles and make cases? Sure thing, do it in profile, don't get paranoid about people trying to guess right URLs. You think an app was hacked? You can terminate the session just like any other "user". Want to allow login only in certain hours and from certain IP? Sure.
An app connecting with JWT will still need username (main difference being it's "just" certificate for signing the request instead of password).
Your best bet is to create dedicated "Mr System", "SystemX integration" account. It sounds like waste of license but in the long run saves you questions "why did you edit my account at 1 am" and you could even use it as backup account if you use SSO and it ever fails...

Related

Use Microsoft OAuth to authenticate our own operations

We have built a React web application that authenticates users with Microsoft via OAuth ( #azure/msal-browser package). Users are redirected to Microsoft auth page during signin, and then redirected back to our site once authentication has completed successfully. This is all working as expected.
However, we are in a position where we wish to add a custom PIN mechanism to protect some of our workflows. PINs will be encrypted/salted and stored in our own API, along with the existing mapping between Microsoft/Azure users and our own user state/records. In order for users to change/reset their PIN, we want to force them to reauthenticate with Microsoft before changing their PIN. I have not dealt with OAuth2 in a while, and am not entirely certain how this might be possible (since current auth workflow does not involve our server at all).
Ideally, users would navigate to the "Reset PIN" page and initiate the workflow. If possible, authentication would be handled through a pop-up (so as to not lose page state), which I think is possible as per documentation? If this is not possible, even a redirect to the same page with a specific query parameter (to indicate post-authentication) could work. The user would then be able to change/confirm their new PIN. At this point, a request would be sent to our API, including both the PIN and something from Microsoft that would allow our server to validate that the user did indeed just re-authenticate (proving they can change the PIN).
The primary sticking point is that our API must be able to verify that the user has just re-authenticated with Microsoft! One way to think about it would be that if a user gained temporary access to an unlocked authenticated workstation, they should not be able to perform restricted actions (as they do not know the PIN), nor be able to change the PIN (as they do not know the user's credentials). Yes, yes, I know physical access is effectively a compromise to any security, but this is a higher-level requirement...
I am guessing this workflow is possible, but am not certain how it might be possible. Would we use a different authentication workflow for this particular use case? Any pointers on a workflow we could investigate or use for this?
I can give you some info about how this should work. This type of flow can require a high level of extensibility in the authorization server though.
CLIENT REDIRECT
The client can send the OpenID Connect acr_values parameter, indicating the assurance levels it requires. In your case you would send two values.
CUSTOM AUTHENTICATION FACTOR
The user will perform standard authentication first, eg passwords. Then you would implement a custom second factor that uses the user identity and some custom logic to call your custom API.
ACCESS TOKENS
After authentication has completed, the authorization server will issue access tokens to the client. High privilege claims should only be included when strong authentication has been used. Some kind of scripting would be used here, that can read authentication result attributes.
API AUTHORIZATION
APIs should receive short lived access tokens. If it contains the high privilege claim, you know that your PIN requirements have been met.
CAN YOU SIMPLIFY?
It feels suspect to do your own PIN management. Can you outsource this, eg use a second factor of time based one time password (TOTP) instead? Mobile platforms such as the Google authenticator app provide tested solutions.

How to communicate securely to an Database with electron?

I am creating an electron application that connects to an Database and do POST and GET requests to retrieve and insert data into it, the problem is that in the code i have defined my database uri ( im using mongodb)
const uri = "mongodb+srv://<myusesrname>:<mypassword>#cluster0.wqbiu.mongodb.net/query?retryWrites=true&w=majority"
like in the example above, but if i pack my electron app the connection to the database as well as the credentials its visible if someone unpacks the app.asar file and look in the server.js file how i can solve this problem? i dont want any security breaches neither for me or the people that will be using my application, thanks in advance for any answer :)
An application that requires a secure connection to something cannot afford to have any username's or password's hardcoded into its code.
Instead, a procedure of authentication and authorisation is utilised.
Authentication is used to verify the user. IE: They are who they say they are, often achieved via the use of some type of login form.
Authorisation is used to verify the logged-in user is allowed to access the requested resource. EG: Is this user allowed to retrieve a list of all users email addresses from the database.
As a rough guide, a user will login with their username and password. You could use OpenID as well here if you wanted. Once the user is 'logged-in' you could set a cookie or session and save the session id in the DB against the user. Of course, all of this is done over HTTPS.
There are various ways to control the validity of the session such as but not limited to refreshing the expiration date / time every time the user hits the server, auto timeout if the user has not interacted with the server for more than X minutes, etc.
In your app, the user could try and interact with the database at any time, but if the user is not logged in, the server could return the appropriate response and prompt the user to login. Some form of API here is really the way to go.
If the user is logged in then then next step is to authorise the users request, ensuring they are allowed to perform what they are asking before sending a response back. If they are not authorised to access the resource (EG: Edit another user’s post) then an appropriate response is returned indicating so.
As you can see, securing your app will take some work but the result of not doing so could be devastating to you and your users.

Sitecore - How to get User ID if the user was logged in using external identity provider (Salesforce SSO)

I have a little bit of problem with the authentication on Sitecore website. Basically there is a button on the navbar, and when user clicks on the button, it redirects the same user to Salesforce to log in (Implementation of SSO). Basically I am using Salesforce as a identity provider and Sitecore Website as a service provider. Now I have a question? When user is logged, how can I get the ID of that user.
Do users in Sitecore User Manager have the same ID as the users in Salesforce, or I can just get a email to identify the user?
P.S: Sorry if this is a really stupid question, but I am a begineer when it comes to making Sitecore websites and the SAML SSO. Thank you in advance
Stop with the Sitecore and Salesforce for a second, you'll need to cover some basics and click through the login process manually before you automate it.
You probably are using a "connected app" in Salesforce that includes OAuth2 config (consumer key also known as client id; a secret; a list of scopes telling what this app is allowed to do on behalf of this SF user; a list of allowed urls that can login using this consumer key and secret. Etc.) It might even have something about Canvas Apps at bottom of the page.
Next would be - who's logging in. A core Salesforce user or do you have Partner Community, Customer Community (recently rebranded to "Digital Experiences").
Open incognito window and go to https://openidconnect.herokuapp.com/
For login host leave as is if you have production user or test.salesforce.com if you go from sandbox (you can also use branded urls, mycompany--dev.my.salesforce.com etc). If you have a community user you'll have to change the url to whatever is the community base url, like https://dev-mycompany.cs123.force.com/mycommunity
Don't change anything else, click next, next, next. This will take you through OAuth2 "web server flow" (one of many ways to log in). You type the username/password to SF screen and go back to that herokuapp with "authorisation code". The app has few minutes to swap that code for actual final "access token" and couple other pieces of info. Final step in this wizard calls OpenId "userinfo" - returning some info about the user that logged in. That's where you could pull the email if needed (and if there are extra fields you'd like SF to return in this process that's configurable too)
Close that browser window. Check the "connected app" in SF. Open new incognito window, do same thing but this time put your url, consumer key and secret (you might have to edit the app in SF first to allow callbacks to https://openidconnect.herokuapp.com/callback).
So now you should have rough idea about whole login process. Your sitecore app probably does same thing, receives authorisation code and exchanges it for final token. At that point you have valid SF session ID you could use to call that "userinfo", run queries (if the app allowes API access, check the "scopes") etc.
I doubt the Sitecore developer created it all by hand, you probably have some Spring stuff like spring.security.oauth2.client... My Java days are long gone but if you get better at manual click-click-click through the flow you should be able to follow existing code?
It's a big topic and there are other ways to do it (other OAuth flows, sending info about the current user when you have external page embedded in SF as iframe, you'd need to read about "canvas apps")... but that's best guess based on info you provided. You might want to check some trailhead courses too like https://trailhead.salesforce.com/content/learn/projects/build-a-connected-app-for-api-integration/implement-the-oauth-20-web-server-authentication-flow
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_oauth_and_connected_apps.htm
https://developer.salesforce.com/docs/atlas.en-us.api_streaming.meta/api_streaming/code_sample_auth_oauth.htm (Java but very hand-crafted raw HTTP, probably that Spring security is better)

Salesforce: How to automate report extraction as JSON/CSV

I am new to Salesforce, but am an experienced developer. I am provided a link to a Salesforce report, which mostly has the right filters (query). I would like to use an REST API to pull that information as CSV or JSON so that I can do further processing on it.
Here are my questions:
Do I need special permissions to make API calls? What are they?
Do I need to create an "app" with client-key & secret? Does my admin need to grant me permission for this too?
There are a lot of REST APIs from Salesforce, which one do I need to get the info from the report? Analytics?
How do I authenticate in code?
You'd have to work with the System Administrator on the security pieces. Anybody who knows how the company works, can all users see everything, is there Single Sign-On in place, how likely is the report to change...
You will need an user account to pull the data. You need to decide if it'll be some "system account" (you know username and password and have them stored in your app) or can it run for any user in this org. It might not matter much but reports are "fun". If there will be data visibility issues 6 months from now, you'll be asked to make sure the report shows only French data to French users etc... you can make it in report filters or have multiple reports - or you can just use current users access and then it's the sysadmin that has to set the sharing rules right. (would you ever think about packaging what you did and reusing in another SF instance? Making a mobile app out of it? Things like that, they may sound stupid now but will help you decide on best path)
The user (whether it'll be system account or human) needs Profile permissions like "API Enabled" + whatever else you'd need normally ("Run Reports" etc). If you're leaning towards doing it with system user - you might want to look at Password Policies and maybe set password to Never Expires. Now this is bit dangerous so there would be other things you might want to read up about: "API only user" (can't login to website), maybe even locking down the account so it can login only from certain IP ranges or at certain times when the job's supposed to be scheduled...
Connected App and OAUth2 stuff - it's a good idea to create one, yes. Technically you don't have to, you could use SOAP API to call login, get session id... But it's bit weak, OAuth2 would give you more control over security. If you have sandboxes - there's little-known trick. You can make connected app in production (or even totally unrelated Developer Edition) and use client id & secret from it to login to sandboxes. If you create app in sandbox and you refresh it - keys stop working.
(back to security piece - in connected app you can let any user allow/deny access or sysadmin would allow only say these 3 users to connect, "pre-authorize". Could be handy)
Login - there are few REST API ways to login. Depends on your decision. if you have 1 dedicated user you'll probably go with "web server flow". I've added example https://stackoverflow.com/a/56034159/313628 if you don't have a ready SF connection library in your programming language.
If you'll let users login with their own credentials there will be typical OAuth "dance" of going to the target page (Google login, LinkedIn, Twitter...) and back to your app on success. This even works if client has Single Sign-On enabled. Or you could let people type in their username and pass into your app but that's not a great solution.
Pull the actual report already
Once you have session id. Official way would be to use Reporting API, for example https://developer.salesforce.com/docs/atlas.en-us.api_analytics.meta/api_analytics/sforce_analytics_rest_api_get_reportdata.htm
A quick & dirty and officially not supported thing is to mimic what happens when user clicks the report export in UI. Craft a GET request with right cookie and you're golden. See https://stackoverflow.com/a/57745683/313628. No idea if this will work if you went with dedicated account and "API access only" permission.

Azure AD | Conflict when logged in with another Azure Account

I have a Asp.net MVC application that uses Azure AD and OpenID Connect OWIN middlewares to handle authentication. Everything works fine except for one thing : if a user is already logged-in on another Microsoft Application lets say a Office 365 account or maybe a live mail account, when trying to login it recives a page saying that it is not allowed to log into my app, which is correct, but some how I need to catch that situation in my code to allow the user to sign in with a different account. Is there a way of doing that? This is by design? I mean : the user have to log in only with a live/azure account at the time ? I couldn't find any documentation about this.
As of today there is typically one user at a time, but we will soon support for you a way to select a specific user instead of automatically signing you in with the most recent one.
One way you can work around this today is by injecting the parameter "prompt=login" in your sign in requests. You can do that in the RedirectToIdentityProvider notifications, similarly to what is showin in http://www.cloudidentity.com/blog/2014/11/17/skipping-the-home-realm-discovery-page-in-azure-ad/ for domain_hint. This will cause the sign in experience to always start with a fresh prompt even if the user is already signed in. The draw back is that you'll never get SSO this way. Hopefully our account switiching feature will become available soon, keep an eye on http://blogs.technet.com/b/ad/ for announcements

Resources