-
Notifications
You must be signed in to change notification settings - Fork 1
Authentication
In this project JWT (Json Web Tokens) are used to authenticate and authorize users. These tokens are getting stored in the localstorage of the browser. A JWT looks as follows:
_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c_
As you can see it has a certain format and you can also store different kinds of information in it. These tokens include a signature. With this signature (and other data) you can check if a token is valid and got issued from the Authentication server. That means we can check the authenticity and the authority with these tokens. Up to now a symmetric authentication is used (for further information about JWTs check out https://jwt.io/introduction/). So every time a user requests something where he has to be logged in, or personal data, the system will send a request with the token of the user to the Authentication server, where the token is getting validated. Depending on the response of the Authentication server the user is allowed or not allowed to access the requested data.
This could be improved with a asymmetric authentication system, which means that an asynchronous encryption algorithm must be used for the signature. If this is the case we could build a public key infrastructure and the other services could validate token by their self with the public key, which is offered by the Authentication server. With this solution the other services wouldn't have to ask the authentication server every time to validate the token if they get a request which requires authentication or authorization.
In this case the system has different parts which require authentication or you have to be logged in to see certain parts. The different parts are:
- REST-API of the Resource server
- Certain routes of the SPA
For the Authentication in the Microservices the JTW (https://github.com/auth0/java-jwt) library from auth0 is used. To protect certain routes of the Resource server, you first have to configure the web security of the spring application via an object (WebSecurityConfig.java) In the config you can tell the application which routes should be protected. Now you have protected routes and can add filters to these. If you want to add a filter to your web security filter chain, you have to add it in the configuration, which looks like this:
...
// Custom JWT based security filter
JwtAuthorizationFilter authenticationFilter = new JwtAuthorizationFilter(tokenHeader, tokenValidationUrl);
httpSecurity.addFilterAfter(authenticationFilter, UsernamePasswordAuthenticationFilter.class);
...The **JwtAuthorizationFilter ** is a class which extends a class and overrides methods. Basically the filter sends a REST-Request to the Authentication server.
...
HttpEntity<TokenRequest> tokenRequest = new HttpEntity<>(new TokenRequest(authToken));
boolean tokenIsValid =
this.restTemplate.postForObject(this.tokenValidationUrl, tokenRequest, Boolean.class);
if (!tokenIsValid) {
throw new IOException("Token was invalid!");
}
...Then the server is checking if the token is valid, with the following function:
public static DecodedJWT verify(String token) throws IllegalArgumentException, UnsupportedEncodingException {
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm).build(); // Reusable verifier instance
return verifier.verify(token);
}After the token got validated the authentication will respond with the result and if the token was valid the user will receive the requested data.
The goal in the SPA is to protect certain areas, so e.g. a users which is not logged in can’t access other profiles if he's not logged in. to ensure this the application has the following function in the Vue Router.
function checkAuthentication (to: Route, from: Route, next: any) {
Store.getters.isTokenValid.then((result: boolean) => {
if(!result) {
Router.push('/');
}
next();
}).catch((err: any) => {
Router.push('/error');
next();
});
}This function is bound to the beforeEnter variable of each route which needs to be protected. The function itself does pretty much the same thing like the Resource server. It sends a request with the user token to the Authentication server. The token is getting validated and the front end receives a response. Depending on that response the Router is pushing the next Router-View or redirects the user to the login page.