identity.launchWebAuthFlow not completing with 2FA in extension - google-chrome-extension

I have an extension that is calling identity.launchWebAuthFlow for google authentication.
chrome.identity.launchWebAuthFlow(
{
'url': authUrl.href,
'interactive': interactive
},
(redirectedTo) => {
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError.message);
resolve(null)
}
else {
let idToken = idToken.substring(0, idToken.indexOf('&'))
resolve(idToken)
}
}
)
I get the error "Authorization page could not be loaded". The google account is using active directory federated services (adfs) as well as a hardware 2FA token through duo. I make it to the ADFS login, and then after that the authentication windows close and I get the above error in the console. I can login in Chrome to accounts.google.com to test with this and it works fine. What do I need to do different in an extension for this.

Related

Azure MSAL authentication - SSO with MFA

I have an an iframe, which uses MSAL authentication. it's parent also uses the same auth mechanism and once the user has logged in the parent app, I should be able to log him in the iframe with SSO. I tried doing it with loginHint but I get this error:
That's the piece of code in the iframe that receives the loginHint from the parent and trying to use it for SSO:
window.addEventListener("message", (event) => {
// check the origin of the data
if (event.origin === parentDomain) {
const loginHint = event.data;
// attempt SSO
publicClient
.ssoSilent({
scopes: ["openid", "profile", "User.Read"],
loginHint,
})
.then((res) => {
console.log(res);
})
.catch((error) => {
console.error(error);
});
}
});
I think it might have something to do with the fact that my organization is using MFA (Multi factor authentication), but I'm not exactly sure. Is there a way to bypass this
without canceling the MFA?
You cannot use interactive login inside IFRAME with MSAL, also embedded webviews can stop working for security reassons authenticathing against third party providers like Google or others (OpenID).
It's not about MFA.
CmsiInterrupt - For security reasons, user confirmation is required for this request. Because this is an "interaction_required" error, the client should do interactive auth. This occurs because a system webview has been used to request a token for a native application - the user must be prompted to ask if this was actually the app they meant to sign into. To avoid this prompt, the redirect URI should be part of the following safe list:
http://
https://
msauth://(iOS only)
msauthv2://(iOS only)
chrome-extension:// (desktop Chrome browser only)

Changing Firebase target with Chrome Extension results in auth/invalid-credential

I've previously setup and followed these steps, and got it to work:
https://firebaseopensource.com/projects/firebase/quickstart-js/auth/chromextension/readme/#license
But cloning this extension, but with a different Extension ID, different firebase instance and OAuth/key setup, I've tried to follow the steps at least 3 separate times, but every time it fails at the last step, the login (the consent screen works though)
Upload a fresh dummy extension (without key field in manifest.json) (But it is the exact same code as the working one)
Get the Chrome Extension ID, and the Public Key, no problem
Create OAuth Client ID with the Extension ID, configured consent screen, no problem, the screen shows up and I can click through
Add OAuth & Public Key to manifest.json
Make another OAuth Client ID? (I think this is a duplicate step, because which Client ID should I use? and afaik the whitelisting is optional)
Use chrome.identity to get OAuth token:
export function startAuth(interactive) {
// Request an OAuth token from the Chrome Identity API.
chrome.identity
.getAuthToken({ interactive: !!interactive }, (token) => {
if (chrome.runtime && !interactive) {
console.error('It was not possible to get a token programmatically.');
}
else if (token) {
// Authorize Firebase with the OAuth Access Token.
const credential = firebase.auth.GoogleAuthProvider
.credential(null, token);
firebase.auth()
.signInWithCredential(credential)
.catch((error) => {
// The OAuth token might have been invalidated. Lets' remove it from cache.
if (error.code === 'auth/invalid-credential') {
chrome.identity
.removeCachedAuthToken({ token }, () => {
startAuth(interactive);
});
}
});
}
else {
console.error('The OAuth Token was null');
}
});
}
Note: This code is working with another extensionID/OAuth/key, so the code itself can't be the problem.
There isn't much to change between them, it's really the ExtensionID, the OAuth client ID url, and the public key.
I've followed the steps 3 times, to no avail, every time I get the error auth/invalid-credential. I do get a token though, but that token won't authenticate. How to find out why this is?
It's trying to post to this address, and returning error 400:
POST: https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=xxxxx
Error: INVALID_IDP_RESPONSE : Invalid Idp Response: access_token audience is not for this project
My conclusion
There must be something changed with how to set this up, even though it works with different credentials
The problem was that I didn't create the OAuth in the same project in google cloud console, as the firebase project...

Azure EasyAuth: Getting Unauthorized error when try to login with a Microsoft account

This has been baffling me for hours now, so I have been trying to get EasyAuth working using different providers.
I am using this on Azure Functions, so let's say my function address is
https://xxx.azurewebsites.net
If I want to login into the service using a Google account I send my post request along with token received from Google to the following address
https://xxx.azurewebsites.net/.auth/login/google
This gives me a converted token back.
However if I do the same thing with a Microsoft account using the following details
Request Body:
{ "access_token": "token-string-value" }
Endpoint:
https://xxx.azurewebsites.net/.auth/login/microsoftaccount
It gives me the following error instead of a converted token
401 Unauthorized You do not have permission to view this directory or page.
--
I am using Msal JavaScript library to get my authentication token. Also I am testing these in Postman which makes it easy to understand what the problem is before I deal with the code and other stuff.
-- Update 1.0
This does seem like a bug, as even if I try to navigate to the
https://xxx.azurewebsites.net/.auth/login/microsoftaccount
It shows me the following
This URL works for other providers, Google, Facebook and Twitter. For all of them it redirects the user to the provider's login page.
According to the error page and the address bar contents, the client doesn't exist which could be referring to the application created on Azure to allow my website access the API. But everything has been setup correctly.
It would be helpful if someone from Azure We App Services can take a look at this.
I have created the Application and added the application ID and Secret int eh App Services page.
-- Update 2.0
So after hours of investigation, I managed to get the URL working, shockingly it was due to wrong information given on Azure portal. The link in Authorization and Authentication section of App Service is pointing to a new platform to register applications, which is purely for Azure AD based users.
For the external users to be able to login the application need to be registered in the following portal
https://apps.dev.microsoft.com
After registering the application here, and added the details in the App Service blade, the URL to EasyAuth is working.
However this doesn't resolve my issue. I still need a JavaScript library that gives me valid token which I can pass to EasyAuth endpoint.
Strangely the token taken from MSAL is not valid for Microsoft account. It just gives me the same error that my access is unauthorised. This means I probably need to use a different library to get a different token. I'd appreciate it if still someone can help me with this.
Below is a short sample code I am using to retrieve token and pass it to another function n which call EasyAuth endpoint and post the token along.
var applicationConfig = {
clientID: "xxxx-xxx-xxxx-xxxx",
authority: "https://login.microsoftonline.com/9fc1061d-5e26-4fd5-807e-bd969d857223",
graphScopes: ["user.read"],
graphEndpoint: "https://graph.microsoft.com/v1.0/me"
};
var myMSALObj = new Msal.UserAgentApplication(applicationConfig.clientID, applicationConfig.authority, acquireTokenRedirectCallBack,
{ storeAuthStateInCookie: true, cacheLocation: "localStorage" });
function signIn() {
myMSALObj.loginPopup(applicationConfig.graphScopes).then(function (idToken) {
//Login Success
acquireTokenPopupAndCallMSGraph();
}, function (error) {
console.log(error);
});
}
function signOut() {
myMSALObj.logout();
}
function acquireTokenPopupAndCallMSGraph() {
//Call acquireTokenSilent (iframe) to obtain a token for Microsoft Graph
myMSALObj.acquireTokenSilent(applicationConfig.graphScopes).then(function (accessToken) {
// accessToken
}, function (error) {
console.log(error);
});
}
I managed to find what was causing the problem.
So basically only Live Connect SDK generated tokens are valid on
https://xxx.azurewebsites.net/.auth/login/microsoftaccount
We were using MSAL which was generating tokens valid only on Azure Active Directory. I have been in touch with Azure Support, and have asked them to update the documentation. It currently is very confusing as none of these have been explained in the EasyAuth documentations.
We decided to go with Azure AD B2C, as it's more reliable and turns out cheaper for us.
In case anyone would like to use EasyAuth with Microsoft Account, the following is showing how to get access token from Live SDK
WL.Event.subscribe("auth.login", onLogin);
WL.init({
client_id: "xxxxxx",
redirect_uri: "xxxxxx",
scope: "wl.signin",
response_type: "token"
});
WL.ui({
name: "signin",
element: "signin"
});
function onLogin(session) {
if (!session.error) {
var access_token = session.session.access_token;
mobileClient.login('microsoftaccount', { 'access_token': access_token }, false)
.then(function () {
console.log('TODO - could enable/disable functionality etc')
}, function (error) {
console.log(`ERROR: ${error}`);
});
}
else {
console.log(`ERROR: ${session.error_description}`);
}
}
Reference to
< script src="//js.live.net/v5.0/wl.js">

Google Chrome Extension Identity API Authentication

I'm having issues with my authentication on a Chrome Extension that I am working on to learn. Currently, my extension works for my profiles if users are logged in. As soon as I test this (by giving another party access), the extension does not seem to authorize. Am I doing something wrong here?
Could the below code be causing the issues with authentication? To give some context, this is in the background.js file of my extension.
function auth(token){
chrome.identity.getAuthToken({ 'interactive': true }, function (token) {
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError);
//Push Manual Authorise Button to UI
} else {
//Authorised
console.log('Token acquired: ' + token +
' See chrome://identity-internals for details.');
classroomsExist(token);
}
return token;
});
}
Update:
I have tested this on another user account by loading the extension manually, as an unpacked extension and the authentication works. What could be causing the issue when installing from the webstore? My application ID is the same in manifest.json as Google Developer Console.
The client_id changes when you publish, so the manifest.json and app code needs to update any references to it when publishing to the web store.

Auth0 SSO with multiple google accounts

I'm setting up Auth0 with SSO enabled for multiple web sites.
I have it working perfectly for username/password connections and for google connections where the user is only logged into a single google account.
But... I have two google accounts logged in on my browser. When I go to site 1 and use the google connection, it prompts me to select a google account to log in with. That's correct.
But when I go to site 2, and attempt to stay logged in using sso data from Auth0, it still prompts me to select a google account again. Which I would not expect.
Here's my sign in code:
auth0.getSSOData(function (err, ssoData) {
if (!err && ssoData.sso) {
auth0.signin({
connection: ssoData.lastUsedConnection.name,
scope: 'openid email email_verified name app_metadata',
state: 'http://localhost:21763/#/',
authParams: {
prompt: 'none'
}
});
}
});
I added prompt: 'none' having read this older post on Auth0 community, but to no avail. https://auth0.com/forum/t/sso-login-with-google-connection-must-select-account/4983
Has anyone else done this? I feel like it must be possible.
Thanks!
I started experimenting with the possible parameters into the signin method call and stumbled across the answer...
I tried a few things, but this seems to work perfectly, moving the "prompt: 'none'" up out of the authParams to be a direct option to signin method call...
auth0.getSSOData(function (err, ssoData) {
if (!err && ssoData.sso) {
auth0.signin({
connection: ssoData.lastUsedConnection.name,
scope: 'openid email email_verified name app_metadata',
state: 'http://localhost:21763/#/',
prompt: 'none'
});
}
});

Resources