I'm writing a website which uses ngRoute for changing pages.
for logging in a form will appear and when it's successful controller changes the http header for requests in the next steps.
bud the problem is that when I change the header, page should be reloaded if not, the Token would not be added to header.
Controller :
app.controller('catCtrl',['Api','$scope','$cookieStore','$rootScope',function (Api,$scope,$cookieStore,$rootScope) {
$scope.Login = function(){
Api.loginEmail($scope.log_email, $scope.pass, 'chrome', 'windows','').success(function(response){
$cookieStore.put('Auth-Key', 'Token ' + response.token);
$scope.is_Loggedin = true;
$scope.showLoginWin();
}).error(function(response){
$scope.log_email = null;
$scope.pass = null;
$scope.error = response.error;
});
};
}
App.run :
app.run(['$cookieStore','$http',function($cookieStore, $http){
$http.defaults.headers.common['Authorization'] = $cookieStore.get('Auth-Key');
}]);
How can I change the header without reloading page.
so you want to add your token on further request after login.
You can try angular interceptor. Here is few Answers related how to add toke via interceptor.
Interceptor Example 1
Interceptor example 2
sample Code:
app.factory('httpRequestInterceptor', function () {
return {
request: function (config) {
config.headers['Authorization'] = $cookieStore.get('Auth-Key');
return config;
}
};
});
In your service layer, Ignore verification this header for Login.
Related
I don't want to pass the Bearer token in every http request, so to automate it I did the following:
angular.module('projectApp').run(function ($http, $rootScope, $location) {
$http.defaults.headers.common.Authorization = 'Bearer ' + localStorage.getItem('token');
}
But when there is a page that don't need authentication, the header will be passed too. There is a way to optionally don't pass this header(but pass it as default)?
You can set that header to undefined for a particular request like this:
$http.get('/someUrl', {headers: { 'Authorization ': undefined }}).then(successCallback, errorCallback);
You can use interceptors to select in what requests add the Authorization header, like this:
Config :
app.config([ '$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('APIInterceptor');
} ]);
Service :
app.service('APIInterceptor', [function() {
var service = this;
service.request = function(config) {
config.headers.YOUR_HEADER= YOUR_HEADERS_VALUE;
return config;
};
}]);
What I am looking to do I when a user comes to the index.html page I need the login module to do 2 things:
I need this to check if a user is authenticated ( which I think I already started with the "function authService" ) if the user has a valid token then change the ui-view to dashboard/dashboard.html and if the key is not valid or there is no key at all then load login/login.html into ui-view.
Once they have successfully logged in I want them to be routed to "dashboard/dashboard.html"
Here is my login script:
function authInterceptor(API) {
return {
request: function(config) {
if(config.url.indexOf(API) === 0) {
request.headers = request.headers || {};
request.headers['X-PCC-API-TOKEN'] = localStorage.getItem('token');
}
return config;
}
}
}
function authService(auth) {
var self = this;
self.isAuthed = function() {
localStorage.getItem('token');
}
}
function userService($http, API) {
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;';
$http.defaults.transformRequest = [function(data) {
return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
}];
var self = this;
self.login = function(username, pwd, ctrl) {
ctrl.requestdata = API + '/winauth' + '; with ' + username;
return $http.post(API + '/winauth', {
username: username,
pwd: pwd
})
};
var param = function(obj) {
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
for(name in obj) {
value = obj[name];
if(value instanceof Array) {
for(i=0; i<value.length; ++i) {
subValue = value[i];
fullSubName = name + '[' + i + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if(value instanceof Object) {
for(subName in value) {
subValue = value[subName];
fullSubName = name + '[' + subName + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if(value !== undefined && value !== null)
query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
}
return query.length ? query.substr(0, query.length - 1) : query;
};
}
function LoginCtrl(user) {
var self = this;
function handleRequest(res) {
self.responsedata = res;
self.message = res.data.message;
var authToken = res.data.auth_token;
localStorage.setItem('token', authToken);
}
self.login = function() {
this.requestdata = 'Starting request...';
user.login(self.username, self.pwd, self)
.then(handleRequest, handleRequest)
}
}
// Login Module
var login = angular.module('login', ["ui.router"])
login.factory('authInterceptor', authInterceptor)
login.service('user', userService)
login.service('auth', authService)
login.constant('API', 'http://myserver.com/api')
EDIT - I added this into my login controller to provide the login routes
login.config(function($httpProvider, $stateProvider, $urlRouterProvider) {
$httpProvider.interceptors.push('authInterceptor');
$urlRouterProvider.otherwise('/login');
$stateProvider
// HOME STATES AND NESTED VIEWS ========================================
.state('login', {
url: '/login',
templateUrl: 'login/login.html',
controller: "mainLogin",
controllerAs: "log"
})
// nested list with just some random string data
.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard/dashboard.html',
})
})
login.controller('mainLogin', LoginCtrl)
Here is my index.html:
EDIT - I removed "ng-include" and added "ng-view" to control the routes.
<body ng-app="login" ng-controller="mainLogin as log" class="loginPage">
<div class="main" ui-view></div>
</body>
As you can see I have a function that is checking for the token in the users local storage:
function authService(auth) {
var self = this;
self.isAuthed = function() {
localStorage.getItem('token');
}
}
And I am loading it in the module as a service:
login.service('auth', authService)
This is where I am stuck. I don't know where to go from here. I don't even know if I am using my authService function properly. I am still learning a lot about AngularJS so its easy for me to get stuck. :)
Another thing you will notice is in my index.html file I am just loading the "login/login.html" partial as default. I need it to load either login.html or dashboard.html depending if they are logged in or not. And then also route them to dashboard.html once they have successfully logged in.
The script works great as far as hitting the auth API, authenticating the user and then storing a valid auth key on their local storage.
Anyone know how I can accomplish this?
There are two separate concerns that you are dealing with. The first, is to be able to determine if you are logged in. Assuming the user needs to be logged in for any state except the login state, you would implement it like so by listening for $stateChangeState events and verifying that the user is logged in:
login.run(function($state, authService) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
var authToken = authService.isAuthed();
if (!authToken && toState !== 'login') {
//not logged in, so redirect to the login view instead of the view
//the user was attempting to load
event.preventDefault();
$state.go('login');
}
})
});
This will put them on the login state if they haven't already logged in.
The second part is to redirect to the correct view after they login, which you would do in your login controller:
function LoginCtrl(user, $state) {
var self = this;
function handleRequest(res) {
self.responsedata = res;
self.message = res.data.message;
var authToken = res.data.auth_token;
localStorage.setItem('token', authToken);
//after successful login, redirect to dashboard
$state.go('dashboard');
}
self.login = function() {
this.requestdata = 'Starting request...';
user.login(self.username, self.pwd, self)
.then(handleRequest, handleRequest)
}
}
ok I see you are using ui.router so let's work within this framework.
You want to
check if a user is logged in
redirect user to a view
What you're looking for is resolve:{loggedIn: checkLoggedInFn}
so your route for dashboard could be something like
.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard/dashboard.html',
resolve: {
loggedIn: function(){
//do your checking here
}
}
})
what this does basically is that the controller will not instantiate until every resolve is resolved (so you can use a promise here for example), and then the value is passed into the controller as a parameter, so you could then do something like:
if(!loggedIn){
$state.go('login');
}
You would handle the logic inside your login controller specifically here:
self.login = function() {
this.requestdata = 'Starting request...';
user.login(self.username, self.pwd, self)
.then(handleRequest, handleRequest)
}
Inside the callback for the success on login, you would simple do a state change to send the user to the correct state.
In authInterceptor add code for response. So:
return {
request: function(config) {
if(config.url.indexOf(API) === 0) {
request.headers = request.headers || {};
request.headers['X-PCC-API-TOKEN'] = localStorage.getItem('token');
}
return config;
},
response: function(response) {
//ok response - code 200
return response;
},
responseError: function(response){
//wrong response - different response code
}
};
On server side check http header X-PCC-API-TOKEN and if is wrong ( no authentication) response should have different code like 403. So responseError method will run in interceptor.
responseError: function(response){
//wrong response - different response code
if (response.status === 403) {
alert("No rights to page");//your code for no auth
//redirect to different route
$injector.get('$state').transitionTo('login');//use injector service
return $q.reject(response);//return rejection - use $q
}
}
Your service is fine and it's on the loginModule but you are not using it anywhere where i can see. You need to inject your service into controller to do stuff you want. In your authService you are getting item from localstorage but you are not returning anything for example you have your login service
function authService(auth) {
var self = this;
self.isAuthed = function() {
return localStorage.getItem('token');
}
}
//here you can inject your auth service to get it work as you want
function LoginCtrl(user, auth) {
var self = this;
function handleRequest(res) {
self.responsedata = res;
self.message = res.data.message;
var authToken = res.data.auth_token;
localStorage.setItem('token', authToken);
}
self.login = function() {
this.requestdata = 'Starting request...';
user.login(self.username, self.pwd, self)
.then(handleRequest, handleRequest)
}
}
login.service('auth', authService)
function authService(auth) {
var self = this;
self.isAuthed = function() {
**localStorage.getItem('token');**
}
}
Where are you getting the localstorage item into? The LValue is missing.
At the most basic level, you could handle a check for this item - token - in the Dashboard page, at the time of loading the page and if it is null ie. empty, then redirect/route the user to the login page. Btw, use the sessionStorage rather than the localStorage as the former will flush as soon as the browser session is closed.
There are more elegant and simpler ways of accomplishing it like Passport. Have you checked it? It is as simple as this:
app.post('/login', passport.authenticate('local', { successRedirect: '/',
failureRedirect:'/login'}));
Your code isn't checking on url changes or affecting routes in a cross-cutting way.
Remember that authentication and authorization are cross-cutting concerns. That being said, Angular has a way for you to intercept routing calls by listening on $routeChangeStart. Your "interceptor" should be added there. You can then redirect the router to the required view by manually routing there. Have a look as the solution from a previous stack overflow thread.
There is a simple way you can achieve what you want for your application, using PassportJs.
The documentation is pretty simple and easy to implement.
You can also refer this tutorial to implement authentication using Passport. This tutorial teaches in very simple way, how to do authentication for your application.
Simple way to do that is just use https://github.com/Emallates/ng-enoa-auth package. You just need to include it in your app, nothing else.
In my angular application I store the logged in user name in a cookie.
And I want to display this user name in the web page header.
I can retrieve this in my controller as below and display in the page.
$rootScope.fullName = $cookies.get('user');
But instead of doing this in every controller, is it possible to do it in one place and always get this data ?
Update #1:
I don't use ui-view. I use angular route and a sample is as below.
Are there any simple approach please ?
var mdmApp = angular.module('mdmApp');
// Routes
mdmApp.config(function($routeProvider, $httpProvider, $locationProvider) {
$routeProvider
.when('/listScopeAndFrequency/:reportTypeId', {
templateUrl : '3_calendar/listScopeAndFrequencies.html',
controller : "listScopeAndFrequenciesController"
})
.when('/listTemplateFrequencyExceptions/:reportTypeId/:consolidationScopeCode/:frequencyCode', {
templateUrl : '3_calendar/listTemplateFrequencyExceptions.html',
controller : "listTemplateFrequencyExceptionsController"
})
.when('/viewSubmissionDates', {
templateUrl : '3_calendar/viewSubmissionDates.html',
controller : "viewSubmissionDatesController"
})
Update #2
I tried like below but could not get any dynamic values from REST API, I am only able to hard code the value. Not able to read from cookie, localStorage or var all are undefined or give errors.
mdmApp.factory('userService', function($http, $localStorage, $cookies) {
var fullName ;
// Gets user details
$http.get("/mdm/getUser")
.success(function(data, status, headers, config) {
console.log('userService > user : ' +data.fullName);
fullName = data.fullName;
$localStorage.user = data;
$cookies.put('user', data.fullName);
})
.error(function(data, status, headers, config, statusText) {
console.log("Error while retrieving user details.");
});
console.log('fullName : ' +fullName);
console.log('$cookies.get(user) : ' +$cookies.get('user'));
console.log('$localStorage.user : ' +$localStorage.user);
return { name: "hard code only works here"};
});
mdmApp.directive('userTitle', ['userService', function(user) {
console.log('userTitle > user : ' +user);
return {
template: user.name,
};
}]);
Why don't you use a service? Those are specially designed for this task:
Angular services are:
Lazily instantiated – Angular only instantiates a service when an application component depends on it.
Singletons – Each component dependent on a service gets a reference to the single instance generated by the service factory.
How I do it (not necessarily the best way):
setup an independent angular app (non-secured area) for user registration, on login store a token or some identifier in a cookie or the localStorage
when instantiating the full angular app (secured area), create a service which will get back the previous value and inject it whenever you need the user
My User service looks like:
angular.module('app.core')
.service('User', User);
function User($rootScope, localStorageService) {
let user = localStorageService.get('user');
let token = localStorageService.get('userToken');
if(!token) {
//this loads another angular app which has nothing to do with this secured area (on /login)
window.location = '/login'
return;
}
for(let i in user)
this[i] = user[i]
this.token = 'Bearer ' + token;
//note you could reference this to the rootScope so that every scope can have the User object, this can be considered as bad practice!
//$rootScope.user = this;
return this;
}
I would go with a service and a directory for this.
As soyuka explained. Services exists for the purpose of sharing data between parts of an application. I would then use a directive to handle the data in relation to the DOM, that is, to write to the header.
Service/factory:
app.factory('userService', function() {
// do what you have to get your user and save the data.
return { name: 'John'};
});
Directive. Notice the injection of the service. This could be done through a controller if you wish. It depends on whether you want your directives to have a dependency to the service.
app.directive('userTitle', ['userService', function(user) {
// do what you want with the data
return {
template: user.name,
};
}]);
Here the service just returns a dummy name and the directive outputs the name in the DOM.
Here is a running plunker of the setup.
An AngularJS service is injected into two separate modules. This is causing the service to re-initialize separately when the second module calls it. I have used the FireFox debugger to confirm that the module is being re-initialized. How can I avoid this problem?
Here is the specific case:
An AngularJS app uses an authentication service in a module called auth to manage authentication concerns. The auth service is imported into a message module which manages access to the secure /message route and auth is also imported into a navigation module which manages both login/registration and also the visible contents of the navigation links in the user's browser. A user is able to successfully login using the GUI tools linked to the navigation module, and is then successfully redirected to the secure /message route as an authenticated user because the auth.authenticated1 and auth.authenticated2 properties are set to true just before the redirect to /message occurs.
However, the FireFox debugger confirms that the problem is that, when the user refreshes the browser to reload the /message url pattern, the auth module is re-initialized, setting the values of auth.authenticated1 and auth.authenticated2 back to false, and thus giving the user a message that they are not logged in, even though they were logged in a moment before using valid credentials provided by the user. What specific changes need to be made to the code below so that the user is NOT logged out on page re-load?
I want the AngularJS code to check the pre-existing value for auth.authenticated2 when the /message route is loaded or reloaded. If auth.authenticated2=false, then the user gets a message saying they are logged out. But if auth.authenticated2=true, I want the user to be able to see the secure content at the /message route. I DO NOT want auth.authenticated2 to be automatically re-set to false upon reloading the route, the way it is now.
Here is the code in message.html which contains the GUI elements for the /message route:
<div ng-show="authenticated2()">
<h1>Secure Content</h1>
<div>
<p>Secure content served up from the server using REST apis for authenticated users.</p>
</div>
</div>
<div ng-show="!authenticated2()">
<h1>You are not logged in.</h1>
</div>
Here is the code in message.js which is the controller for the message module that manages the /message route:
angular.module('message', ['auth']).controller('message', function($scope, $http, $sce, auth) {
$scope.authenticated2 = function() {
return auth.authenticated2;
}
//Other code calling REST apis from the server omitted here to stay on topic
});
Here is the code for the navigation module, which also injects the auth service:
angular.module('navigation', ['ngRoute', 'auth']).controller('navigation', function($scope, $route, auth, $http, $routeParams, $location) {
$scope.credentials = {};//from old navigation module
$scope.leadresult = "blank";
$scope.processStep = "start";
$scope.uname = "blank";
$scope.wleadid = "initial blank value";
$scope.existing = "blank";
$scope.tab = function(route) {
return $route.current && route === $route.current.controller;
};
$scope.authenticated1 = function() {
return auth.authenticated1;
}
$scope.authenticated2 = function() {
return auth.authenticated2;
}
$scope.login = function() {
auth.authenticate1($scope.credentials, function(authenticated1) {
//a bunch of stuff that does level 1 authentication, which is not relevant here
})
}
$scope.logout = auth.clear;
//some other methods to manage registration forms in a user registration process, which are omitted here because they are off-topic
$scope.pinForm = function(isValid) {//this method finishes authentication of user at login
if (isValid) {
$scope.resultmessage.webleadid = $scope.wleadid;
$scope.resultmessage.name = $scope.uname;
$scope.resultmessage.existing = $scope.existing;
var funcJSON = $scope.resultmessage;
auth.authenticate2(funcJSON, function(authenticated2) {
if (authenticated2) {
$location.path('/message');
$scope.$apply();//this line successfully re-directs user to `/message` route LOGGED IN with valid credentials
}
});
}
};
$scope.$on('$viewContentLoaded', function() {
//method that makes an unrelated call to a REST service for ANONYMOUS users
});
});
Here is the code for the auth service in auth.js:
angular.module('auth', []).factory( 'auth', function($rootScope, $http, $location) {
var auth = {
authenticated1 : false,
authenticated2 : false,
usrname : '',
loginPath : '/login',
logoutPath : '/logout',
homePath : '/message',
path : $location.path(),
authenticate1 : function(credentials, callback) {
var headers = credentials && credentials.username ? {
authorization : "Basic " + btoa(credentials.username + ":" + credentials.password)
} : {};
$http.get('user', {
headers : headers
}).success(function(data) {
if (data.name) { auth.authenticated1 = true; }
else { auth.authenticated1 = false; }
callback && callback(auth.authenticated1);
}).error(function() {
auth.authenticated1 = false;
callback && callback(false);
});
},
authenticate2 : function(funcJSON, callback) {
$http.post('/check-pin', funcJSON).then(function(response) {
if(response.data.content=='pinsuccess'){
auth.authenticated2=true;
callback && callback(auth.authenticated2);
}else {
auth.authenticated2=false;
auth.authenticated2 = false;
callback && callback(false);
}
});
},
clear : function() {
$location.path(auth.loginPath);
auth.authenticated1 = false;
auth.authenticated2 = false;
$http.post(auth.logoutPath, {}).success(function() { console.log("Logout succeeded");
}).error(function(data) { console.log("Logout failed"); });
},
init : function(homePath, loginPath, logoutPath) {
auth.homePath = homePath;
auth.loginPath = loginPath;
auth.logoutPath = logoutPath;
}
};
return auth;
});
The routeProvider is managed by the main js file for the app, which is hello.js and is as follows:
angular.module('hello', [ 'ngRoute', 'auth', 'home', 'message', 'public1', 'navigation' ])
.config(
function($routeProvider, $httpProvider, $locationProvider) {
$locationProvider.html5Mode(true);/* This line is one of 3 places where we set natural urls to remote the default # */
$routeProvider.when('/', {
templateUrl : 'js/home/home.html',
controller : 'home'
}).when('/message', {
templateUrl : 'js/message/message.html',
controller : 'message'
}).when('/public1', {
templateUrl : 'js/public1/public1.html',
controller : 'public1'
}).when('/register', {
templateUrl : 'js/navigation/register.html',
controller : 'navigation'
}).otherwise('/');
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
}).run(function(auth) {
// Initialize auth module with the home page and login/logout path
// respectively
auth.init('/checkpin', '/login', '/logout');
});
Not a complete answer as in, exact code to change here. But enough to get something built nicely.
You shouldn't explicitly use only boolean values inside your auth service. As far as I can see, you're not using any data that you're receiving from the server after a successful authentication. So whenever you refresh, everything is lost. You don't have anything in your code to recover from a refresh.
Ideally, you should have something like a token or a cookie. The cookie will be saved and can be recovered after a refresh, so while starting the auth service, you can check for the existence of that cookie.
You could also save a token that can be used to access an API inside an indexedDB or something like that. Just as I said before, during boot time of the auth service, you'll have to check for the existence of that token.
If you need more information, check for Oauth2. Even though Oauth2 isn't an Authentication API but an authorization API, the password grant type is something you could use. To get an idea how to build a solid system. The other grant types are mostly only focused on the authorization side of OAuth.
Because OP ask for code here it is:
when creating_service:
if exists(cookie) or exists(token) and valid(cookie) or valid(token):
mark_service_as_logged_in()
If pseudo code is better than words.
My angular app (SPA) needs to redirect to another server if user is not authenticated. This is a separate machine which means there can be a delay when redirecting from the my angular app to this auth server.
What I am looking to achieve is as follows:
When the app is requested and being loaded , it either dont show the content or show a vanilla/simple page.
If the app finds that the user is not logged in or login expired then it will continue to show that vanilla page while redirecting the app to this auth server.
Would really appreciate inputs in this.
Thanks,
Edit: interceptor.js code looks as follows:
app.factory('authInterceptorService', ['$q', '$injector', '$location', 'localStorageService',
function ($q, $injector, $location, localStorageService) {
....
var request = function (config) {
config.headers = config.headers || {};
var fragments = getFragment();
if(fragments.access_token != undefined)
localStorageService.add("authorizationData", { token: fragments.access_token, token_type: fragments.token_type, state : fragments.state, });
var authData = localStorageService.get('authorizationData');
if(authData)
{
config.headers.Authorization = authData.token_type + ' ' + authData.token;
$location.path( "/dashboard" );
}
else
logout();
return config;
};
var responseError = function (rejection) {
if (rejection.status === 401) {
logout();
}
return $q.reject(rejection);
};
var logout = function()
{
localStorageService.remove('authorizationData');
var scope = 'my-scope';
var uri = addQueryString('http://www.authserver.com/OAuth/Authorize', {
'client_id': 'dsfdsafdsafdsfdsfdsafasdf',
'redirect_uri': 'www.returnuri.com',
'state': 'asdfasfsdf',
'scope': 'scope1',
'response_type': 'token'
});
window.location.replace(uri);
};
authInterceptorServiceFactory.request = request;
authInterceptorServiceFactory.responseError = responseError;
authInterceptorServiceFactory.logout = logout;
return authInterceptorServiceFactory;
}]);
});
which is similar to what is being suggested by Blackunknown. But the problem is that the landing page gets loaded fully and then its gets redirected to the auth server. I know that the issue is that they are separate servers so they can have different response time.
I use a couple of things to get this done in an mvc 5 application. Of which the most important component being the AuthorizeInterceptor. I use a class set up in my coffee/javascripts than you will be seeing in most examples but the main principles are the same. I'll spare you the coffee here is some javascript:
(function() {
"use strict";
var AuthorizeConfig, AuthorizeInterceptor;
AuthorizeInterceptor = (function() {
function AuthorizeInterceptor($q, $location) {
this.$q = $q;
this.$location = $location;
return {
response: function(response) {
return response || $q.when(response);
},
responseError: function(rejection) {
if (((rejection != null ? rejection.status : void 0) != null) && rejection.status === 401) {
$location.path("/Login");
}
return $q.reject(rejection);
}
};
}
return AuthorizeInterceptor;
})();
angular.module("myapp").factory("AuthorizeInterceptor", ["$q", "$location", AuthorizeInterceptor]);
AuthorizeConfig = (function() {
function AuthorizeConfig($httpProvider) {
$httpProvider.interceptors.push("AuthorizeInterceptor");
}
return AuthorizeConfig;
})();
angular.module("myapp").config(["$httpProvider", AuthorizeConfig]);
}).call(this);
When a request results in a 401 it will redirect this person to the login page of the application.
Since you provided absolutely no code, here's a pseudo-example:
$http.get('yourAuthServer').success(function(response){
// save session data and redirect the user to the regular page
$location.path('loggedInRoute');
}).error(function(err){
// handle the failed authentification here
$location.path('authFailed');
});
So, the idea is to have a landing page with no sensitive data. You'll make an auth request from the main controller and, based on the results, you'll redirect the user properly. Of course, you should have authentication checks in place on your logged in page and not rely only on that redirection. But that will get you started.