<!DOCTYPE html>
<html ng-app="app">
<head>
<title>AngularJS JWT Authentication Example & Tutorial</title>
<!-- bootstrap css -->
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<!-- application css -->
<link href="app-content/app.css" rel="stylesheet" />
</head>
<body>
<!-- main app container -->
<div class="jumbotron">
<div class="container">
<div class="col-sm-8 col-sm-offset-2">
<ui-view></ui-view>
</div>
</div>
</div>
<!-- credits -->
<div class="text-center">
<p>
<a href="http://jasonwatmore.com/post/2016/04/05/AngularJS-JWT-Authentication-Example-Tutorial.aspx" target="_top">AngularJS JWT Authentication Example & Tutorial</a>
</p>
<p>
<a href="http://jasonwatmore.com" target="_top">JasonWatmore.com</a>
</p>
</div>
<!-- angular scripts -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-messages.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ngStorage/0.3.6/ngStorage.min.js"></script>
<!-- application scripts -->
<script src="app.js"></script>
<script src="app-services/authentication.service.js"></script>
<script src="home/index.controller.js"></script>
<script src="login/index.controller.js"></script>
<!-- scripts for fake backend -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-mocks.js"></script>
<script src="app-helpers/fake-backend.js"></script>
</body>
</html>
.help-block {
font-size: 12px;
}
(function () {
'use strict';
angular
.module('app')
.run(setupFakeBackend);
// setup fake backend for backend-less development
function setupFakeBackend($httpBackend) {
var testUser = { username: 'test', password: 'test', firstName: 'Test', lastName: 'User' };
// fake authenticate api end point
$httpBackend.whenPOST('/api/authenticate').respond(function (method, url, data) {
// get parameters from post request
var params = angular.fromJson(data);
// check user credentials and return fake jwt token if valid
if (params.username === testUser.username && params.password === testUser.password) {
return [200, { token: 'fake-jwt-token' }, {}];
} else {
return [200, {}, {}];
}
});
// pass through any urls not handled above so static files are served correctly
$httpBackend.whenGET(/^\w+.*/).passThrough();
}
})();
(function () {
'use strict';
angular
.module('app')
.factory('AuthenticationService', Service);
function Service($http, $localStorage) {
var service = {};
service.Login = Login;
service.Logout = Logout;
return service;
function Login(username, password, callback) {
$http.post('/api/authenticate', { username: username, password: password })
.success(function (response) {
// login successful if there's a token in the response
if (response.token) {
// store username and token in local storage to keep user logged in between page refreshes
$localStorage.currentUser = { username: username, token: response.token };
// add jwt token to auth header for all requests made by the $http service
$http.defaults.headers.common.Authorization = 'Bearer ' + response.token;
// execute callback with true to indicate successful login
callback(true);
} else {
// execute callback with false to indicate failed login
callback(false);
}
});
}
function Logout() {
// remove user from local storage and clear http auth header
delete $localStorage.currentUser;
$http.defaults.headers.common.Authorization = '';
}
}
})();
(function () {
'use strict';
angular
.module('app')
.controller('Home.IndexController', Controller);
function Controller() {
var vm = this;
initController();
function initController() {
}
}
})();
<div class="col-md-6 col-md-offset-3">
<h1>Home</h1>
<p>You're logged in with JWT!!</p>
<p><a href="#/login">Logout</a></p>
</div>
(function () {
'use strict';
angular
.module('app')
.controller('Login.IndexController', Controller);
function Controller($location, AuthenticationService) {
var vm = this;
vm.login = login;
initController();
function initController() {
// reset login status
AuthenticationService.Logout();
};
function login() {
vm.loading = true;
AuthenticationService.Login(vm.username, vm.password, function (result) {
if (result === true) {
$location.path('/');
} else {
vm.error = 'Username or password is incorrect';
vm.loading = false;
}
});
};
}
})();
<div class="col-md-6 col-md-offset-3">
<div class="alert alert-info">
Username: test<br />
Password: test
</div>
<h2>Login</h2>
<form name="form" ng-submit="form.$valid && vm.login()" novalidate>
<div class="form-group" ng-class="{ 'has-error': form.$submitted && form.username.$invalid }">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" ng-model="vm.username" required />
<div ng-messages="form.$submitted && form.username.$error" class="help-block">
<div ng-message="required">Username is required</div>
</div>
</div>
<div class="form-group" ng-class="{ 'has-error': form.$submitted && form.password.$invalid }">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" ng-model="vm.password" required />
<div ng-messages="form.$submitted && form.password.$error" class="help-block">
<div ng-message="required">Password is required</div>
</div>
</div>
<div class="form-group">
<button ng-disabled="vm.loading" class="btn btn-primary">Login</button>
<img ng-if="vm.loading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
</div>
<div ng-if="vm.error" class="alert alert-danger">{{vm.error}}</div>
</form>
</div>
(function () {
'use strict';
angular
.module('app', ['ui.router', 'ngMessages', 'ngStorage', 'ngMockE2E'])
.config(config)
.run(run);
function config($stateProvider, $urlRouterProvider) {
// default route
$urlRouterProvider.otherwise("/");
// app routes
$stateProvider
.state('home', {
url: '/',
templateUrl: 'home/index.view.html',
controller: 'Home.IndexController',
controllerAs: 'vm'
})
.state('login', {
url: '/login',
templateUrl: 'login/index.view.html',
controller: 'Login.IndexController',
controllerAs: 'vm'
});
}
function run($rootScope, $http, $location, $localStorage) {
// keep user logged in after page refresh
if ($localStorage.currentUser) {
$http.defaults.headers.common.Authorization = 'Bearer ' + $localStorage.currentUser.token;
}
// redirect to login page if not logged in and trying to access a restricted page
$rootScope.$on('$locationChangeStart', function (event, next, current) {
var publicPages = ['/login'];
var restrictedPage = publicPages.indexOf($location.path()) === -1;
if (restrictedPage && !$localStorage.currentUser) {
$location.path('/login');
}
});
}
})();