I wrote a web application which connects to the Salesforce API using the OAuth 2.0 web server flow, and that all works fine.
But now there is a requirement to access the
redirect uri doesn't have to be public. It can be localhost:somePort
and your application would have to be listening to traffic on that port.
For example if you want to develop SF code using SFDX CLI + Visual Studio Code - there's a nice way to authorise access to SF org where you type your credentials on the website but when all is good - the OAuth piece gets sent to localhost:1717
. As long as nothing else is listening on this port you're fine. Similar with Salesforce Data Loader - you can type username and pass to it but it also has this web-based flow. And sometimes it's the only option really, if your SF admin enabled Single Sign-On that authenticates against Active Directory/Google/Facebook/... - you might not be able to use SF username and password.
My C# days are long gone but listening on a port on local machine shouldn't be the end of the world? You shouldn't need a full-blown web server bundled with your app...
https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow has some good theory
https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.tcplistener?redirectedfrom=MSDN&view=netcore-3.1 example code?
As eyescream's answer explains, there are security issues with the Webserver flow, since any malware listening to that port could also access the security token.
Thus, I want to explain how to use the User-Agent flow in this scenario:
Set REDIRECT_URI
to any https-endpoint that you trust. Since your data will never reach that endpoint, it doesn't matter what endpoint you choose.
For example, I use REDIRECT_URI = https:\\login.salesforce.com\
, since I am sure that Salesforce themselves will not do anything harmful with a token to their own API, in case something goes wrong and they do actually receive it.
Since you are using a browser (CefSharp) directly in your application, you have access to the URL string. I do not know CefSharp, but I am sure there is something like a BeforeRedirect
event which tells you the URL before actually redirecting.
Before every redirect, search the URL string for "access_token="
. If you find that string, extract the token from the URL string and close the browser.
Make sure that you close the browser before the redirect. This ensures that the token never reaches the endpoint you chose in step 1.