and
in
Client
Server
1. Client sends user/password
Client
Server
1. Client sends user/password
2. Server validates user/pass and upon success creates a cookie
Client
Server
1. Client sends user/password
2. Server validates user/pass and upon success creates a signed cookie
3. Server sends cookie
Client
Server
1. Client sends user/password
2. Server validates user/pass and upon success creates a signed cookie
3. Server sends cookie
4.
All further communication
involves the signed cookie
Client
Server
1. Client sends user/password
2. Server validates user/pass and upon success creates a signed cookie
3. Server sends cookie
4.
All further requests
send the signed cookie
5.
All further requests check the cookie
Client
Server
1. Client sends user/password
2. Server validates user/pass and upon success creates a JWT (which are signed)
3. Server sends JWT
4.
All further requests
send the JWT
5.
All further requests check the JWT
Crucially: a client needs to be able to hold information that uniquely identifies it, but that could not be recreated by a 3rd party attacker.
JWT was invented specifically to deal with cases where cookies do not work well.
Single Page App + Service Oriented Architecture is an example of such a case.
Interceptors are the middleware of angular.
Angular Client:
Initial HTTP
Request
Interceptor
Server
Interceptors are the middleware of angular.
Angular Client:
Initial HTTP
Request
Interceptor
Server
app.config(function($routeProvider, $httpProvider){
$httpProvider.interceptors.push('testInterceptor');
})
Step 1: register your interceptor with $httpProvider
This is a service that we are about to create
.service('testInterceptor', function testInterceptor(){
return {
request: function(config){
return config;
},
requestError: function(err){
return err;
},
response: function(response){
return response;
},
responseError: function(err){
return err;
}
};
})
Step 2: Create the "interceptor service"
myApp.service('testInterceptor', function testInterceptor(){
return {
// An interceptor that is called when making
// a request. The config object is the same
// type of object used when calling $http(config)
request: function(config){
return config;
}
};
})
Step 2.5: Types
Request interceptor
myApp.service('testInterceptor', function testInterceptor(){
return {
// An interceptor that runs when $http
// or another interceptor encounters an
// error. The input is that error.
requestError: function(err){
return err;
}
};
})
Step 2.5: What are these?
Request Error interceptor
myApp.service('testInterceptor', function testInterceptor(){
return {
// An interceptor that runs when a
// response is received. The parameter
// here is the data from that response.
response: function(response){
return response;
}
};
})
Step 2.5: What are these?
Response Interceptor
myApp.service('testInterceptor', function testInterceptor(){
return {
// An interceptor that runs when
// an error occurs during another
// interceptor. *NOT* if the response
// object itself is erroneous (404/500)
responseError: function(err){
return err;
}
};
})
Step 2.5: What are these?
Response Error Interceptor
// Somewhere in the login code:
var loginPromise = $http({
method: "POST",
url: "/login",
data: {user: "teb", password: "123456"}
});
loginPromise.then(function(response) {
// Assuming this is how your server responds
if(response.data.jwt) {
localStorage.set('token', response.data.jwt);
}
});
Step 3: If you login successfully -- store JWT
myApp.service('testInterceptor', function testInterceptor(){
return {
request: function(config){
var token = localStorage.getItem("token");
if(token) {
config.headers.Authorization = "Bearer " + token;
}
return config;
}
};
})
Step 4: Use an Interceptor for JWT tokens
Ask local storage if there is a JWT -- if there is then always throw it in the authorization header
Get a whiteboard, and draw the steps for JWT authorization. Explain it to your neighbor!