Is it possible to setup Single sign-on for a Single Page Application that will initiate the SSO from an arbitrary (not pre-approved) domain? - security

Our scenario is the following:
We have an SPA that we package and send to multiple customers.
The customers hosts the SPA on an arbitrary domain like www.unknown.com/spa/anything-goes, or www.also-unknown.com/spa/really-anything-goes, etc.
The customer also opens the SPA in a popup window and injects a service to communicate back and fourth from the popup (the SPA) and the main window.
The SPA uses our own API service, lets call it www.backend.com, as a backend.
The SPA also uses the service that is injected into the popup window by the opener (the customer website), meaning the main popup (where the SPA is loaded) window can't directly redirect to a common login page, because that will interrupt the connection to the injected service, and we can't modify the customer code to make it more robust).
We want to let the user of the SPA authenticate against our backend (www.backend.com) using SSO (their Microsoft credentials)
For any given (fixed) domain, we can make this work by approving the exact domain as an allowed Redirect URI in AzureAd, and just using the MSAL in the SPA.
But how would you go about using SSO when you don't know ahead of time which Redirect URIs to add in AzureAd?
We can't re-direct the SPA to a common login page (cleared in AzureAd), because that would break the connection to the injected service.
The msal-browser library has an option to use a popup window instead of a redirect directly in the SPA window, but this option also needs a pre-approved Redirect URI.
I'm thinking we may need to implement custom logic to let our SPA open a popup window that navigates to a page we can pre-approve as a Redirect URI, that itself has the MSAL library and does the SSO login and communicates the result back to our SPA. But before I attempt a custom solution like that, I wonder if maybe I'm missing something.
Is there a more standard, less "hacky", solution that I have missed?
We would appreciate any input, thanks!

We eventually went with the solution I hinted at in the question:
Publish a simple page including the MSAL library on a "central" location that we can pre-approve in AzureAD. Let's call that the Central SSO-page (CSSO).
Let each SPA, running on what ever domain they want, open a popup with the CSSO. This runs the MSAL and completes the login.
CSSO has logic that, on login-completion, communicates back to the SPA, using window.postMessage("Some message", "https://somerandomdomain.com")
The SPA sets up a listener window.addEventListener("message", handleMessage(){..logic here}).
The drawbacks are, as far as I can tell, mostly that you need to make sure you are posting the message so that only the correct window can receive it.
Another drawback is that popups are often blocked, but in our case that is unlikely since our SPAs are running from domains where the main way of loading our SPAs is through a popup, so for the user to even see our SPA, popups must already be allowed. Still, some fallback logic is needed to open the popup manually with a click (which seems to circumvent the default block of popups).

Related

Teams application - Bot: How to open up a third party signup page in a new tab/browser when a user types a certain text

I am new to teams application development and i am Building a Bot that will communicate with a third party APIs. For users to get information from that third party, they need to sign up to that 3rd party. Can i open a web page in a dialog to sign up user ? How is this possible using Team bot node.js SDK ?
It's possible to load a page, from a bot, in a Task Module. It basically provides a mini embedded browser experience. See more at https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/what-are-task-modules and https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/task-modules/task-modules-bots?tabs=nodejs .
Note though that you won't know that the user has actually signed up to the service, only that they opened the "popup". You might be able (depending on the 3rd party's website) to embed their content in an iframe inside your own web page, within the task module, maybe with a button at the bottom to "complete the process" or something like that. That way, your bot will know to proceed. Alternatively, maybe you get a message from the 3rd party when signup is complete.

How to integrate Chrome extension MV3 with PayPal

How can I use PayPal to charge users for feature(s) in my MV3 Chrome extension?
I'm specifically looking for PayPal as Stripe isn't supported in my country.
This is the first-ever time I'm trying to charge money for anything, so I wish to do it the right way the first time.
Also, my extension is open-source, so if I could make the code in a certain way to prevent the user from bypassing the storage to enable the feature without paying, it'd be cool.
You need a web server that provides services and payment verification if you want to prevent the user from bypassing anything.
Current versions of the PayPal Checkout require loading external JS resources, which browser extensions typically frown on. So the simplest solution, again, is going to be to have your extension direct over to a web page to handle the payment.
If you insist on processing the payment directly from your extension, the only possible way would be using a legacy HTML-only PayPal flow, most simply opening a tab to a link such as:
https://www.paypal.com/webscr?cmd=_xclick&item_name=payment%20purpose%20goes%20here&amount=100&currency_code=USD&business=receiverofpayment#emaildomain.com
This would not be at all secure or verifiable, other than perhaps if you were to also integrate the legacy IPN service on a server (also a bad idea).
So in summary, to do what you want to do you ought to pair a server and web page with your extension for payment processing/verification.
See the full stack example at https://developer.paypal.com/docs/subscriptions/integrate/ , and do API calls from your server's backend (in whatever programming environment, the node js there is just an example) for the order creation and capture. Your 2 server routes should be called from your web page, ideally using this approval flow includes a sample of error handling code for if the capture fails.

How do I capture the URL after an external website login in ReactJS?

I want to retrieve the URL after opening an external website pop up in my ReactJS/NodeJS application. Basically in my application, I have a button that redirects the page to microsoft online login page. What I want is the URL of the page after the user logs into microsoft online.
Is there any way that's possible? If so, what are my options?
If you navigate to another webpage, your React application is no longer being served to your browser, and can't do anything. You would need to have a script running on the microsoft website, either by writing it in the source code (which I doubt you can do) or by some other method such as a browser extension.
There is no way to track different systems like methods #izb mentioned, if they already dont provide.
Many systems provides information from their servers, push/ping systems.
One of the payment systems, I redirect request, customer pays, and they redirects the page I entered before in their panel, like successful or fail pages.

identity.launchWebAuthFlow vs windows.create in chrome extension

I'm new to chrome extensions but I can't seem to understand what value the identity.launchWebAuthFlow adds over windows.create. I'm trying to use Oauth from an external provider. There doesn't appear to be any automatic persistence of an identity token as part of that flow. Also other browsers do not (yet?) support the identity.launchWebAuthFlow function. Both of which point to NOT using it vs a normal popup.
What am I overlooking?
chrome.identity.launchWebAuthFlow launches your authentication page in a window until it comes back to https://<app-id>.chromiumapp.org/*, and then the callback fires.
chrome.windows.create launches any URL and then fires the callback with the window object.
There's one significant advantage to chrome.identity.launchWebAuthFlow, from the docs:
Since some auth flows may immediately redirect to a result URL, launchWebAuthFlow hides its web view until the first navigation either redirects to the final URL, or finishes loading a page meant to be displayed.
This means that you can seamlessly sign in (if your auth supports it)

How to invoke /api/auth/{provider} as a popup (ajax) rather than a full post?

I am looking to replace a toolkit that does social auth through a seamless popup, where the entry point is a javascript function and there are javascript callbacks that you install that pass the results of the authentication back to you once everything has asynchronously been processed.
The socialbootstrap example shows how to perform posts to /api/auth/{provider} and this causes the browser to redirect to the login screen of the social provider and then back to a redirectUrl in the original app.
I would like to have this work in some kind of popup and the result be passed back to me as some kind of ajax result or a javascript success or failure handler.
Is this possible and if so do you know of any code examples that show this?
My understanding is that iframes are not a universally good way to do this as some social providers have iframe busters...
Thanks
If you only need to support Credentials i.e. UserName/Password Authentication you could do this via a HTML from in a Popup and ajax.
The https://httpbenchmarks.servicestack.net Live Demo shows an example of this when you click on Login with your email button or Sign In link (on the top right).
The Authentication/Login process is documented in detiail the repository, e.g it uses a modal bootstrap form and ss-utils bindForm to ajaxify the HTML Form and provide automatic form and validation binding.
On successful authentication, the success callback is fired where you can hide the modal form and run any other post-authentication scripts, e.g:
$("#form-login").bindForm({
success: function (r) {
$('#modalLogin').modal('hide');
localStorage["UserName"] = $("[name=UserName]").val();
$(document).trigger('signed-in');
}
});
Now that the Users Session is authenticated, every subsequent ajax request is sent in the context of the users authenticated session.
If you want to use OAuth then you would need to stick to full-page reloads since often the page will be redirected to the 3rd Party site where the user needs to explicitly allow authentication via your app.

Resources