This is the continuation of my question
So far i didn't even get the url value. But now i can able to get the url paameter but the problem is that my page is getting redirected once showing the alert
Here is my controller and route
route
.when('/showprofile/:UserID', {
templateUrl: 'resources/views/layout/showprofile.php',
controller: 'ShowUserCtrl'
})
Controller ;
app.controller('ShowUserCtrl', function($scope, $routeParams) {
var b = $routeParams.UserID;
alert(b);
$scope.userid = $routeParams.UserID;
});
My View :
{{userid}}
The problem is My Url is like this
http://192.168.1.58/myapp/#/showprofile/18
After showing the alert 18
It makes the url like
http://192.168.1.58/myapp/#/showprofile/:UserID
How can i stop the redirection .. ??
I just want this as my final url
http://192.168.1.58/myapp/#/showprofile/18
I found that the problem is because of .run function that i have.
After removing it works good.
Here is my .run function
.run(function ($rootScope, $location, Data, $http) {
$rootScope.$on("$routeChangeStart", function (event, next, current) {
$http.post('CheckSession', {}).then(function (results)
{
console.log(results.data);
var nextUrl = next.$$route.originalPath;
if (nextUrl == '/signin' || nextUrl == '/login' || nextUrl == '/verify' || nextUrl == '/registration' || nextUrl == '/forget' || nextUrl == '/invalidtoken' || nextUrl == '/registersuccess')
{
console.log('outpages');
}
else
{
if (results.data == 1)
{
console.log('loggedin');
console.log(nextUrl);
console.log('to be redirect');
$location.path(nextUrl);
}
else {
console.log('not logged in');
$location.path('login');
}
}
});
});
});
Related
I am following this article on Social Logins with AngularJS and ASP.Net WebAPI (which is quite good):
ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app
Pretty much, the code works fine when you are running the social login through a desktop browser (i.e. Chrome, FF, IE, Edge). The social login opens in a new window (not tab) and you are able to use either your Google or Facebook account and once your are logged in through any of them, you are redirected to the callback page (authComplete.html), and the callback page has a JS file defined (authComplete.js) that would close the window and execute a command on the parent window.
the angularJS controller which calls the external login url and opens a popup window (not tab) on desktop browsers:
loginController.js
'use strict';
app.controller('loginController', ['$scope', '$location', 'authService', 'ngAuthSettings', function ($scope, $location, authService, ngAuthSettings) {
$scope.loginData = {
userName: "",
password: "",
useRefreshTokens: false
};
$scope.message = "";
$scope.login = function () {
authService.login($scope.loginData).then(function (response) {
$location.path('/orders');
},
function (err) {
$scope.message = err.error_description;
});
};
$scope.authExternalProvider = function (provider) {
var redirectUri = location.protocol + '//' + location.host + '/authcomplete.html';
var externalProviderUrl = ngAuthSettings.apiServiceBaseUri + "api/Account/ExternalLogin?provider=" + provider
+ "&response_type=token&client_id=" + ngAuthSettings.clientId
+ "&redirect_uri=" + redirectUri;
window.$windowScope = $scope;
var oauthWindow = window.open(externalProviderUrl, "Authenticate Account", "location=0,status=0,width=600,height=750");
};
$scope.authCompletedCB = function (fragment) {
$scope.$apply(function () {
if (fragment.haslocalaccount == 'False') {
authService.logOut();
authService.externalAuthData = {
provider: fragment.provider,
userName: fragment.external_user_name,
externalAccessToken: fragment.external_access_token
};
$location.path('/associate');
}
else {
//Obtain access token and redirect to orders
var externalData = { provider: fragment.provider, externalAccessToken: fragment.external_access_token };
authService.obtainAccessToken(externalData).then(function (response) {
$location.path('/orders');
},
function (err) {
$scope.message = err.error_description;
});
}
});
}
}]);
authComplete.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<script src="scripts/authComplete.js"></script>
</body>
</html>
authComplete.js
window.common = (function () {
var common = {};
common.getFragment = function getFragment() {
if (window.location.hash.indexOf("#") === 0) {
return parseQueryString(window.location.hash.substr(1));
} else {
return {};
}
};
function parseQueryString(queryString) {
var data = {},
pairs, pair, separatorIndex, escapedKey, escapedValue, key, value;
if (queryString === null) {
return data;
}
pairs = queryString.split("&");
for (var i = 0; i < pairs.length; i++) {
pair = pairs[i];
separatorIndex = pair.indexOf("=");
if (separatorIndex === -1) {
escapedKey = pair;
escapedValue = null;
} else {
escapedKey = pair.substr(0, separatorIndex);
escapedValue = pair.substr(separatorIndex + 1);
}
key = decodeURIComponent(escapedKey);
value = decodeURIComponent(escapedValue);
data[key] = value;
}
return data;
}
return common;
})();
var fragment = common.getFragment();
window.location.hash = fragment.state || '';
window.opener.$windowScope.authCompletedCB(fragment);
window.close();
The issue I am having is that when I run the application on a mobile device (Safari, Chrome for Mobile), the social login window opens in a new tab and the JS function which was intended to pass back the fragment to the main application window does not execute nad the new tab does not close.
You can actually try this behavior on both a desktop and mobile browser through the application:
http://ngauthenticationapi.azurewebsites.net/
What I have tried so far in this context is in the login controller, I modified the function so that the external login url opens in the same window:
$scope.authExternalProvider = function (provider) {
var redirectUri = location.protocol + '//' + location.host + '/authcomplete.html';
var externalProviderUrl = ngAuthSettings.apiServiceBaseUri + "api/Account/ExternalLogin?provider=" + provider
+ "&response_type=token&client_id=" + ngAuthSettings.clientId
+ "&redirect_uri=" + redirectUri;
window.location = externalProviderUrl;
};
And modified the authComplete.js common.getFragment function to return to the login page, by appending the access token provided by the social login as query string:
common.getFragment = function getFragment() {
if (window.location.hash.indexOf("#") === 0) {
var hash = window.location.hash.substr(1);
var redirectUrl = location.protocol + '//' + location.host + '/#/login?ext=' + hash;
window.location = redirectUrl;
} else {
return {};
}
};
And in the login controller, I added a function to parse the querystring and try to call the $scope.authCompletedCB(fragment) function like:
var vm = this;
var fragment = null;
vm.testFn = function (fragment) {
$scope.$apply(function () {
if (fragment.haslocalaccount == 'False') {
authenticationService.logOut();
authenticationService.externalAuthData = {
provider: fragment.provider,
userName: fragment.external_user_name,
externalAccessToken: fragment.external_access_token
};
$location.path('/associate');
}
else {
//Obtain access token and redirect to orders
var externalData = { provider: fragment.provider, externalAccessToken: fragment.external_access_token };
authenticationService.obtainAccessToken(externalData).then(function (response) {
$location.path('/home');
},
function (err) {
$scope.message = err.error_description;
});
}
});
}
init();
function parseQueryString(queryString) {
var data = {},
pairs, pair, separatorIndex, escapedKey, escapedValue, key, value;
if (queryString === null) {
return data;
}
pairs = queryString.split("&");
for (var i = 0; i < pairs.length; i++) {
pair = pairs[i];
separatorIndex = pair.indexOf("=");
if (separatorIndex === -1) {
escapedKey = pair;
escapedValue = null;
} else {
escapedKey = pair.substr(0, separatorIndex);
escapedValue = pair.substr(separatorIndex + 1);
}
key = decodeURIComponent(escapedKey);
value = decodeURIComponent(escapedValue);
data[key] = value;
}
return data;
}
function init() {
var idx = window.location.hash.indexOf("ext=");
if (window.location.hash.indexOf("#") === 0) {
fragment = parseQueryString(window.location.hash.substr(idx));
vm.testFn(fragment);
}
}
But obviously this is giving me an error related to angular (which I have no clue at the moment):
https://docs.angularjs.org/error/$rootScope/inprog?p0=$digest
So, pretty much it is a dead end for me at this stage.
Any ideas or input would be highly appreciated.
Gracias!
Update: I managed to resolve the Angular error about the rootscope being thrown, but sadly, resolving that does not fix the main issue. If I tried to open the social login on the same browser tab where my application is, Google can login and return to the application and pass the tokens required. It is a different story for Facebook, where in the Developer's tools console, there is a warning that seems to stop Facebook from displaying the login page.
Pretty much, the original method with which a new window (or tab) is opened is the way forward but fixing the same for mobile browser seems to be getting more challenging.
On desktop, when the auth window pops up (not tab) it has the opener property set to the window which opened this pop up window, on mobile, as you said, its not a pop up window but a new tab. when a new tab is opened in the browser, the opener property is null so actually you have an exception here:
window.opener.$windowScope.authCompletedCB
because you can't refer the $windowScope property of the null value (window.opener) so every line of code after this one wont be executed - thats why the window isn't closed on mobile.
A Solution
In your authComplete.js file, instead of trying to call
window.opener.$windowScope.authCompletedCB and pass the fragment of the user, save the fragment in the localStorage or in a cookie (after all the page at authComplete.html is in the same origin as your application) using JSON.stringify() and just close the window using window.close().
In the loginController.js, make an $interval for something like 100ms to check for a value in the localStorage or in a cookie (don't forget to clear the interval when the $scope is $destroy), if afragment exist you can parse its value using JSON.parse from the storage, remove it from the storage and call $scope.authCompletedCB with the parsed value.
UPDATE - Added code samples
authComplete.js
...
var fragment = common.getFragment();
// window.location.hash = fragment.state || '';
// window.opener.$windowScope.authCompletedCB(fragment);
localStorage.setItem("auth_fragment", JSON.stringify(fragment))
window.close();
loginController.js
app.controller('loginController', ['$scope', '$interval', '$location', 'authService', 'ngAuthSettings',
function ($scope, $interval, $location, authService, ngAuthSettings) {
...
// check for fragment every 100ms
var _interval = $interval(_checkForFragment, 100);
function _checkForFragment() {
var fragment = localStorage.getItem("auth_fragment");
if(fragment && (fragment = JSON.parse(fragment))) {
// clear the fragment from the storage
localStorage.removeItem("auth_fragment");
// continue as usual
$scope.authCompletedCB(fragment);
// stop looking for fragmet
_clearInterval();
}
}
function _clearInterval() {
$interval.cancel(_interval);
}
$scope.$on("$destroy", function() {
// clear the interval when $scope is destroyed
_clearInterval();
});
}]);
i can't access to the cookies stored in localhost.
The cookis are already stored (view image)
When i try to display, i get undefined (view image)
Here is my js code for display :
var app = angular.module("Authentification", ['ngCookies']);
app.controller("log", ['$cookieStore', '$scope', '$http', function($cookieStore, $scope, $http) {
$scope.typeEmploye = $cookieStore.get('typeEmploye');
alert($scope.typeEmploye);
}]);
Here is my js code where i store the attribute in cookies after getting the result from my rest API.
var app = angular.module("Authentification", ['ngCookies']);
app.controller("main", ['$cookieStore', '$scope', '$http','$location',
function($cookieStore, $scope, $http, $location) {
$scope.user = [];
$scope.type=[];
$scope.auth = function() {
$http.get("/Employe/authentification?login=" + $scope.log + "&password=" + $scope.pw)
.success(function(data) {
console.log(data);
if (data) {
$scope.user = data;
$cookieStore.put('typeEmploye', $scope.user.type);
$cookieStore.put('Authentified',true);
$scope.type=$cookieStore.get('typeEmploye');
if($scope.type == "gerant"){
window.location.href = "/Gerant/index.html";
}
else if($scope.type == "cuisinier"){
window.location.href = "/Cuisinier/index.html";
}
else if($scope.type == "servant"){
window.location.href = "/Servant/index.html";
}
else{
window.location.href = "/error";
}
}
else{
alert("Login ou mot de passe incorrects");
}
}).error(function(data, status) {
alert("Problème dans le service d'authentification");
});
};
}]);
The information is stored in cookies. But, when i go to an other page ( with a different js file), i can't get the cookies. here is the js code.
var app = angular.module("ger", ['ngCookies']);
app.controller("main", ['$cookies', '$scope', '$http','$location',
function($cookies, $scope, $http, $location) {
var Type = $cookies.typeEmploye;
alert(Type);
}]);
Im trying to verify that a user is logged in. Initially I went with $scope.use, $scope.user.uid, $scope.getCurrenUser() as described on Firebase docs but I think I simply have the dependencies wrong.
Code:
myApp.js
https://gist.github.com/sebbe605/2b9ff7d3b798a58a3886
firebase.js
https://gist.github.com/sebbe605/f9e7b9a75590b3938524
If I understand this correctly there is no way for the program to know that I'm referring to a Firebase user. To clarify I want .controller('templateCtrl',function($scope, $firebase) to have the ability to show a certain button if the user is logged in.
--UPDATE 1--
So, i have updated my files and for what i understand this should work. Previous code are as gits above to enhance the cluther.
myApp.js
angular.module('myApp', [
'ngRoute',
'firebase'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/template',
{
templateUrl:'partials/template.html', controller:'templateCtrl'
});
$routeProvider
.when('/login',
{
templateUrl:'partials/login.html', controller:'signupCtrl'
});
$routeProvider
.when('/signup',
{
templateUrl:'partials/signup.html', controller:'signupCtrl'
});
$routeProvider
.when('/user',
{
templateUrl:'partials/user.html', controller:'userCtrl'
});
$routeProvider
.otherwise('/template');
}])
controllers.js
'use strict';
angular.module('myApp').controller('signupCtrl', function($scope, $http, angularFire, angularFireAuth){
$scope.loginBusy = false;
$scope.userData = $scope.userData || {};
var ref = new Firebase('https://boostme.firebaseio.com/');
angularFireAuth.initialize(ref, {scope: $scope, name: 'user'});
/*//////////////LOGIN - LOGOUT - REGISTER////////////////////*/
$scope.loginEmailText = "Email"
$scope.loginPasswordText = "Password"
$scope.login = function() {
$scope.loginMessage = "";
if ((angular.isDefined($scope.loginEmail) && $scope.loginEmail != "") && (angular.isDefined($scope.loginPassword) && $scope.loginPassword != "")) {
$scope.loginBusy = true;
angularFireAuth.login('password', {
email: $scope.loginEmail,
password: $scope.loginPassword
});
} else {
$scope.loginPassword = ""
$scope.loginPasswordText = "Incorrect email or password"
}
};
$scope.logout = function() {
$scope.loginBusy = true;
$scope.loginMessage = "";
$scope.greeting = "";
$scope.disassociateUserData();
$scope.userData = {};
angularFireAuth.logout();
};
$scope.emailText = "Email"
$scope.passwordText = "Password"
$scope.confirmPasswordText = "Confirm Password"
$scope.register = function() {
$scope.loginMessage = "";
if ((angular.isDefined($scope.email) && $scope.email != "") && (angular.isDefined($scope.password0) && $scope.password0 != "" && $scope.password0 == $scope.password1)) {
$scope.loginBusy = true;
angularFireAuth.createUser($scope.email, $scope.password0, function(err, user) {
if (user) {
console.log('New User Registered');
}
$scope.loginBusy = false;
});
} else {
$scope.password0 =""
$scope.password1 =""
$scope.passwordText = "Password Not Matching"
$scope.confirmPasswordText = "Password Not Matching"
}
};
$scope.$on('angularFireAuth:login', function(evt, user) {
$scope.loginBusy = false;
$scope.user = user;
console.log("User is Logged In");
angularFire(ref.child('users/' + $scope.user.id), $scope, 'userData').then(function(disassociate) {
$scope.userData.name = $scope.userData.name || {};
if (!$scope.userData.name.first) {
$scope.greeting = "Hello!";
} else {
$scope.greeting = "Hello, " + $scope.userData.name.first + "!";
}
$scope.disassociateUserData = function() {
disassociate();
};
});
});
$scope.$on('angularFireAuth:logout', function(evt) {
$scope.loginBusy = false;
$scope.user = {};
console.log('User is Logged Out');
});
$scope.$on('angularFireAuth:error', function(evt, err) {
$scope.greeting = "";
$scope.loginBusy = false;
$scope.loginMessage = "";
console.log('Error: ' + err.code);
switch(err.code) {
case 'EMAIL_TAKEN':
$scope.loginMessage = "That email address is already registered!";
break;
case 'INVALID_PASSWORD':
$scope.loginMessage = "Invalid username + password";
}
});
})
Output:
Error: [$injector:unpr] Unknown provider: angularFireProvider <- angularFire
http://errors.angularjs.org/1.3.0-rc.3/$injector/unpr?p0=angularFireProvider%20%3C-%20angularFire
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:80:12
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:3938:19
at Object.getService [as get] (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:4071:39)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:3943:45
at getService (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:4071:39)
at invoke (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:4103:13)
at Object.instantiate (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:4123:23)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:7771:28
at link (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular-route.js:938:26)
at invokeLinkFn (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:7549:9) <div ng-view="" class="ng-scope">
(anonymous function) angular.js:10683
(anonymous function) angular.js:7858
invokeLinkFn angular.js:7551
nodeLinkFn angular.js:7069
compositeLinkFn angular.js:6441
publicLinkFn angular.js:6320
boundTranscludeFn angular.js:6461
controllersBoundTransclude angular.js:7096
update angular-route.js:896
Scope.$broadcast angular.js:13751
(anonymous function) angular-route.js:579
processQueue angular.js:12234
(anonymous function) angular.js:12250
Scope.$eval angular.js:13436
Scope.$digest angular.js:13248
Scope.$apply angular.js:13540
done angular.js:8884
completeRequest angular.js:9099
xhr.onreadystatechange angular.js:9038
I cant figure out what the problem is. However i think there is something wrong with: but i can't tell. If more information is needed i'm happy to post it.
I initially was taking the same if-then-else approach as you do for handling privileged actions. But it turns out this is not the best approach when using Angular. Instead of having this if-then-else approach, try to reframe the problem to a solution that isolates the privileged code.
show a certain button if the user is logged in
So your original question was about showing an HTML element only when the user if logged in, which is easy with something like this in your controller:
$scope.auth = $firebaseSimpleLogin(new Firebase(FBURL));
This line binds the Firebase login status to the current scope, which makes it available to the view. No if-then-else is needed, since there is always a login status. AngularFire ensure that the view gets notified when that status changes, so all we have to do is ensure that we have the HTML markup to handle both presence and absence of authenticated users:
<div ng-controller="TrenchesCtrl" class='auth'>
<div ng-show="auth.user">
<p>You are logged in as <i class='fa fa-{{auth.user.provider}}'></i> {{auth.user.displayName}}</p>
<button ng-click="auth.$logout()">Logout</button>
</div>
<div ng-hide="auth.user">
<p>Welcome, please log in.</p>
<button ng-click="auth.$login('twitter')">Login with <i class='fa fa-twitter'> Twitter</i></button>
<button ng-click="auth.$login('github')">Login with <i class='fa fa-github'> GitHub</i></button>
</div>
</div>
See how it almost reads like an if-then-else? But then one without me writing code that tries to detect if the user is logged in. It is all declaratively handled by AngularJS and AngularFire.
perform actions only when a user is logged in
When you actually need to perform a privileged action, I've found it easiest to isolate the code like this:
function updateCard(id, update) {
var auth = $firebaseSimpleLogin(new Firebase(FBURL));
auth.$getCurrentUser().then(function(user) {
update.owned_by = user.username;
var sync = $firebase(ref.child('cards').child(id));
sync.$update(update);
});
};
Note that these are (simplified) fragments from my Trenches app (demo), which I wrote to learn more about Angular and AngularFire.
I have this function in a angular controller:
$scope.sendCompanyData = function() {
delete $scope.company["step1Form"];
delete $scope.company["step2Form"];
delete $scope.standard_address["state"];
$http.post(Routing.generate('create-company'), {
'company': $scope.company,
'standard_address': $scope.standard_address,
'phone': $scope.phone,
'courrier_address': $scope.courrier_address,
'logoFileName': $scope.logoFileName,
'mercantilDocFileName': $scope.mercantilFileName,
'rifDocFileName': $scope.rifFileName,
'standardAddressState': $scope.state.standard_address,
'standardAddressCity': $scope.city.standard_address,
'courrierState': $scope.courrierState.courrier_address,
'courrierCity': $scope.courrierCity.courrier_address
}).success(function(data) {
if (!data.success) {
if (!data.exception) {
$scope.errors = data.errors;
} else {
$scope.errors = data.exception;
}
} else {
$templateCache.removeAll();
ClientUser.loginToCompany(data.companyId);
if ($scope.mercantilFileName != "" && $scope.rifFileName != "") {
$noty.success(Translator.trans('company.register_success'));
} else {
$noty.success(Translator.trans('company.register_document_missing'));
}
$location.path('/empresa/' + data.companyAlias);
}
}).error(function(data, status) {
$scope.error = status;
});
$scope = angular.element($(".seller-layout.new")).scope();
$scope.section = 'segundo-paso';
}
The problem related to this code is on this line $scope.mercantilFileName != "" && $scope.rifFileName != "" since this is not checked or never happen even if I don't send any value on that. I'm getting crazy with this and perhaps it's easy but the code always goes trough else sentence. Any help on this?
Why not simply:
if ($scope.mercantilFileName && $scope.rifFileName) {...}
I think that $scope.mercantilFileNam is rather 'undefined' than an empty string("").
I have two views right now.
login
main
Right now I login and change my path to /main which works fine. When I am not logged in, and try to visit /main my web service returns "Access denied for user anonymous" which I then forward them to / which is my login view. How can I pass something so my LoginController knows they were forwarded from /main to alert them to login first?
LoginController.js
VforumJS.controller('LoginController', function($scope, $location, $routeParams, LoginModel)
{
$scope.email = "";
$scope.password = "";
$scope.fetching = false;
$scope.error = null;
$scope.login = function()
{
$scope.error = null;
$scope.fetching = true;
LoginModel.login($scope.email, $scope.password);
}
$scope.$on('LoginComplete', function(event, args)
{
log('login complete: ' + args.result);
$scope.fetching = false;
if (args.result == "success")
{
$location.path('/main');
}
else
{
$scope.error = args.result;
}
});
});
MainController.js
VforumJS.controller('MainController', function($scope, $location, $routeParams, MainModel)
{
$scope.currentTitle = '-1';
$scope.presentationData = MainModel.getPresentations();
$scope.$on('PresentationsLoaded', function(event, args)
{
log(args.result);
if (args.result != "Access denied for user anonymous")
{
//-- Parse preso data
$scope.presentationData = args.result;
}
else
{
//-- Need to login first, route them back to login screen
$location.path("/");
}
});
});
You can use $location.search() in your MainController to pass query string to the LoginController.
Inside you MainController:
if (args.result != "Access denied for user anonymous")
{
//-- Parse preso data
$scope.presentationData = args.result;
}
else
{
//-- Need to login first, route them back to login screen
$location.search({ redirectFrom: $location.path() });
$location.path("/");
}
And then in your LoginController, shortened for brevity:
VforumJS.controller('LoginController', function($scope, $location, $routeParams, LoginModel)
{
var queryString = $location.search();
$scope.$on('LoginComplete', function(event, args)
{
log('login complete: ' + args.result);
$scope.fetching = false;
if (args.result == "success")
{
if (queryString && queryString.redirectFrom) {
$location.path(queryString.redirectFrom);
} else {
$location.path('/somedefaultlocation');
}
}
else
{
$scope.error = args.result;
}
});
});
Alternatively you can use a shared service, maybe even your LoginModel to set a parameter from MainController to indicate the redirect came from it.
Update
Even better still, use $httpProvider.interceptors to register a response interceptor, and then use the same $location.search() technique described above to redirect to the login screen on authentication failure. This method is ideal as your controllers are then clean of authentication logic.
$location broadcasts $locationChangeStart and $locationChangeSuccess events, and the third param of each is oldUrl.
One solution would be to have a service that subscribes to $locationChangeStart in order to save the current and old urls.
When you hit /, your LoginController can check your service to see if the oldUrl is /main, and then act accordingly.