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

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.

Related

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?

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).

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)

Gmail API: Triggering in-webpage refresh

I'd like to trigger the in-webpage refresh button programmatically for the purpose of applying labels to emails without making the user manually refresh the page or make some other page action in order to see the labels. Is this possible to do? All of the documentation I am finding is surrounding refresh tokens, which is obviously something different.
Thank you for your time.
There's no way to do that from the Gmail REST API (i.e. trigger refresh action in web browser viewing the gmail page). If you're running as a browser extension on the other hand, then sure.

How to Logout user from Spotify after authorization and Web API call is over

Im using Spotify Web API to get list of playlist and track of user. Authorization is working fine. Also i do get track details. But after that I want to logout user from spotify and allow new login .
There is a session time till the user auto logout from spotify account. But user might not have patience to wait so long and re try with different spotify account.
Is there any API to logout user from spotify.
What can be done. Please help.
While an application using the Spotify Web API can't log a user out, it can force the permissions dialog to be shown during the login process. For that, use the show_dialog query parameter and set it to true when calling the https://accounts.spotify.com/authorize endpoint.
If there is a user already logged in, there will be a (Not you?) link to change the user.
This applies to the 'Authorization Code' and 'Implicit Grant' flows. You can read the documentation about the show_dialog parameter on the Spotify Web API Authorization Guide.
As addition to José M. Pérez his answer, if you really want to log out, it seems the only way you could achieve this is by opening the Spotify log out URL in the user's browser: https://www.spotify.com/logout/
To prevent CORB protection this could for example be achieved by opening a pop up window with JavaScript and close it after 2 seconds:
const url = 'https://www.spotify.com/logout/'
const spotifyLogoutWindow = window.open(url, 'Spotify Logout', 'width=700,height=500,top=40,left=40')
setTimeout(() => spotifyLogoutWindow.close(), 2000)
UPDATE:
https://accounts.spotify.com/en/logout could also be used, this will redirect to a login page instead of the Spotify main page which is nicer IMHO.
You want to simply logout from "spotify web api" then you should terminate your spotify session through clear authentication token like:
AuthenticationClient.clearCookies(getApplication());
I solved this using the asnwer #jpoppe provided. I didn't like the idea of having a popup window so I used an iframe instead.
<iframe style={{display: 'none'}} src="https://spotify.com/logout"></iframe>
One problem I found with this was if the user had signed in with facebook, when logging in on another account using facebook, they would automatically be signed in when they clicked the 'sign in with facebook' button. I couldn't find a simple way to solve this.

Google Chrome Extension - prevent cookie on jquery ajax request or Use a chome.extension

I have a great working chrome extension now.
It basically loops over a list of HTML of a web auction site, if a user has not paid for to have the image shown in the main list. A default image is shown.
My plugin use a jQuery Ajax request to load the auction page and find the main image to display as a thumbnail for any missing images. WORKS GREAT.
The plugin finds the correct image url and update the HTML Dom to the new image and sets a new width.
The issue is, that the auction site tracks all pages views and saves it to a "recently viewed" section of the site "users can see any auctions they have clicked on"
ISSUE
- My plugin uses ajax and the cookies are sent via the jQuery ajax request. I am pretty sure I cannot modify the cookies in this request so the auction site tracks the request and for any listing that has a missing image this listing is now shown in my "recently viewed" even though I have not actually navigated to it.
Can I remove cookies for ajax request (I dont think I can)
Can chrome remove the cookie (only for the ajax requests)
Could I get chrome to make the request (eg curl, with no cookie?)
Just for the curious.
Here is a page with missing images on this auction site
http://www.trademe.co.nz/Browse/SearchResults.aspx?searchType=all&searchString=toaster&type=Search&generalSearch_keypresses=9&generalSearch_suggested=0
Thanks for any input, John.
You can use the webRequest API to intercept and modify requests (including blanking headers). It cannot be used to modify requests which are created within the context of a Chrome extension though. If you want to use this API for cookie-blanking purposes, you have to load the page in a non-extension context. Either by creating a new tab, or use an off-screen tab (using the experimental offscreenTabs API.
Another option is to use the chrome.cookie API, and bind a onChanged event. Then, you can intercept cookie modifications, and revert the changes using chrome.cookies.set.
The last option is to create a new window+tab in Incognito mode. This method is not reliable, and should not be used:
The user can disallow access to the Incognito mode
The user could have navigated to the page in incognito mode, causing cookie fields to be populated.
It's disruptive: A new window is created.
Presumably this AJAX interaction is being run from a content script? Could you run it from the background page instead and pass the data to the content script? I belive the background page operates in a different context and shouldn't send the normal cookies.

Resources