I am using backbone router to redirect to my pages, I have for example this url
http://localhost:56508/#/RegistryMain/44/1234
The code
RegistryMain: function (id, cnt) {
var self = this;
this.load();
require([
'js/views/Questionaire/RegistryMain'
], function (RegistryMainView) {
self.shell();
if (typeof app.RegistryMainView !== 'undefined') {
app.RegistryMainView.destroy();
}
app.RegistryMainView = new RegistryMainView({ Id: id, cnt: cnt });
$("#main-nav li.active").removeClass("active");
$("#admin").addClass("active");
});
},
For security reasons, I need to hide /44/1234 from the url so the user can't reuse them or change them to /45/1234 for example and access forbidden pages.
How can i do this in backbone?
And if i should use the POST approach, how to use it in backbone?
mu is too short is right in saying that you're trying to handle security in the wrong place. You can't trust client-side code, at all.
You should check the rights of the user from the server each time the frontend app calls an API endpoint to avoid your users navigating to pages they don't have the rights to see, or to avoid them messing with the data by posting invalid stuff to an endpoint.
Your API should return a 401 unauthorized HTTP response code to notify your frontend app of the situation.
And for smooth page transition, redirect the user to an error page if an API call fails.
That being said
To avoid showing a url, you can directly call loadUrl:
// current url: http://localhost:56508/#/RegistryMain
Backbone.history.loadUrl("RegistryMain/44/1234");
// current url: http://localhost:56508/#/RegistryMain
This will trigger the route callback without changing the url, so the user never sees the params.
Now that I use .loadUrl in my project, all pages have the same URL, but when I refresh a page, it redirects to the login page (the first
page in my project). How to make it refresh the current page?
That's a drawback of not using the url to trigger routes, you now can't know the state of the app as a single page app lives in the current page only and refreshing starts a new instance completely.
You should really rethink if not using the url is the right choice. If it still is, you could save the current url in the localStorage and use it on the app startup to redirect to the right page.
Related
So I have a login scheme that only needs user login behind specific pages. Currently, I have the page checking if the user exists via the $onInit function, then firing the login (which redirects to a login page via Code Flow in OAuth 2). Then when I've logged in, the page redirects back to the previous page, instead of the page I fired the login even from.
I think this is due to ui-router not registering history with the browser before it redirects, thus the $state object in the OAuth 2 parameters, when decoded shows me the path: "redirectUrl":"http://localhost:3000/reservations" when it should be "redirectUrl":"http://localhost:3000/reservations/purchase".
So my question is two fold.
Is $onInit an appropriate place to be doing this, or should I have some global routechange listener or use resolve? If I use either of those two methods, I think I will still have the route problem.
If I keep using $onInit, is there some way to make sure the url is registered correctly so that it will redirect to the correct location post-login?
$onInit function:
function init() {
var token = Meteor.call('getAccessToken');
if (!token) {
Meteor.loginWithOidc();
}
}
In my angularjs mobile app, I need the certain requirements. Initially, the app is in the home page. If the user needs to go to the next page in that app, he has to click on that certain content. And it will redirect them to the next page of that particular content. After that, If he wants to go to the previous(back) page, he has to click on the back button.
What I need is, when user is going back to the previous page where he was in, that page is reloading. Instead of reloading that previous page, he should be taken to the same place where he was before. So, how to disable the reload. And I think it can be achieved using 'ui.router' and its $stateChangeStart. For url routing I use '$routeProvider'. So how to achieve this one? Please help me out.
For homepage the url is -
'/myapp/landingpage'
For the next page (when he clicks on the particular content) the url is -
'myapp/content/:contentId'
If you home page is a plain static page - then nothing is required - the template for the home page is already cached in the $templateCache.
Else if your home page has some data that is fetched from some service, I would suggest you to cache the data in your angularjs service layer itself.
You can explore $cacheFactory for more details.
If you do not want to use $cacheFactory directly, you can simply use 'cahce:true' property in yout $http.get request :-
$http.get(url, { cache: true}).success(...);
From the $http docs:-
cache – {boolean|Cache} – If true, a default $http cache will be used
to cache the GET request, otherwise if a cache instance built with
$cacheFactory, this cache will be used for caching.
The idea is not to mess up view/states for caching and move that responsibility to your service layer.
Sample Code (using passport-local on angular-fullstack):
app.get('/logout', function(req, res) {
req.logout();
console.log('testing123');
res.redirect('/login');
}
Whenever this code executes, the url displays /logout for a moment before reverting back to the main page. The logout function seems to be running accordingly, and I have attempted to setup a route client side using angular to hold a blank html template to confirm. The bug is in the redirection, coming from a link on the navbar. Also, no log appears in the console on the browser (not that it should) or terminal.
Attempted Solutions:
1.) Adding in the route client side to create test template to ensure app.get(url/logout) has been called and logout() has been implemented.
2.) Changing the redirect route to another template. (Same effect)
3.) Inspecting both route reversions that account for non-registered routes for the client and the express server. This was done through the inclusion on both sides of '/logout' routes being instantiated and tested.
Any help is greatly appreciated. Thanks.
Resolution:
$http get request, upon success, redirected to login using $location.path()
if the route is hit by an xhr request the app won't go anywhere because you are not redirecting the browser just the ajax call, you have to implement listen for the logout call response on your angular app and clear your headers and redirect the browser
I apologize this question turned out a bit long, but I have worked on this for some time and really needed to explain all the story.
Background: App based on MEAN stack, trying to authorize Facebook logins using Passport.js.
Following Passport.js guide I implemented something similar to:
// HTML
Add a Facebook login
// send to facebook to do the authentication
app.get('/connect/facebook',isLoggedIn, passport.authorize('facebook',
{ scope : 'email' })
);
// handle the callback after facebook has authorized the user
app.get('/connect/facebook/callback',
passport.authorize('facebook', {
successRedirect : '/profile',
failureRedirect : '/profile'
}));
Notice the target=_self in the html in order to skip Angular routing.
Clearly, authorization works fine. However, redirection does not work, as the routing is handled by Angular. After authorization I never land on /profile (but on the default Angular route).
Therefore, I tried with a custom callback as suggested by Passport.js here, with the hope of passing json data to Angular, and let Angular do the routing. I ended up doing something like:
// In the controller
$http.get("/connect/facebook").success(function(data){
// here I wait for json data from the server and do the routing
});
// I call this route from Angular
app.get('/connect/facebook',isLoggedIn,passport.authorize('facebook',
{ scope : 'email' })
);
// But Facebook lands here!
app.get('/connect/facebook/callback',function(req, res, next) {
passport.authorize('facebook', function(err, user, info) {
res.json({something:smtg});
...
Clearly custom callbacks work for local-login, as Passport.js explains. But here do you see the problem? I call /connect/facebook from Angular, but I should receive some json from /connect/facebook/callback.
I am about to give up Passport, but before this, do you see any solution which would allow landing on /profile after FB authorization, perhaps with a custom message? Many thanks for reading through.
EDIT:
The same question had been reported as an issue on the Passport-Facebook GitHub account. Some additional attempts have been posted there, but not quite the fix yet.
This is a bit more in depth than can be described in one answer, but I'll try to start pointing you in the right direction.
Essentially, Angular.js routes are not really HTML routes at all, but an internal route structure that happens to use the URL for use of the end user. Remember that Angular.js is a client script, and that a full page reload is not desired, as this will reload the entire script. Therefore, /# is used to trick the browser into jumping to a specific bit of code within the already loaded script. (as opposed to the traditional anchor location in the HTML document). Unfortunately (or fortunately), HTML 5 mode allows you to hide the /# part of the url, so instead of seeing http://somesite.com/#/someroute you just see http://somesite.com/someroute. Rest assured, however, that the /# is still there. Angular.js uses the HTML5 pushState (AKA HistoryAPI) to perform the magic replacement.
Given this, if you have called a server route, you are outside the Angular.js script, and any call to load the angular script again will start from the very beginning. You can't actually call your Angular.js route from the server without a full reload. Therefore, you are really doing a double route redirect here. Your server should be calling it's default route for angular, appending /#/someroute to the call. The angular.js page will load, parse off the /#, and redirect to the correct angular route. Keep in mind, however, that if there was any dependency on already loaded objects, those are no longer in memory. Therefore, any route accessed this way should operate as if it is an entry point to your application.
Effectively, you should try using successRedirect : '#/profile', keeping in mind that the profile route in angular should be treated as an app entry point.
Hopefully this gets you started.
If #Claies's way is not working, is it possible you have not get rid of the #= fragment from the facebook callback.
Have a read of this post
We have two diferent apps in our environment, one that handles login and the main portal. When anyone try to access a portal url and its not logged, the "otherwise" function will save this url and redirect to login.
$urlRouterProvider.otherwise(function($injector, $location){
console.log($location.absUrl());
//save attempted url
//redirect to login,
var loginUrl=$location.absUrl() + '#/login';
var $window=$injector.get('$window');
console.log(loginUrl);
$window.location.href=loginUrl;
});
This work fine in firefox, but in chrome, the 'login' state are never resolved, so it fall back to the default function every time, causing a loop.
You can see this issue in http://plnkr.co/edit/l51Wqn0EB1ySDjbScSvY
Could anyone help me with a solution?
EDIT : I need to perform the redirect with $window.location.href, because this app sometimes get loaded on /portal and need to redirect to /#/login.
When the app initially loads, it is hitting the "" path before going to the path in the URL (in your case, #/login). Each time you do a $window.location, you tell the app to reload. On each reload it looks for a state mapping to "" and cannot find it so it hits the otherwise... thus looping.
You can handle the empty route with a "when"
.when('', '/login')
You can also default it to your home page, assuming you would have logic for your home page to kick the user back to login if they are not logged in.
Not too sure if there is a need to use $window.location, but if you are only trying to store the current location and then direct to one of your states you can inject $state and use $state.go(...)
$urlRouterProvider.otherwise(function($injector, $location){
console.log($location.absUrl());
//save attempted url
//redirect to login,
var $state=$injector.get('$state');
$state.go('login');
});
Updated plunker: http://plnkr.co/edit/aMsjxQ9WQIXqrQ7e9MJq?p=preview