Skip to content

Commit

Permalink
Add stateless authentication (#49)
Browse files Browse the repository at this point in the history
add stateless token authentication. The user must be logged in by '/login' by sending a JSON form with user and pass, and in case the authentication is successful, a token is returned in the Header 'X-AUTH-TOKEN', otherwise an authenticated error is sent. Also, when trying to access a resource which is not '/login' or '/' and no token is provided, a 401 unauthorized error will be returned.

- implement login authentication filter
- implement authentication filter for logged users
- implement handler to return unauthorized message
- add codecov config
  • Loading branch information
gibarsin committed Jan 24, 2017
1 parent d36e200 commit 34c35a5
Show file tree
Hide file tree
Showing 12 changed files with 434 additions and 174 deletions.
28 changes: 28 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
codecov:
notify:
require_ci_to_pass: true
comment:
behavior: default
layout: header, diff
require_changes: false
coverage:
precision: 2
range:
- 70.0
- 100.0
round: down
status:
changes: false
patch: false
project: false
parsers:
gcov:
branch_detection:
conditional: true
loop: true
macro: false
method: false
javascript:
enable_partials: false


203 changes: 107 additions & 96 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,50 +14,51 @@
</modules>
<packaging>pom</packaging>
<name>paw</name>
<repositories>
<repository>
<id>jersey-snapshot</id>
<url>https://maven.java.net/content/repositories/snapshots/</url>
<name>Jersey Snapshots</name>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
<org.springframework.version>4.2.6.RELEASE</org.springframework.version>
<spring.security.version>4.0.4.RELEASE</spring.security.version>
<org.hibernate.version>5.1.0.Final</org.hibernate.version>
<servlet-api.version>3.1.0</servlet-api.version>
<org.slf4j.version>1.7.21</org.slf4j.version>
<ch.qos.logback.version>1.1.7</ch.qos.logback.version>
<org.logback.extensions.version>0.1.4</org.logback.extensions.version>
<jstl.version>1.2</jstl.version>
<org.hsqldb.version>2.3.1</org.hsqldb.version>
<junit.version>4.12</junit.version>
<mockito.version>1.10.19</mockito.version>
<org.postgresql>9.4-1200-jdbc41</org.postgresql>
<commons-lang3.version>3.4</commons-lang3.version>
<javax.validation-api.version>1.1.0.Final</javax.validation-api.version>
<org.hibernate-validator.version>5.2.4.Final</org.hibernate-validator.version>
<maven-war-plugin.version>3.0.0</maven-war-plugin.version>
<hibernate.jpa-api.version>1.0.0.Final</hibernate.jpa-api.version>
<org.jboss.logging>3.3.0.Final</org.jboss.logging>
<maven-surefire-plugin.version>2.15</maven-surefire-plugin.version>
<jacoco.version>0.7.8</jacoco.version>
<jacoco.ut.execution.data.file>${project.build.directory}/coverage-reports/jacoco-ut.exec</jacoco.ut.execution.data.file>
<skip.unit.tests>false</skip.unit.tests>
<coveralls-maven-plugin.version>4.3.0</coveralls-maven-plugin.version>
<coveralls-maven-plugin.jacoco-report>${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml</coveralls-maven-plugin.jacoco-report>
<sonar-maven-plugin.version>3.0.1</sonar-maven-plugin.version>
<jersey.version>3.0-SNAPSHOT</jersey.version>
<org.modelmapper.version>0.7.7</org.modelmapper.version>
<jersey.bean-validation>2.25</jersey.bean-validation>
</properties>
<repositories>
<repository>
<id>jersey-snapshot</id>
<url>https://maven.java.net/content/repositories/snapshots/</url>
<name>Jersey Snapshots</name>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
<org.springframework.version>4.2.6.RELEASE</org.springframework.version>
<spring.security.version>4.0.4.RELEASE</spring.security.version>
<org.hibernate.version>5.1.0.Final</org.hibernate.version>
<servlet-api.version>3.1.0</servlet-api.version>
<org.slf4j.version>1.7.21</org.slf4j.version>
<ch.qos.logback.version>1.1.7</ch.qos.logback.version>
<org.logback.extensions.version>0.1.4</org.logback.extensions.version>
<jstl.version>1.2</jstl.version>
<org.hsqldb.version>2.3.1</org.hsqldb.version>
<junit.version>4.12</junit.version>
<mockito.version>1.10.19</mockito.version>
<org.postgresql>9.4-1200-jdbc41</org.postgresql>
<commons-lang3.version>3.4</commons-lang3.version>
<javax.validation-api.version>1.1.0.Final</javax.validation-api.version>
<org.hibernate-validator.version>5.2.4.Final</org.hibernate-validator.version>
<maven-war-plugin.version>3.0.0</maven-war-plugin.version>
<hibernate.jpa-api.version>1.0.0.Final</hibernate.jpa-api.version>
<org.jboss.logging>3.3.0.Final</org.jboss.logging>
<maven-surefire-plugin.version>2.15</maven-surefire-plugin.version>
<jacoco.version>0.7.8</jacoco.version>
<jacoco.ut.execution.data.file>${project.build.directory}/coverage-reports/jacoco-ut.exec</jacoco.ut.execution.data.file>
<skip.unit.tests>false</skip.unit.tests>
<coveralls-maven-plugin.version>4.3.0</coveralls-maven-plugin.version>
<coveralls-maven-plugin.jacoco-report>${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml</coveralls-maven-plugin.jacoco-report>
<sonar-maven-plugin.version>3.0.1</sonar-maven-plugin.version>
<jersey.version>3.0-SNAPSHOT</jersey.version>
<org.modelmapper.version>0.7.7</org.modelmapper.version>
<jersey.bean-validation>2.25</jersey.bean-validation>
<jwt.version>0.7.0</jwt.version>
</properties>
<build>
<plugins>
<plugin>
Expand Down Expand Up @@ -347,57 +348,67 @@
<version>${jacoco.version}</version>
</dependency>

<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring4</artifactId>
<version>${jersey.version}</version>
<exclusions>
<exclusion>
<groupId>org.glassfish.hk2.external</groupId>
<artifactId>bean-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
<exclusions>
<exclusion>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>${jersey.bean-validation}</version>
</dependency>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring4</artifactId>
<version>${jersey.version}</version>
<exclusions>
<exclusion>
<groupId>org.glassfish.hk2.external</groupId>
<artifactId>bean-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
<exclusions>
<exclusion>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>${jersey.bean-validation}</version>
</dependency>
<!-- Jersey -->

<!-- Jersey JSON -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- Entity-DTO Mapper -->
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>${org.modelmapper.version}</version>
</dependency>

<!-- JSON JWT (User Token generator) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!-- JSON JWT (User Token generator) -->

<!-- Jersey JSON -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- Entity-DTO Mapper -->
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>${org.modelmapper.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand All @@ -406,7 +417,7 @@

<!-- Environment Settings -->
<ciManagement>
<system>travis</system>
<url>https://travis-ci.org/MatiasComercio/paw</url>
<system>travis</system>
<url>https://travis-ci.org/MatiasComercio/paw</url>
</ciManagement>
</project>
5 changes: 4 additions & 1 deletion webapp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,10 @@
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!--Testing-->
<dependency>
<groupId>junit</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package ar.edu.itba.paw.webapp.auth;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

public class JWTTokenHandler implements TokenHandler {
private static final String KEY = "B/1+wzD9jv8UwBZke9EZHfAclHDYre9msPR54UfhXmhx8OBQXrQb0URl9mBwGPBK\n" +
"ZExc4gxayeTxEPT3DIwMCZfCdMBVh4yjhzJ46AzummsrpyHeo2TgRtWRW+KCTtwo\n" +
"19kyrxbMpc8dEY9YO2ghNT0ZOcwtvEu13kzngevUsPV9pWsKdRXGgt5HV3rpuvJ7\n" +
"M0rL3BeV4L2HxkGcs6lfFgsHPxeQvtXLInwdTlrba0TjhN7AdC9vu3000CPmhRGL\n" +
"4opte33ukexjtkzRXoMdYsDv+pbbufi+vlcl439dwMl9toEhFpKt74ZmPfd989m2\n" +
"cvSzTN3iOdjfYlf2jMecDV/s05Cs1k4WgCuXYeBY7KVm0hDH3qSzUwPy2I8lH+Pv\n" +
"ECeypIH0fXNiJurARZ+TndcHicM0ENyEdtM8z8x77oneYioidGC6InotO3FiPiiP\n" +
"g5gkCMmZKgKdwrHqyT7+/TEUd6dggmHyUgLcSdIb6kznwof/vnbGaoIpyGJqGBc/\n" +
"rOk4WY61BOQAwnqxg/81vXTv+xFRSjhHWEoSNToshpZwXKq1OvM4s6xIENBXdz6p\n" +
"V3t4aUYxW7+wBxKxOkl4lq/2MFcTG0szMyiq4E9qrz4kSL6lKEzM/9arXX6+2uOy\n" +
"ccSr02tkCPLSl05R+/unRZJbOTAgFrvLQvl0dFawj7HQaS0sPf53NenXzU9gmVgo\n" +
"ZlINm2XKpmf3xOTCS81TS7ReKj4NMGAw0y0WhXasn18ziTEEK9im99SECsZC/hUU\n" +
"JXBgahepbHqkv8HzJkhV0ExhVn88OOv+Ma2X95ZARmkpbPVBhERRfWVSns12NQzX\n" +
"FAmS+LCbTTaE2xsz0PDSGZwKIFa5lh2QxKaNlSaaYLbOwVtYxf0CdNQHpvBYJSjj\n" +
"v5BNMyleYKCZAuLTqTRDuEPn08sPpii2bOafiKPWJ/dgqRjB2sJKpEj0E9IcO5Mk\n" +
"/SbjyQB7KD0ZwbCQyRC7ffaxjiHkOJV8GwC1x5wB0H5uSfPRIvOmm9FDiZeexbUc\n" +
"EiOYfXiqetKJe9dTcLKFKRYZDHIj3fZThasbA7nC2qthNHy/0T/UFksmMO+VnOUe\n" +
"Nm8Zq0DFZqQx6Q/FMUFWZbZvJDT8YtBATX6XkxHGpkWapnkidowDdsWeWT44HCfk\n" +
"uxCXTkhNRmoQAgOr5Eev2Zda7+ydFK6jxweC5hvR+diobD6ItHllAdBaoOj9hVVs\n" +
"tJ53S9JXi/az7+UlzxUtPgk4kO1jrulQ5XiN2tn6R2pv1ncnIHdqhaQHjSBkUZik\n" +
"vUf8FRscFkvo2EbtKPPLQiY6A1yuvrpobCgWj6TOKeujALF6jzdhepsk7sL2Qg1g\n" +
"6Nah/Tu9I0VOloJlciQenA==\n";

private UserDetailsService userDetailsServices = new UserDetailsServiceImpl();

@Override
public String createToken(final UserDetails user) {
final String token = Jwts.builder()
.setSubject(user.getUsername())
.signWith(SignatureAlgorithm.HS512, KEY)
.compact();

return token;
}

public String getUsername(final String token) {
String username = null;

try {
username = Jwts.parser()
.setSigningKey(KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
} catch (SignatureException e) {
return null;
}
return username;

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ar.edu.itba.paw.webapp.auth;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class PlainTextBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {

@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ar.edu.itba.paw.webapp.auth;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class StatelessAuthenticationFilter extends GenericFilterBean {

private final TokenAuthenticationService tokenAuthenticationService;

public StatelessAuthenticationFilter(TokenAuthenticationService tokenAuthenticationService) {
this.tokenAuthenticationService = tokenAuthenticationService;
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
final Authentication authentication = tokenAuthenticationService.getAuthentication((HttpServletRequest) request);

SecurityContextHolder.getContext().setAuthentication(authentication); //Set the context to be accessed by the controllers
chain.doFilter(request, response); //Continue the chain of filters
}
}
Loading

0 comments on commit 34c35a5

Please sign in to comment.