Firebase cookie issue for Twitter Authentication - node.js

I am currently trying to allow users to login to my Vue.js application via Twitter authentication. This is essentially the code I am using. Every time I click the Twitter sign in button I get this issue:
A cookie associated with a cross-site resource at http://google.com/ was set without the SameSite attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with SameSite=None and Secure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.
Any idea as to how I can resolve this? Any help would be greatly appreciated. I feel like these two pieces of code could be the issue but I am not so sure.
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import * as firebase from 'firebase/app'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
user: null
},
getters: {
user (state) {
return state.user
}
},
mutations: {
SET_USER (state, payload) {
state.user = payload
},
LOGOUT (state, payload) {
state.user = null
}
},
actions: {
autoSignIn({ commit }, payload) {
const newUser = {
userDetails: payload.providerData
}
commit('SET_USER', newUser)
},
signIn({ commit }) {
var provider = new firebase.auth.TwitterAuthProvider();
firebase.auth().signInWithRedirect(provider);
firebase.auth().getRedirectResult().then(result => {
// The signed-in user info.
var user = result.user;
commit('SET_USER', user)
}).catch(error => {
alert(error)
return
})
},
logout({ commit }) {
firebase.auth().signOut().then(function () {
commit('LOGOUT')
}).catch(function (error) {
alert(error)
return
});
}
}
})
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import {store} from './vuex/store'
import * as firebase from 'firebase/app'
import Vuex from 'vuex'
import {config} from './firebaseConfig'
// Firebase App (the core Firebase SDK) is always required and must be listed first
// If you enabled Analytics in your project, add the Firebase SDK for Analytics
import "firebase/analytics"
// Add the Firebase products that you want to use
import "firebase/auth"
import "firebase/firestore"
Vue.use(Vuex)
Vue.config.productionTip = false
/* eslint-disable no-new */
firebase.initializeApp(config)
const check = firebase.auth().onAuthStateChanged((user) => {
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
store,
created() {
if (user) {
store.dispatch('autoSignIn', user)
}
}
})
check()
})

This warning is coming from a google.com cookie, so it's not something you can affect. You can get more on the context of these changes over on https://web.dev/samesite-cookies-explained however there's no action you need to take. If there are any warnings associated with your domain, then you should check to see if there's an appropriate SameSite value to set on your cookie.
To explain what's happening here, even though you are using Twitter Sign-In, you probably have some kind of Google supplied third-party resource on your site. This may be retrieving the Firebase libraries, Google Analytics, or perhaps you're loading the Google Sign-In library in there too. As you have some eligible cookies in your browser, they are also being sent on these requests. They do not have a SameSite attribute added, so as a result once the SameSite=Lax by default enforcement is in place then these cookies will no longer be sent.
A good way to test this is to open up a new incognito session so you can be sure you only have new cookies set and then see if you still get the warning, it may simply be you have some older cookies in your current profile. However, the warning is just that - a warning, not an error. For compatibility with older browsers, sites and services may continue to set certain cookies without the SameSite attribute.

I had the wrong callback url in my Twitter app. Didn't realise firebase gave you a callback URL once you insert the API/secret API key in firebase.

Related

Route keycloak register button to Vue app

I am using keycloak as authentication for my Vue.js app. I am trying to implement the user registration but with custom fields i.e some extra data, I need for user registration. Since I do not have expertise in Java so I am not willing to clone keycloak repo and make changes to it. The workaround I found was to move the registration flow to my Vuejs app.
Is there any way I can redirect the user to my Vuejs registration page as soon as the user clicks the registration button on the keycloak login page? I have passed the correct client-id and realm-name and have a keycloak instance running on my local via docker.
Here is my keycloak initialization code:
import Keycloak from 'keycloak-js'
import useStore from './store'
const initOptions = {
realm: '',
clientId: '',
url: 'http://localhost:8082/',
'public-client': true,
'verify-token-audience': false,
}
const keycloak = Keycloak(initOptions)
function initKeycloak() {
return new Promise(function(resolve, reject) {
const store = useStore()
keycloak.init({ onLoad: 'login-required', promistType: 'native', pkceMethod: 'S256' }).then((auth) => {
if (!auth) {
window.location.reload()
} else {
console.log('Authenticated')
}
if (keycloak.token) {
store.token = keycloak.token
window.localStorage.setItem('keycloakToken', keycloak.token)
resolve()
}
})
setInterval(() => {
keycloak.updateToken(70).then((refreshed) => {
if (refreshed) {
store.token = keycloak.token
window.localStorage.setItem('keycloakToken', keycloak.token)
console.info('Token refreshed' + refreshed);
} else {
console.warn('Token not refreshed, valid for '
+ Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds');
}
}).catch(() => {
console.error('Failed to refresh token');
});
}, 3000)
})
}
// keycloak logout
var logoutOptions = { redirectUri : 'http://localhost:3000' };
function keycloakLogout() {
keycloak.logout(logoutOptions).then((success) => {
console.log("--> log: logout success ", success );
}).catch((error) => {
console.log("--> log: logout error ", error );
});
}
export { initKeycloak, keycloakLogout }
You don't need to make any change to Keycloak source to do this. The UI layer you see comes from the default theme in Keycloak. You can create your custom theme in which you would use the link to your own user registration. But there are some important points to be aware of:
You should probably have your own application backend in which the new user's data would be validated and then it will call Keycloak's REST API to add the new user. Otherwise you can't just submit your Vue.js client data to Keycloak.
Unfortunately the Keycloak's theme implementation requires you to code in FreeMarker template language
Check if the new preview feature named declarative-user-profile can solve your problem or not (you have to enable it on Keycloak startup)
Regarding the theme customization, I recommend you to have a look at the keycloakify project
There may not be an easy way to achieve this if you're not Java developer or have no experience with Keycloak before.

How to configure firebase-admin-sdk for `verifyIdToken` to pass?

I try to use Firebase in my application. The frontend logs the user in using the Web SDK, without any backend. Later, I would like to call some backend APIs. For this reason, I pass the idToken to the backend and try to validate the user as described in the Firebase docs.
When I do the above flow locally using the Firebase Emulator everything works as expected.
When I switch off the Emulator the idToken validation fails with
{
errorInfo: {
code: 'auth/argument-error',
message: 'Firebase ID token has invalid signature. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.'
},
codePrefix: 'auth'
}
I created a Google hosted Firebase function to check if I can get the idToken validated there. The above setup works when the validation happens within the Google infrastructure.
Based on the above, I think the issue is in my FirebaseApp setup in the API. What that issue might be?
This is my setup.
I define 3 environment variables:
FIREBASE_DB_URL=https://<project-id>.firebaseio.com
FIREBASE_PROJECT_ID=<project-id>
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
I checked and cat $GOOGLE_APPLICATION_CREDENTIALS prints the correct file.
I initialize Firebase in the API with
import admin from "firebase-admin";
if(admin.apps.length == 0) {
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: process.env.FIREBASE_DB_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
});
console.log('Firebase initialized')
} else {
console.warn('Firebase already initialized')
}
and this is the validating code
import { DecodedIdToken } from 'firebase-admin/lib/auth/token-verifier';
import { getAuth } from 'firebase-admin/auth';
import './initializeFirebase';
export default async function needsLoggedInUser(idToken: string): Promise<DecodedIdToken|false> {
try {
return await getAuth().verifyIdToken(idToken)
} catch(err) {
console.error(err)
return false
}
}
I use the above in a NextJS API code as
import { NextApiRequest, NextApiResponse } from 'next'
import { getDatabase } from 'firebase-admin/database';
import 'services/backend/initializeFirebase';
import needsLoggedInUser from 'services/backend/needsLoggedInUser';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// As an admin, the app has access to read and write all data, regardless of Security Rules
const decodedToken = await needsLoggedInUser(req.body.user)
if(!decodedToken) {
return res.status(403).send("403 Forbidden")
}
/// ... rest of the API
}

How to track an error generated by providing wrong instrumentation key in Azure App Insights

I'm using Azure app Insights for collecting analytical data.I want to handle a case where I'm getting a 400 error due to providing the wrong instrumentation key in the AppInsights.js file. I have created a profile for encrypting instrumentation key in App. Where can I catch this error in code and display fallback UI in a React App.The backend is in Java.
import { ApplicationInsights from'#microsoft/applicationinsightsweb';
import {ReactPlugin,AppInsightsErrorBoundary,} from
'#microsoft/applicationinsights-react-js';
import { createBrowserHistory } from 'history';
import { ClickAnalyticsPlugin } from '#microsoft/applicationinsights-
clickanalytics-js';
import io from 'react/IOGlobal';
const clickPluginInstance = new ClickAnalyticsPlugin();
const browserHistory = createBrowserHistory({ basename: '' });
const reactPlugin = new ReactPlugin();
const clickPluginConfig = {
autoCapture: true,
dataTags: {
useDefaultContentNameOrId: true,
},
};
const appInsights = new ApplicationInsights({
config: { instrumentationKey:
***io.platform.getProfileValue('APP_INSTRUMENTATION_KEY')***,
extensions: [reactPlugin, clickPluginInstance],
extensionConfig: {
[reactPlugin.identifier]: { history: browserHistory },
[clickPluginInstance.identifier]: clickPluginConfig,
},
},
});
appInsights.loadAppInsights();
export default { reactPlugin, appInsights };
Also please help with any other implementation in App Insights to catch the same error.
Thanks In Advance.
Update index.js by putting the following route at the end of the route declaration, before app.listen():
…
// this matches all routes and all methods
app.use((req, res, next) => {
res.status(404).send({
status: 404,
error: ‘Not found’
// You can add your alert
})
})
Check here for more info here
First need to set the Instrumentation key .setup(“Instrumentation key”) To get the instance of the default client that is configured with .setup("Instrumentation key") use appInsights.client. Alternatively, if you want a new client just use getClient("Instrumentation key").
Just like for setup, you can skip providing the Instrumentation key in code if it's in the special instrumentation key environment variable.
Refer for similar kind of issue here

Logging old user data on login after logout in react using JWT

I am using react node js with SQL.
When I logout from reactJS I am removing the token while logging out. But still when i login within different credentials it takes me to dashboard with old user data and when I refresh page i get the data with new currently logged in user.
What could be it
The code part is pretty much correct I guess because it shows perfect data after page refresh.
my logout action
export const logoutAction = () => {
return dispatch => {
localStorage.removeItem('tkn')
dispatch({ type: LOGOUT, payload: "" })
}
}
logout reducer
case LOGOUT:
return {
...state,
token: action.payload,
isAuth: false,
}
Triggered action from the navbar
const logout = () => {
props.logoutUser()
handleDrawerClose()
}
I Had the same problem. My APP get a JWT auth token from a ASP.NET Web API and use this for display some items after login. But when the user loggout and other user does login, the data from the first user apear instead off the last user data.
I found a session cookie and I resolved the problem installing the react-native-cookies package (#react-native-cookies/cookies). https://github.com/react-native-cookies/cookies
yarn add #react-native-cookies/cookies
After this, on my AuthActions, on my Logout routine, I call clearAll() method.
import CookieManager from '#react-native-cookies/cookies';
export const userLogout = () => {
CookieManager.clearAll();
return (dispatch) => {
dispatch({type: LOGOUT_ACTION});
// more actions...
};
};

How to manage authentication of a user through a vue router and a server-provided JWT token?

I am building a web app using vue/webpack for the front end and node.js/express on back end. The node.js back end is exposing REST APIs that are used by the front end to login, logout and other CRUD-like operations.
On server side, the login REST API is setting a JWT token and redirects to the vue application home path.
On front end side, the vue components access (including home) is guarded by the beforeEach method of the vue router (based on sample from here).
My question is, from within my vue application, how can I access the JWT token (set by the login REST API in the HTTP Headers of the response) and store it in my vuex store so that my vue components can use it?
Thanks for your help!
PS: I am using node.js 8.5, Vue 2.4.4, Vue Router 2.7, Vuex 2.4.1
Use Axios Interceptors:
import { defaults, get } from 'lodash';
import axios from 'axios';
import store from 'vuex-store';
import def from './default';
export const connection = (options = {}) => {
def.headers = { Authorization: store.getters.auth.getToken() };
const instance = axios.create(defaults(def, options));
instance.interceptors.response.use(
function (response) {
const newtoken = get(response, 'headers.authorization');
if (newtoken) store.dispatch('setToken', newtoken);
console.log(response.data);
return response;
},
function (error) {
switch (error.response.status) {
case 401:
store.dispatch('logoff');
break;
default:
console.log(error.response);
}
return Promise.reject(error);
}
);
return instance;
};

Resources