Redirect if already authenticated - ember simple auth - javascript

I have registration and login working for my Ember app but for some reason 'routeIfAlreadyAuthenticated' is not working currently. Here is my setup:
config/environment.js
'ember-simple-auth': {
authenticationRoute: 'auth.login',
routeIfAlreadyAuthenticated: 'rows',
routeAfterAuthentication: 'rows'
}
But if I go to say /auth/login after I'm signed in it doesn't redirect me to the rows route. Does anybody know what I could be doing wrong?

Your login route should extend unauthenticated-route-mixin mixin:
import Route from '#ember/routing/route';
import UnauthenticatedRouteMixin from 'ember-simple-auth/mixins/unauthenticated-route-mixin';
export default Route.extend(UnauthenticatedRouteMixin, {
});

Related

In Next.js: How to redirect all empty routes to a route of my choosing

If I type in a dead endpoint in Next.js I get a 404 error. Instead, I want all unused routes to redirect to a default route and in this case, the landing page.
I have been researching this for over an hour and I don't believe this task warrants this amount of effort. It should be very easy.
I decided to ask.
Thank you!
You can create a custom 404 page which redirects.
//src/pages/404.js
import React, { useEffect } from 'react'
import Router from 'next/router'
export default function Custom404() {
useEffect(() => {
Router.push('/')
},[])
return null
}

Using EmberJS and Oauth2, how can I modify the default route after invalidation?

My goal is to send the user to a different page/route other than the oauth default after invalidation. Currently the default is my root login page. How can I change this?
I have this logout code in app/controller/protected.js.
Specifically the .invalidate(); method is what I'm trying to modify.
import { inject as service } from '#ember/service';
export default Controller.extend({
session: service(),
actions: {
invalidateSession() {
this.get('session').invalidate();
}
}
});
This is my code in app/routes/protected.js
import Route from '#ember/routing/route';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Route.extend(AuthenticatedRouteMixin, {
});
Any help is much appreciated!

Authentication using ReactJS and Firebase

I'm new to web development and started learning ReactJS.
Till now there is no problem with building simple web apps.
Now I wanted to use authentication using Firebase.
I know how to authenticate a user using Firebase but I'm not able to get how to design frontend to restrict access to certain pages.
Previously, I used PHP and in that I used session variable and include to include the parts of HTML to show to the user.
But I don't know how to do it in ReactJS using Firebase.
Initial and failed approach:
I thought of updating this.state.loggedIn and using that to show the component. But this is not a correct way because I'm sending both the components to display and easily we can change the state of a component using React developer extension in Chrome.
This is my main index.js code:
import React from 'react';
import ReactDOM from 'react-dom';
import Login from './components/Login/Login';
import Home from './components/Home/Home';
import fire from './components/Fire';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
loggedIn: false,
};
this.authListener = this.authListener.bind(this);
}
componentDidMount() {
this.authListener();
}
authListener() {
fire.auth().onAuthStateChanged(user => {
if (user) {
// User is signed in.
console.log(user);
this.setState({
loggedIn: true
})
} else {
// No user is signed in.
this.setState({
loggedIn: false
});
}
});
}
render() {
return (
<div>
{this.state.loggedIn ? <Home/> : <Login/>}
</div>
);
}
}
ReactDOM.render(
<App/>, document.getElementById('app'));
And In Login.js, I'm calling the Firebase authentication function.
Just the snippet:
fire
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.catch(function (error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log(error);
// ...
});
The authentication is working fine and I can see it in the console log.
So, how should I do it in ReactJS + Firebase to authenticate?(Is it posible without using any other packages like react-routes etc?)
Or should I be using Cloud functions for this?
UPDATE:
Everything you link in your html files should always come from your public directory. So, keep your bundled .js files in your public directory.
I have wrote some time saving tips for beginners. You can find more about that beginners tips here.
It is actually simple.
If you want to send only required html file to the browser, you have to hit the server every time you need a whole different html.
You said that you used PHP. In PHP, we use sessions to know whether a person is logged-in or not.
So, we try to implement it here.
First lets look at how sessions in PHP work. Taken from an SO Answer
In the general situation :
the session id is sent to the user when his session is created.
it is stored in a cookie (called, by default, PHPSESSID)
that cookie is sent by the browser to the server with each request
the server (PHP) uses that cookie, containing the session_id, to know which file corresponds to that user.
The data in the sessions files is the content of $_SESSION,
serialized (ie, represented as a string -- with a function such as
serialize) ; and is un-serialized when the file is loaded by
PHP, to populate the $_SESSION array.
Sometimes, the session id is not stored in a cookie, but sent in
URLs, too -- but that's quite rare, nowadays.
For more informations, you can take a look at the Session
Handling section of the manual, that gives some useful
informations.
For instance, there is a page about Passing the Session ID, which
explains how the session id is passed from page to page, using a
cookie, or in URLs -- and which configuration options affect this.
So, session is just a cookie. Then I guess we can use a cookie to find out about the user login status.
In Firebase, there is a problem with cookies. You can only set cookie name as __session. Other names are ignored by the Firebase and as a result you can't read cookies on the server.
You need to use Firebase Functions to do some backend work and serve html based on the user login status.
So, setup the Firebase Functions in your project directory. In the root,
$ firebase init functions
Now you have to say to Firebase that any requests coming to your domain must invoke a function.
To do that you have to write rewrites in your firebase.json file. Our function name will be main.
{
"database": {
"rules": "database.rules.json"
},
"hosting": {
"public": "/dev",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites":[{
"source": "**",
"function": "main"
}]
}
}
Now create an index.js anywhere(Prefer root of the project directory as this is the main file).
index.js
import express from 'express';
import * as functions from 'firebase-functions';
import fs from 'fs';
var cookieParser = require('cookie-parser')
const app = express();
app.use(cookieParser());
app.get('**', (req, res) => {
// Check the custom set cookie for user
// If the user is not logged-in, redirect to Login. Otherwise, redirect to Home page
if (req.cookies.__session == 'loggedin') {
var index = fs.readFileSync(__dirname + '/src/Home/index.html', 'utf8');
}
else {
var index = fs.readFileSync(__dirname + '/src/Login/index.html', 'utf8');
}
res.send(index);
});
export let main = functions.https.onRequest(app);
Some explanation about above parts:
express: It is used to process the requests and send the response.
firebase-functions: It is provided by the Google to use Firebase Functions.
fs : We read appropriate html according to the user login status from the file system and serve it.
cookie-parser: We use it to access our cookies easily.
Note: You need to convert it to ES5. So use babel command to convert it(I assume you saved index.js in your root.)
$ babel index.js -d functions
We are using cookie named __session to know about the user login status.
If the __session is set to loggedin, we send the user Home html. Otherwise, we send Login html.
Now, the real question is: "Where do we need to set the cookie __session?"
We set the cookie in the user browser.
We make use of onAuthStateChanged().
Call this method in your Login page component like:
componentDidMount() {
this.authListener();
}
authListener() {
fire.auth().onAuthStateChanged(user => {
if (user) {
// User is signed in.
if (Cookies.get('__session') === undefined) {
Cookies.set('__session', 'loggedin', { expires: 3652 });
window.location.reload();
}
} else {
// No user is signed in.
Cookies.remove('__session');
}
});
}
Note: Cookies object is imported from js-cookie. So, install it.
What we are doing here is:
First the onAuthStateChanged() is called initially when the page is loaded.
If the user is already logged-in, we enter into if block.
Then we check for the __session cookie. This is important because sometimes user can clear all the cookies. When we try to read the cookie in the server, we get undefined and we send the login page to the user. Process is repeated from 1.
Then we reload the page. When we reload the page, the user hits the server again. Then we can check for the __session cookie and send the Home html to the user.
Previously, I used PHP and in that I used session variable and include to include the parts of HTML to show to the user.
Firebase has a variety of ways it persists its auth state as described here: https://firebase.google.com/docs/auth/web/auth-state-persistence
By default it is local. On the Web, this is localStorage. This may be a drastic change for you since normally the auth state is in some sort of session or cookie that's done server side and client side.
So, how should I do it in ReactJS + Firebase to authenticate?(Is it posible without using any other packages like react-routes etc?)
But with Firebase, everything is done client side. Once a user has successfully authenticated, you will have access to their auth token as described here: https://firebase.google.com/docs/auth/users#auth_tokens
With this token, you would need to verify on the server side as described here: https://firebase.google.com/docs/auth/admin/verify-id-tokens in order to protect/secure any API access.
But for protecting certain pages in your React application, you will need to verify the auth state that is in localStorage in some sort of middleware. Preferably, you would have a listener for the auth state in one of your React lifecycle methods: https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged
At any point in your application, the auth state becomes invalid, block them from viewing the page.
Well, I show you how I used firebase Auth on a React App. I just want you to know that it's not THE RIGHT WAY, you'll find a lot of ways of doing it.
So let's begin, first I'm using the Google Auth, I've a file called firebase.service.js where I handle the auth. The file looks like:
import firebase from 'firebase';
import { firebaseConfig } from './private';
export const firebaseApp = firebase.initializeApp(firebaseConfig);
export const auth = firebase.auth();
export const db = firebase.database();
export function loginGoogle(/* options */) {
const provider = new firebase.auth.GoogleAuthProvider();
return firebase.auth().signInWithPopup(provider);
}
The firebaseConfig object looks like this:
const firebaseConfig = {
apiKey: API_KEY,
authDomain: AUTH_DOMAIN,
databaseURL: DB_URL,
projectId: PROJECT_ID,
storageBucket: STORE_BUCKET,
messagingSenderId: MSG_SENDER,
};
You can find it at Firebase Console.
At the index file of the app, where it's mounted, I wrapped the ReactDOM.render method with an auth check, to be sure if an user is or isn't logged. The index looks like:
import React from 'react';
import ReactDOM from 'react-dom';
import firebase from 'firebase';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { auth } from './services';
auth.setPersistence(firebase.auth.Auth.Persistence.LOCAL).then(() => {
const stop = auth.onAuthStateChanged(() => {
ReactDOM.render(<App />, document.getElementById('root'));
stop();
});
});
registerServiceWorker();
Now you're sure that if an user go away and come back to the app he won't need to login again if his session stills valid.
The next step is to create the PrivateRoute Component. Here is what I've done:
import * as React from 'react';
import { Redirect, Route } from 'react-router-dom';
import PropTypes from 'prop-types';
import { auth } from '../services';
function PrivateRoute({ component: Component, ...rest }) {
const toRender = propsRender => (
auth.currentUser ?
<Component {...propsRender} /> :
<Redirect
to={{
pathname: '/',
state: { from: propsRender.location },
}}
/>
);
return <Route {...rest} render={toRender} />;
}
PrivateRoute.propTypes = {
component: PropTypes.func.isRequired,
path: PropTypes.string.isRequired,
};
export default PrivateRoute;
Here you can see that the function checks if exists any logged user otherwise it sends the user back to the root path. Take note that I'm importing auth from the ./services not from the firebase, it's because this auth was initialized at firebase.service.js, then I use it through all application.
Now you can use this PrivateRoute as a common Route, the difference is that one will check if the user is logged. Take this as example:
import * as React from 'react';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import { Layout } from 'antd';
import moment from 'moment';
import 'moment/locale/pt-br';
import 'antd/dist/antd.css';
import { PrivateRoute, MainLogged, Login, Navbar, Page404 } from './components';
const { Header } = Layout;
moment.locale('pt-br');
function Main() {
return <Redirect to="/login" />;
}
function App() {
return (
<BrowserRouter>
<Layout>
<Header style={{ paddingLeft: '0', backgroundColor: '#096dd9' }}>
<Navbar />
</Header>
<Switch>
<Route exact path="/" component={Main} />
<Route exact path="/login" component={Login} />
<PrivateRoute path="/app" component={MainLogged} />
<Route component={Page404} />
</Switch>
</Layout>
</BrowserRouter>
);
}
export default App;
As you can see PrivateRouse is beeing used side by side the Route component from react-router.
I thought that it's all, if you want to ask anything else just comment, and if you want to take a look on the project from where I take this codes, you can find it here.

Unable to load second level routing page in vuejs after refreshing it

I have my VueJS app running. It is working fine but the only issue is that when I try to refresh the second or third level routing pages, it shows me an error message in the console, stating:
Failed to load resource: the server responded with a status of 404 ()
For eg.,
http://localhost:8080 renders me home page. No issue on refreshing.
http://localhost:8080/details renders details page. No issue on refreshing.
http://localhost:8080/details/users renders users page. On refreshing, it errors out.
I also have similar links defined for http://localhost:8080/details/assets and http://localhost:8080/details/groups which all errors out on page refresh.
Here is the code for main.js:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import { routes } from './routes';
Vue.use(VueRouter);
//Vue.config.productionTip = false
const router = new VueRouter({
mode: 'history',
routes
});
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
new Vue(Vue.util.extend({ router }, App)).$mount('#app');
and for routes.js:
import Home from './components/summary.vue'
import Details from './components/details/details.vue'
import Users from './components/details/users/users.vue'
import Assets from './components/details/assets/assets.vue'
import Groups from './components/details/groups/groups.vue'
export const routes = [
{ path: '/', component: Home},
{ path: '/details', component: Details},
{path: '/details/users', component: Users},
{path: '/details/groups', component: Groups},
{path: '/details/assets', component: Assets}
];
Any idea on how to fix this issue?
As is described in official document of vue-router
To get rid of the hash, we can use the router's history mode, which leverages the history.pushState API to achieve URL navigation without a page reload
So navigating only in front end will not send request to back end, which is your spring boot application (you can see this from network traffic)
However, when you refresh your page, the request is sent directly to back end, which results the 404 error.
To fix your problem, one option could be setting a default 404 page to index.html which is suggested here
#Component
public class WebConfiguration implements EmbeddedServletContainerCustomizer {
#Override
public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
configurableEmbeddedServletContainer.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/index.html"));
}
}
Hope it works for you!

How to transit from a component to a route in ember

I have a popup component in which i have a button and on click of that if im in my target route (mainRoute) i just want to pass the query parameters to my current route, but if i'm in another route i just want to transit with new query parameters. I know neither transitionTo or transitionToroute work. Is there any way to do that?
The transitionTo wouldn't work because you don't have access to routing from inside your component context. You can add the routing support at any place in your app using -routing service like so:
export default Ember.Component.extend({
routing: Ember.inject.service('-routing'),
someFuncUsingRouting(){
let routing = this.get('routing');
routing.transitionTo('some-route');
}
});
This is my code for logout function that close the session and redirect you to /login route.
import Ember from 'ember';
export default Ember.Component.extend({
authManager: Ember.inject.service('session'),
routing: Ember.inject.service('route'),
tagName: '',
actions: {
invalidateSession() {
console.log("logout invalidateSession");
this.get('authManager').invalidate();
let routing = this.get('routing');
routing.transitionTo('login');
}
}
});
This is working code for:
ember-cli: 2.8.0
node: 7.1.0

Categories