Reputation: 47088
I'm reading through the following tutorial. The AngularJS navigation controller fires when the page loads, and that includes executing an authenticate function that looks like this:
var authenticate = function(credentials, callback) {
var headers = credentials ? {
authorization: "Basic " +
btoa(credentials.username + ":" + credentials.password)
} : {};
$http.get('user', {
headers: headers
}).then(function(response) {
if (response.data.name) {
$rootScope.authenticated = true;
} else {
$rootScope.authenticated = false;
}
callback && callback();
}, function() {
$rootScope.authenticated = false;
callback && callback();
});
}
The function is called like this:
authenticate()
So no credentials or call back is passed, so the authentication obviously does not succeed on page load. IIUC the reason this is called like this is in the event of a browser refresh post login. So my question is how does this function succeed in setting $rootScope.authenticated
to true post login, since IIUC the basic authentication headers
value sent with the ajax request (The line $http.get('user', {headers : headers}
) will be {}
. Will Spring simply let the request through since the user is already authenticated and does this happen because the Authentication Basic
header is set post form authentication?
Upvotes: 0
Views: 530
Reputation:
The point here is that Spring Boot (in reality Spring Security) creates an HttpSession
on the backend side after successful authentication.
Actually, the backend is stateful because it retains session data (authenticated user) on the server side. A client (here browser) gets identified by the supplied session id.
The authentication flow looks like this from a protocol perspective.
Use case: Browser initiates an HTTP call to the backend: Backend answers with Unauthorized
because the client tries to access a protected resource without Authorization
header
$ curl -I -H "X-Requested-With:XMLHttpRequest" http://localhost:8080/user
HTTP/1.1 401
Set-Cookie: XSRF-TOKEN=b1137571-5e15-491c-8df5-9db5d34f29a8;path=/
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Transfer-Encoding: chunked
Use case: Preemptive basic authentication. Backend grants access to resource and notifies client about session id
$ curl -I -H "X-Requested-With:XMLHttpRequest" -H "Authorization:Basic dXNlcjpwYXNzd29yZA==" http://localhost:8080/user
HTTP/1.1 200
Set-Cookie: XSRF-TOKEN=ef72f0b8-4262-4ea2-8a46-5f7e19558079;path=/
Set-Cookie: JSESSIONID=52B61923DE639EE339A653845FBFC5F2;path=/;HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type : application/json;charset=UTF-8
Content-Length: 343
Due to the fact that the browser sends valid user credentials via the HTTP header Authorization
, the backend creates a new HttpSession
and sends back an identifier (the session id) to the browser
Set-Cookie: JSESSIONID=52B61923DE639EE339A653845FBFC5F2;path=/;HttpOnly
Now, the browser attaches to every subsequent HTTP call the Cookie
header automatically
Cookie: JSESSIONID=52B61923DE639EE339A653845FBFC5F2
which prevents a new authentication cycle. As long as the session does not timeout on the server side, the server "assigns" the session data to this particular HTTP request.
Basic authentication is not limited to Spring Boot (Spring Security) nor Angular. It is a standardized authentication scheme for the Internet since many years.
Bear in mind, basic authentication is an old-fashioned authentication scheme and highly discouraged in modern web applications.
Will Spring simply let the request through since the user is already authenticated and does this happen because the Authentication Basic header is set post form authentication?
Regarding the quoted example, you may now understand why an empty headers
object does not lead to a rejection.
Authorization
header with valid user credentials and initiates an HTTP request to a restricted resourceHttpSession
identified by a session id and sends it back to the browserWhat happens if you instruct Spring Security not to create sessions on the server? For that purpose append
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
to SecurityConfiguration::configure
.
Now, you can see that every call to /resource
in the example leads to an HTTP 401 because there is no session on the server anymore. The Angular application is now forced to set the Authorization
header on every HTTP request on its own.
The browser may attach Authorization
header automatically too. For the sake of brevity, I will skip that part. Please keep in mind, basic authentication is highly discouraged in modern web applications.
The intention of the example is not to show you how to implement a sign in with Spring Boot and Angular. The main intention is to evolve the primitive sign in towards a single sign on based on OAuth2 and Spring in a microservice architecture.
Don't take the code example for granted.
Upvotes: 1