Flutter: Navigation issues between lifecycle of app - authentication

In my application, I'm using routes to navigate between pages.
Here's how I implemented route:
In main.dart file, I've defined routes like this:
bool session = await isValidSession(); //queries database and validate session
if (session) {
_defaultHome = new HomePage();
}
final routes = {
'/login': (BuildContext context) => new LoginPage(),
'/home': (BuildContext context) => new HomePage(),
//several other pages
'/logout' : (BuildContext context) => new LogoutPage(),
};
I've passed that route as argument to runApp method:
runApp(new MaterialApp(
title: 'My Application',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: _defaultHome,
routes: routes,
));
The pages are navigatable through drawer menu. When user will Tap on a menu, this code executes and take customer to respective page.
Navigator.of(context).pushNamed("/PAGE_NAME");
Problematic Scenario:
When user open app, fill up form and try to login
A function validates credentials and login user
Upon successful login, I've this code for navigating to Home page.
Navigator.of(context).popAndPushNamed("/home");
According to official documentation of popAndPushNamed method,
Pop the current route off the navigator that most tightly encloses the given context and push a named route in its place.
So according to my understanding, popAndPushNamed is supposed to remove login page from context and will navigate to home page.
It doesn't work as expected, it navigates to home page but doesn't remove login page from context, because pressing back button, takes back to login page (even the form is in filled state).
Alternatively, if I pop current context and push to new page then it works as expected.
Navigator.pop(context);
Navigator.of(context).pushNamed("/home");
But there's still an issue with this approach, when I Tap on back button from home page. The screen goes blank, instead of quitting the app.
Questions:
How do I properly remove login page from context? (if user press back button then app quits)
When user logout, how do I remove all pages from context and navigate to login page? (already tried but it doesn't work in my case)
Navigator.of(context).popUntil(ModalRoute.withName('/login'));

you can try this for logout :
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (BuildContext context) => LoginPage()),
ModalRoute.withName('/'));

Related

Flutter Web - Authentication. User ID lost on hot reload

I am very new to Flutter Web and have been pulling my hair out over this one. This is exactly how I authenticate my users on mobile but for some reason when I use hot reload on flutter web the user authentication is lost and returns null and shows the CircularProgressIndicator(CPI).
Why is it doing this? If null is called then surely it should show the LoginPage() - which is does when the page is initially loaded - but as soon as I hot reload it returns null and the CPI.
Further - I added a print statement to help me keep track of the user calls - and noticed each time I navigate to a new page the user id is printed and wondering why this is?
What I would like to achieve:
Landing page directs user to login page if snapshot.data == null
Landing page directs user to home page if snapshot.data != null
Return a circularprogressindicator if ConnectionState.waiting
Fix the error as described above
class Landing extends StatelessWidget {
#override
Widget build(BuildContext context) {
final auth = Provider.of<UserRepository>(context, listen: false);
return StreamBuilder(
stream: auth.onAuthStateChanged,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
User user = snapshot.data;
print(user);
return user == null ? LoginPage() : HomePage();
} else
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
},
);
}
}
I was running the program via F5 rather than flutter run -d chrome
Running the program via F5 allows one to press the hot reload button on VScode but importantly hot reload is currently not available on Flutter Web.
I believe, in part, this has answered my question.
You are passing a stream into a Stateless widget.
Change Stateless widget to stateful widget this will solve your problem.

Aurelia cancel navigation in navigation strategy

I have a login route that will redirect the user to an external Open ID Connect login page. Once there, if the user clicks the back button, they hit the same route that redirected them, thus being redirected again. Is there a way to cancel Aurelia's navigation or prevent the current route from being remembered in the history?
config.mapRoute({
name: "login",
nav: false,
// If I exclude the module id, I get the desired behavior but errors are thrown from Aurelia.
moduleId: "components/login/login",
route: "login",
navigationStrategy: (instruction: NavigationInstruction) => {
// This promise constructs the redirect url then sets the window.location.href.
// Unfortunately, Aurelia seems to be finishing its business before the page is redirected because this login route is recorded in history.
return this.userManager.signinRedirect();
}
});
I know its been a while so you probably found an answer elsewhere, but you can try
router.navigate('new url', { replace: true });

react native navigationExperimental NavigationCardStack renderScene didn't re-render for previous routes

I already checked similar existing issues on stack-overflow or gihub, like:
NavigationCard will only re-render when the route changes, Help: renderScene is executed just once and does not refresh updated props, etc. But my case is different.
Page list:
sign in page
home page: user can only see this page after sign in;
Transition logic:
In "sign in page", after sign in, it shall go to "home page"
In "home page", there is a sign out button, after user click, it shall go back to "sign in" page.
My implementation
I created a top level component called App, and the code looks like the below:
// app.js
class App extends Component {
componentWillMount() {
const {doNavigateReplaceAtIndex} = this.props;
let {isSignedIn} = this.props;
doNavigateReplaceAtIndex(isSignedIn? 'home': 'sign-in');
}
render() {
const {globalNavigationState} = this.props;
return (
<NavigationCardStack
navigationState={globalNavigationState}
style={styles.container}
onNavigate={()=>{}}
renderScene={this._renderScene}
/>
);
}
_renderScene({scene}) {
const { route } = scene;
switch(route.key) {
case 'home':
return <Home />
case 'sign-in':
return <SignIn />
}
}
}
export default connect (
state =>({
isSignedIn: !! state.auth.token,
token: state.auth.token,
globalNavigationState: state.globalNavigation
}),
dispatch => ({
doNavigateReplaceAtIndex: (key) => dispatch(navigateReplaceAtIndex(0, key))
})
)(App);
// sign in page
// after signin, it will doNavigateReplaceAtIndex(0, 'home');
// home page
// after clicking "sign out", it will doNavigateReplaceAtIndex(0, 'sign-in');
// doNavigateReplaceAtIndex basically is just call NavigationStateUtils.replaceAtIndex
Symptoms
At beginning, it shows sign in page, after signing in, it goes to home page, it is good. In home page, when click the sign out button, it didn't move anywhere, but when refresh, it shows sign in page.
What I got so far
It is not because of this issue: NavigationCard will only re-render
when the route
changes,
because I debugged into rn source code, the shouldComponentUpdate didn't block;
I am not sure if I didn't right for doNavigateReplaceAtIndex, usually we use push or pop, but my case I cannot use push/pop, because after sign in, we should not allow use to go back sign in page by clicking "BACK" button on Android.
I think the issue may because of NavigationScenesReducer(which is called by NavigationAnimatedView used in NavigationCardStack), it will mark all previous routes as stale, and will not show it them.
Any help will be welcome, thanks.
My environment
react native: 0.29.1
react native cli: 1.0.0
node: 5.6.0
OS: ios 9.3

preventing user to go back once logged out in laravel 5

I have a logout function like this
public function logout() {
Auth::logout(); // logout user
return Redirect::to('login'); //redirect back to login
}
When logout function is triggered through routes which looks like
Route::get('logout', array(
'uses' => 'userController#logout'
));
user get redirected to the login page. But when goes back using browser, dashboard view gets opened which i don't want to. What can be the best way to prevent users from going back to dashboard once they logged out? Though there are some discussion on this topic, but didn't helped me.
Since you're using the Auth, you can utilise the existing Middleware to stop the back button putting them on dashboard.
Wrap the routes you want to protect with a Route::group
Route::group(['middleware' => 'auth'], function () {
Route::get('dashboard', function () {
// Uses Auth Middleware
});
});
Any attempt to access dashboard without login will put them back on the home page (default location in the middleware). Modify the middleware (found in app/Http/Middleware/Authenticate.php) to change the redirect url.
you need to add a middleware in your dashboard so that even if they press back the button they can go back to the page but can't do anything unless they login again.

Sencha Touch history issue, when using routes and route filters

In Sencha Touch 2, I have a beforeFilter, before the routes.
When the user wants to visit a certain view, the "beforeFilter" acts first.
I use the filters for authentication check and other things.
I kept the example very simple, to highlight where I need help:
Ext.define("TestApp.controller.Router", {
extend: "Ext.app.Controller",
config: {
before: {
home: 'beforeFilter',
login: 'beforeFilter',
products: 'beforeFilter'
},
routes: {
'': 'home',
'home' : 'home',
'login' : 'login',
'products' : 'products',
'products/:id': 'product',
}
},
beforeFilter: function(action) {
// The before filter acts before the user gets to any of the routes.
// Check the user's authentication state.
// If the user wants to visit the "products" route and he ISNT't authenticated,
// Redirect the user to the login page.
this.redirectTo('login');
// else - go to the normal root.
action.resume();
},
home: function () {
// This and the functions bellow handle the display of the routes.
},
login: function () {
},
products: function () {
}
});
The problem.
User wants to view the products route but he isn't logged in.
The beforefilter steps in, and redirects the user to the login page.
Here is where I need help:
If the user is on the login page and clicks a button which triggers Sencha's history.back() event, the user gets redirected to the products page, AGAIN, the beforefilter steps in, and it redirects him back to the login view.
Basically, the history will no longer work.
To solve the problem, I would need a way to keep the products route from being logged into Sencha's history object when the user isn't authenticated.
Do you guys have other ideas?
I asked a more general question about this, but this one feel more documented to the issue in particular.
For views that you don't want to have history support, simply add / change the view without using redirectTo.
Straigh to viewport:
Ext.Viewport.add({xtype: 'myloginview'})
or with navigation view (in a controller):
this.getMyNavView().push({xtype: 'myloginview'})
this way the url doesn't change to #login, and doesn't add to the history stack.