I am receiving a CORS error from my browser while trying to implement a simple login authentication (email/password) with firebase.
I checked the security rules and it is set to
{
"rules": {
".read": true,
".write": true
}
}
Here's a summary of my code from the example.
<script src="https://cdn.firebase.com/js/client/1.0.15/firebase.js"></script>
<script type='text/javascript' src='https://cdn.firebase.com/js/simple-login/1.5.0/firebase-simple-login.js'> </script>
var myRootRef = new Firebase('https://vivid-fire-myserver.firebaseio.com/');
var authClient = new FirebaseSimpleLogin(myRootRef, function(error, user) {
if (error) {
alert(error);
return;
}
if (user) {
alert('user already logged in');
} else {
alert('user logged out');
}
});
$("#registerButton").on("click", function() {
var email = $("#email").val();
var password = $("#password").val();
authClient.createUser(email, password, function(error, user) {
if (!error) {
alert('registered successfully');
} else {
alert(error);
}
});
});
It appears that the problem is a result of submitting my form, which causes the page to reload. As confirmed with Rob, "the reload is taking place before the HTTP OPTIONS request to the server checking the CORS configuration is able to complete.
A work around is to prevent the form from reloading upon submission. I did this by returning false in my html form and my jquery scripts.
<form class="m-t" role="form" onSubmit="return goLogin()">
..........
function goLogin() {
$("#loginButton").click(function() {
......
)};
return false;
}
Related
I am new to SvelteKit and i am trying to use MSAL.js with SvelteKit, the issue is i want to implement something similar to an AuthGuard/HttpInterceptor which checks to see if the user is still logged in as they navigate around the SPA or call the external API.
I am using the OAuth 2.0 authorization code flow in Azure Active Directory B2C
within in my auth.ts file i have the following code
let accountId: string = "";
const signIn = () => {
try {
msalInstance.loginRedirect(loginRequestWithApiReadWrite);
} catch (error) {
isAuthenticated.set(false);
console.warn(error);
}
}
// This captures the response from using the redirect flow to login
await msalInstance.handleRedirectPromise()
.then(response => {
if (response) {
if (response.idTokenClaims['tfp'].toUpperCase() === b2cPolicies.names.signUpSignIn.toUpperCase()) {
handleResponse(response);
}
}
})
.catch(error => {
console.log(error);
});
async function handleResponse(response: msal.AuthenticationResult) {
if (response !== null) {
user.set(response);
isAuthenticated.set(true);
setAccount(response.account);
} else {
selectAccount();
}
}
function selectAccount() {
const currentAccounts = msalInstance.getAllAccounts();
if (currentAccounts.length < 1) {
return;
} else if (currentAccounts.length > 1) {
const accounts = currentAccounts.filter(account =>
account.homeAccountId.toUpperCase().includes(b2cPolicies.names.signUpSignIn.toUpperCase())
&&
account.idTokenClaims?.iss?.toUpperCase().includes(b2cPolicies.authorityDomain.toUpperCase())
&&
account.idTokenClaims.aud === msalConfig.auth.clientId
);
if (accounts.length > 1) {
if (accounts.every(account => account.localAccountId === accounts[0].localAccountId)) { console.log("Multiple accounts belonging to the user detected. Selecting the first one.");
setAccount(accounts[0]);
} else {
console.log("Multiple users accounts detected. Logout all to be safe.");
signOut();
};
} else if (accounts.length === 1) {
setAccount(accounts[0]);
}
} else if (currentAccounts.length === 1) {
setAccount(currentAccounts[0]);
}
}
// in case of page refresh
selectAccount();
function setAccount(account: msal.AccountInfo | null) {
if (account) {
accountId = account.homeAccountId;
}
}
const authMethods = {
signIn,
getTokenRedirect
}
In a +page.svelte file i can then import the authMethods no problem, MSAL redirects me to the microsoft sign in page, i get redirected back and can then request an access token and call external API, great all is well.
<script lang='ts'>
import authMethods from '$lib/azure/auth';
<script>
<button on:click={authMethods.signIn}>Sign In</button>
However, the issue i am having is trying to implement this so i can check to see if the user is logged in against Azure B2C using a hook.server.ts file automatically. I would like to check a variable to see if the user is authenticated and if they arnt the hooks.server will redirect them to signUp by calling the authMethod within the hook, and the user will be automatically redirected to the sign in page.
In the hooks.server.ts i have the following code:
export const handle: Handle = (async ({ event, resolve }) => {
if (isAuthenticated === false) {
authRedirect.signIn();
msalInstance.handleRedirectPromise().then((response) => {
if (response) {
console.log('login with redirect succeeded: ', response)
isAuthenticated = true;
}
}).catch((error) => {
console.log('login with redirect failed: ', error)
})
}
const response = await resolve(event);
return response;
}) satisfies Handle;
When i navigate around the SvelteKit SPA, MSAL.js keeps throwing the error below, which i know is because i am running the code from the server flow rather than in the browser, so it was my understanding that if i implement the handleRedirectPromise() in both the auth.ts file and hooks.server.ts this would await the response from the signIn event and so long as i got a response i can then set isAuthenticated to true.
errorCode: 'non_browser_environment',
errorMessage: 'Login and token requests are not supported in non-browser environments.',
subError: ''
Are you required to use the MSAL library? I have got it working with https://authjs.dev/. I was using Active Directory -https://authjs.dev/reference/oauth-providers/azure-ad but there is also a flow for B2C https://authjs.dev/reference/oauth-providers/azure-ad-b2c which I haven't tried.
Then in the hooks.server.js you can do something like the below.
import { sequence } from '#sveltejs/kit/hooks';
import { redirect } from '#sveltejs/kit';
import { SvelteKitAuth } from '#auth/sveltekit';
import AzureADProvider from '#auth/core/providers/azure-ad';
import {
AZURE_AD_CLIENT_ID,
AZURE_AD_CLIENT_SECRET,
AZURE_AD_TENANT_ID
} from '$env/static/private'
const handleAuth = SvelteKitAuth({
providers: [
AzureADProvider({
clientId: AZURE_AD_CLIENT_ID,
clientSecret: AZURE_AD_CLIENT_SECRET,
tenantId: AZURE_AD_TENANT_ID
})
]
});
async function isAuthenticatedUser({ event, resolve }) {
const session = await event.locals.getSession();
if (!session?.user && event.url.pathname !== '/') {
throw redirect(302, '/');
} else if (session?.user && event.url.pathname === '/') {
throw redirect(302, '/dashboard');
}
const response = await resolve(event);
return response;
}
export const handle = sequence(handleAuth, isAuthenticatedUser);
I have Vue.js application where some routes require the user to be logged in, whereas others (such as the login page) are public.
created() {
let context = this;
context.axios.create({withCredentials: true}).get(`${context.$store.getters.getApiUrl}/session/`).then(response => {
context.$store.commit('loginUser');
context.$store.commit('setUser', response.data.data);
}, error => {
/*
This indicates a 401 unathorized response that indicates
the session cookie has expired
*/
context.$store.commit('logoutUser')
});
},
computed: {
authorized: {
get: function() {
let authenticated = this.$store.getters.getUserAuthStatus;
let route = this.$route;
if (authenticated !== true && route.meta.requiresLogin === true) {
return false;
}
else {
return true;
}
}
}
},
watch: {
authorized: function(val) {
if (val === false) {
this.$router.push('/signin');
this.$store.commit('setGlobalInfo', 'Please sign in first.');
}
}
}
Basically, when the user opens the app, I send a request to a protected route on the server. Depending on the response, I either log the user in (and set Vuex authenticated status to true) or log them out.
I added the watcher because I want to automatically redirect the user to login if the authorized computed property changes. However I haven't gotten it to work. The authorized property computes correctly, but the watcher function never triggers.
My understanding is that you can watch computed properties in Vue as long as you give them the same name (i.e. "authorized"). Am I doing something incorrectly?
It looks like I needed to set deep: true on the watcher.
computed: {
authorized: {
let authenticated = this.$store.getters.getUserAuthStatus;
let route = this.$route;
if (authenticated !== true && route.meta.requiresLogin === true) {
return false;
}
else {
return true;
}
}
},
watch: {
authorized: {
handler: function(val) {
if (val === false) {
this.$router.push('/signin');
this.$store.commit('setGlobalInfo', 'Please sign in first.');
}
},
deep: true;
}
I've created an application using google drive API to list and manage all my drive files.
Everything goes fine, except the log out part. I've searched for two days for a solution without a result.
The following is code related to login and works fine:
function checkAuth() {
gapi.auth.authorize(
{
'client_id': CLIENT_ID,
'scope': SCOPES.join(' '),
'immediate': true,
'authuser': '-1'
}, handleAuthResult);
}
function handleAuthResult(authResult) {
var authorizeDiv = document.getElementById('authorize-div');
if (authResult && !authResult.error) {
// Hide auth UI, then load client library.
authorizeDiv.style.display = 'none';
loadDriveApi();
} else {
authorizeDiv.style.display = 'inline';
}
}
function handleAuthClick(event) {
gapi.auth.authorize(
{client_id: CLIENT_ID, scope: SCOPES, immediate: false},
handleAuthResult);
return false;
}
function loadDriveApi() {
gapi.client.load('drive', 'v2', listFiles);
}
I'm able to login and work with files, but when I try to logout with following I get No 'Access-Control-Allow-Origin' error
$(document).on('click', '.logout', function(){
var token = gapi.auth.getToken();
if (token) {
var accessToken = gapi.auth.getToken().access_token;
if (accessToken) {
var revokeToken = 'https://accounts.google.com/o/oauth2/revoke?token=' + accessToken;
jQuery.getJSON(revokeToken).success(function(data) {
console.log(data);
}).error(function(message) {
console.error('error' + message);
}).complete(function() {
console.log('completed!');
});
}
}
gapi.auth.setToken(null);
gapi.auth.signOut();
});
In Google Developers Console I've regitred my website to Authorized JavaScript origins.
Thanks
For my App, I need a users birthdate and email-address. So I set up the permissions to that!
In the preview it works just fine:
but in the actual login dialogue it does not!
Therefore, I don't have the permission. What do I do now?
Code: It's basically right out of facebook's getting started...
window.fbAsyncInit = function() {
FB.init({ // init the FB JS SDK
appId : 'XXXXXXXX', // App ID from the App Dashboard
channelUrl : 'http://nerdjokes.funpic.de/channel.html', // Channel File for x-domain communication
status : true, // check the login status upon init?
cookie : true, // set sessions cookies to allow your server to access the session?
xfbml : true // parse XFBML tags on this page?
});
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
loggedIn();
} else if (response.status === 'not_authorized') {
login(); //user hast not authorized the app. Display the dialogue
} else {
login();
}
});
};
function login() {
FB.login(function(response) {
if (response.authResponse) {
// connected
} else {
// cancelled
}
});
I'm using the Javascript SDK to allow the user to login to facebook, retrieve their friends profile pictures, and then finally post a message on the logged in users wall. Problem is I keep getting an error, "Error while loading page from Pencils of Promise," when the user has to authorize the application.
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script>
FB.init({appId: '154058871279888', status: true, cookie: true,
xfbml: true});
console.log(FB.getLoginStatus());
$('div.voice-btn:eq(0)').click(function() {
FB.login(function(response) {
if(response.session) {
FB.api('/me', function(data) {
console.log(data);
});
donateVoiceSlider();
}
});
});
$('#voice-step-2-btn').click(function() {
var body = 'Test Facebook post';
FB.api('/me/feed', 'post', { body: body }, function(response) {
if (!response || response.error) {
alert('Error occured');
} else {
alert('Post ID: ' + response);
}
});
});
// Donate Voice Content Slider
function donateVoiceSlider() {
var $ul = $('#donatevoice');
var cur_left = parseInt($ul.css('left'));
var li_width = 980;
$ul.animate( {'left': cur_left-li_width+'px'} );
}
</script>
Please help!
My friend who had created the application did NOT set the site URL. After doing that, everything ran smoothly.