Note: I added apache and spring tags because a user commented below that he thinks this is an apache and spring issue.
I am learning AngularJS by reading tutorials and experimenting with sample apps. The code below allows a person to type in mydomain.com
and then click around public links without being authenticated. However, whenever, I type in mydomain.com/public1
directly in the browser, the browser responds with a popup window requesting username and password which are interpreted on the server. The AngularJS app is making the decision to force authentication calls to the server instead of just letting unauthenticated users view public routes. This is obviously not acceptable behavior. What can I do to fix the code below so that mydomain.com/public1 (or any public url) can be accessed directly by typing the url in the browser?
Here is the route provider in hello.js
:
angular
.module('hello', [ 'ngRoute', 'auth', 'home', 'message', 'public1', 'navigation' ])
.config(
function($routeProvider, $httpProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$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('/public2', {
templateUrl : 'js/public1/public2.html',
controller : 'public1'
}).when('/public3', {
templateUrl : 'js/public1/public3.html',
controller : 'public1'
}).when('/public4', {
templateUrl : 'js/public1/public4.html',
controller : 'public1'
}).when('/login', {
templateUrl : 'js/navigation/login.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('/login', '/logout');
});
Here is the auth.js
module that is injected into the route provider shown above:
angular.module('auth', []).factory(
'auth',
function($rootScope, $http, $location) {
var auth = {
authenticated : false,
authenticatedPin : false,
loginPath : '/login',
logoutPath : '/logout',
homePath : '/checkpin',
path : $location.path(),
authenticate : 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.authenticated = true; }
else { auth.authenticated = false; }
callback && callback(auth.authenticated);
$location.path('/message');
}).error(function() {
auth.authenticated = false;
callback && callback(false);
});
},
clear : function() {
$location.path(auth.loginPath);
auth.authenticated = 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;
auth.authenticate({}, function(authenticated) {
if (authenticated) {
$location.path(auth.path);
}
})
}
};
return auth;
});
Here is navigation.js
, which calls the auth module:
angular.module('navigation', ['ngRoute', 'auth']).controller(
'navigation',
function($scope, $route, auth) {
$scope.credentials = {};
$scope.tab = function(route) {
return $route.current && route === $route.current.controller;
};
$scope.authenticated = function() {
return auth.authenticated;
}
$scope.login = function() {
auth.authenticate($scope.credentials, function(authenticated) {
if (authenticated) {
console.log("Login succeeded")
$scope.error = false;
} else {
console.log("Login failed")
$scope.error = true;
}
})
}
$scope.logout = auth.clear;
});
index.html is:
<!doctype html>
<html>
<head>
<title>Hello Angular</title>
<base href="/" />
<link href="css/angular-bootstrap.css" rel="stylesheet">
<style type="text/css">
[ng\:cloak], [ng-cloak], .ng-cloak {
display: none !important;
}ownChair31#
</style>
</head>
<body ng-app="hello" ng-cloak class="ng-cloak">
<div ng-controller="navigation" class="container">
<ul class="nav nav-pills" role="tablist">
<li ng-class="{active:tab('home')}"><a href="/">home</a></li>
<li ng-class="{active:tab('message')}"><a href="/message">message</a></li>
<li ng-class="{active:tab('public1')}"><a href="/public1">public1</a></li>
<li ng-class="{active:tab('public2')}"><a href="/public2">public2</a></li>
<li ng-class="{active:tab('public3')}"><a href="/public3">public3</a></li>
<li ng-class="{active:tab('public4')}"><a href="/public4">public4</a></li>
<li><a href="/login">login</a></li>
<li ng-show="authenticated()"><a href="" ng-click="logout()">logout</a></li>
</ul>
</div>
<div ng-view class="container"></div>
<script src="js/angular-bootstrap.js" type="text/javascript"></script>
<script src="js/auth/auth.js" type="text/javascript"></script>
<script src="js/home/home.js" type="text/javascript"></script>
<script src="js/message/message.js" type="text/javascript"></script>
<script src="js/public1/public1.js" type="text/javascript"></script>
<script src="js/navigation/navigation.js" type="text/javascript"></script>
<script src="js/hello.js" type="text/javascript"></script>
</body>
</html>
Also, the app is run on Apache http, which calls a spring boot app that has its own internal instance of tomcat. The VirtualHost code for apache is:
<VirtualHost www.mydomain.com:80>
ServerName www.mydomain.com
ServerAlias mydomain.com
ProxyRequests Off
ProxyPass / http://localhost:9000/
ProxyPassReverse / http://localhost:9000/
</VirtualHost>
If you are interested where this sample app came from, the following link has complete code for the starting point: https://spring.io/guides/tutorials/spring-security-and-angular-js/
Note that changes have been made to code from the link.