Die Art und Weise der Client-Server-Authentifizierung hat in den vergangenen Jahren einen rasanten Wechsel erfahren. Anmeldungen z.B. über OAuth 2 sind Standard. Auch wenn Authentifizierungsmethoden wie Single-Sign-On (SSO) bereits seit mehreren Jahrzehnten Anforderungen von Unternehmen sind, gab es bisher im Enterprise Java Standard keine Lösungen dafür. Das hat sich mit Java EE 8 und der Version 1.0 der Security-API geändert.
Neben einem Blick auf die neuen Features der Security-API zeigt dieser Vortrag auch die Authentifizierung im Bereich der verteilten Systeme mit Hilfe von SSO über das JWT. Dabei wird darauf eingegangen, was der Standard nun bietet und was der Entwickler dazubauen muss.
2. Ausführliches Beispiel mit Code Beispiel
demnächst auf unserem Blog verfügbar
www.openknowledge.de/blog
www.github.com/openknowledge
Info auf Twitter: @_openknowledge
11. JAAS LoginModule
• Implementierung des Interfaces
javax.security.auth.spi.LoginModule
• Befüllen eines javax.security.auth.Subjects mit
java.security.Principals
#WISSENTEILEN
12. JAAS LoginModule
• Implementierung des Interfaces
javax.security.auth.spi.LoginModule
• Befüllen eines javax.security.auth.Subjects mit
java.security.Principals
• Two-Phase-Authentication
#WISSENTEILEN
13. JAAS LoginModule
• Implementierung des Interfaces
javax.security.auth.spi.LoginModule
• Befüllen eines javax.security.auth.Subjects mit
java.security.Principals
• Two-Phase-Authentication
• 1. Phase: Kann das Modul authentifizieren?
#WISSENTEILEN
14. JAAS LoginModule
• Implementierung des Interfaces
javax.security.auth.spi.LoginModule
• Befüllen eines javax.security.auth.Subjects mit
java.security.Principals
• Two-Phase-Authentication
• 1. Phase: Kann das Modul authentifizieren?
• 2. Phase: Login erfolgreich Befüllen des Subjects
#WISSENTEILEN
23. Java EE 8 – IdentityStore
public interface IdentityStore {
CredentialValidationResult validate(Credential credential);
Set<String> getCallerGroups(CredentialValidationResult result);
int priority();
Set<ValidationType> validationTypes();
enum ValidationType { VALIDATE, PROVIDE_GROUPS }
}
#WISSENTEILEN
24. Java EE 8 – IdentityStore
@LdapIdentityStoreDefinition(
url = "ldap://localhost:3268",
bindDn = "readonly@openknownledge",
bindDnPassword = "password"
)
@DatabaseIdentityStoreDefinition(
dataSourceLookup = "java:jboss/datasources/ExampleDS",
callerQuery = "SELECT password from USERS where name = ?"
)
#WISSENTEILEN
25. Java EE 8 – CredentialValidationResult
public class CredentialValidationResult {
public Status getStatus() {...}
public CallerPrincipal getCallerPrincipal() {...}
public Set<String> getCallerGroups() {...}
public enum Status { NOT_VALIDATED, INVALID, VALID }
}
#WISSENTEILEN
38. Java EE 8 – Security 1.0
• JSR 375
• Aufsatz auf das JASPIC ServerAuthModule
#WISSENTEILEN
39. Java EE 8 – Security 1.0
• JSR 375
• Aufsatz auf das JASPIC ServerAuthModule
• dadurch Java EE 7 kompatibel
#WISSENTEILEN
40. Java EE 8 – Security 1.0
• JSR 375
• Aufsatz auf das JASPIC ServerAuthModule
• dadurch Java EE 7 kompatibel
• Nutzt IdentityStore(Handler)
#WISSENTEILEN
41. Java EE 8 – Security 1.0
• JSR 375
• Aufsatz auf das JASPIC ServerAuthModule
• dadurch Java EE 7 kompatibel
• Nutzt IdentityStore(Handler)
• Nur für HTTP-Authentication
#WISSENTEILEN
42. Java EE 8 – Security 1.0
• JSR 375
• Aufsatz auf das JASPIC ServerAuthModule
• dadurch Java EE 7 kompatibel
• Nutzt IdentityStore(Handler)
• Nur für HTTP-Authentication
• Referenzimplementierung Soteria von GlassFish
#WISSENTEILEN
43. Was ist mit Token-basierten
Authentifizierungsmethoden wie
z.B. JSON Web Token?
82. FAZIT AUTHENTICATION IN JAVA EE 8
Eigene Nutzerquelle ohne Container-Config
Standard-Mechanismen weiterhin möglich
83. FAZIT AUTHENTICATION IN JAVA EE 8
Eigene Nutzerquelle ohne Container-Config
Standard-Mechanismen weiterhin möglich
Support für RememberMe
84. FAZIT AUTHENTICATION IN JAVA EE 8
Eigene Nutzerquelle ohne Container-Config
Standard-Mechanismen weiterhin möglich
Support für RememberMe
Leichte Erweiterbarkeit für HTTP-basierte Mechanismen
95. Role based Access Control
Roles
Teacher 1
Users Permissions
Student 1 Read Course
Teacher
Student
...
...
#WISSENTEILEN
96. Role based Access Control
Servlet Spec
Permissions für Web-Resources
#WISSENTEILEN
97. Role based Access Control
web.xml / Annotations
<security-constraint>
<web-resource-name>courses API</…>
<url-pattern>/api/protected/courses</…>
<auth-constraint>
<role-name>TEACHER</…>
</auth-constraint>
</security-constraint>
@ServletSecurity(
@HttpConstraint(rolesAllowed = {"TEACHER"})
)
#WISSENTEILEN
98. Role based Access Control
Servlet Spec
Permissions für Web-Resources
#WISSENTEILEN
99. Role based Access Control
Servlet Spec
Permissions für Web-Resources
Java EE Security
Permissions für Klassen und Methoden
via @RolesAllowed
Standard unterstützt kein JAX-RS
#WISSENTEILEN
100. Role based Access Control
Servlet Spec
Permissions für Web-Resources
Java EE Security
Permissions für Klassen und Methoden
via @RolesAllowed
Standard unterstützt kein JAX-RS
Java EE 8 Security
Standard-Mapping für User und Rollen
#WISSENTEILEN
110. Role based Access Control
web.xml
<security-constraint>
<web-resource-name>studens API</…>
<url-pattern>/api/protected/students</…>
<auth-constraint>
<role-name>TEACHER</…>
<role-name>STUDENTS</…>
</auth-constraint>
</security-constraint>
#WISSENTEILEN
111. Role based Access Control
web.xml
<security-constraint>
<web-resource-name>studens API</…>
<url-pattern>/api/protected/students</…>
<auth-constraint>
<role-name>TEACHER</…>
<role-name>STUDENTS</…>
</auth-constraint>
</security-constraint>
#WISSENTEILEN
112. Role based Access Control
web.xml
<security-constraint>
<web-resource-name>studens API</…>
<url-pattern>/api/protected/students</…>
<auth-constraint>
<role-name>TEACHER</…>
<role-name>STUDENTS</…>
</auth-constraint>
</security-constraint>
Rechtevergabe auf Methodenebene notwendig!
#WISSENTEILEN
133. Kurs anlegen
@RolesAllowed("TEACHER")
public Course create(Teacher lecturer, …) {
Course course = new Course(lecturer, …);
entityManager.persist(course);
return course;
}
Role Based Access Control reicht nicht aus!
#WISSENTEILEN
134. Kurs anlegen
@Inject
private Principal currentPrincipal;
public Course create(Teacher lecturer, …) {
if (!lecturer.equals(currentPrincipal)) {
throw new SecurityException(…);
}
…
}
#WISSENTEILEN
135. Kurs anlegen
@Inject
private Principal currentPrincipal;
public Course create(Teacher lecturer, …) {
if (!lecturer.equals(currentPrincipal)) {
throw new SecurityException(…);
}
…
}
Sicherheitsüberprüfungen im Code verteilt!
#WISSENTEILEN
149. Separate Logik-Implementierung
public class SecurityRules {
@Secures @Create
public boolean checkOwner(@Owner User owner,
Identity user) {
return owner.equals(user);
}
}
#WISSENTEILEN
150. Separate Logik-Implementierung
public class SecurityRules {
@Secures @Create
public boolean checkOwner(@Owner User owner,
Identity user) {
return owner.equals(user);
}
}
#WISSENTEILEN
151. Separate Logik-Implementierung
public class SecurityRules {
@Secures @Create
public boolean checkOwner(@Owner User owner,
Identity user) {
return owner.equals(user);
}
}
#WISSENTEILEN
152. Separate Logik-Implementierung
public class SecurityRules {
@Secures @Create
public boolean checkOwner(@Owner User owner,
Identity user) {
return owner.equals(user);
}
}
#WISSENTEILEN
153. JPA Security
Security Framework für JPA
https://github.com/ArneLimburg/jpasecurity
• Pluggable Authentication
• Authorization
• Access-Check bei CRUD-Operationen
• In-Database-Filtern von Queries (JPQL und Criteria)
#WISSENTEILEN
158. @Permit(access = AccessType.CREATE,
rule = "lecturer = CURRENT_PRINCIPAL")
@Entity
public Course {
…
}
Automatischer Check bei entityManager.persist(…) oder
entityManager.merge(…) oder bei Cascading!
Entity-Security mit JPA Security
#WISSENTEILEN
159. Entity-Security mit JPA Security
public List<Student> findAll() {
TypedQuery<Student> query
= entityManager.createQuery("SELECT s FROM Student s", …);
return query.getResultList();
}
#WISSENTEILEN
160. Entity-Security mit JPA Security
public List<Student> findAll() {
TypedQuery<Student> query
= entityManager.createQuery("SELECT s FROM Student s", …);
return query.getResultList();
}
Lehrer darf nur Studenten aus seinen eigenen Kursen sehen.
#WISSENTEILEN
161. Entity-Security mit JPA Security
public List<Student> findAll() {
TypedQuery<Student> query
= entityManager.createNamedQuery(…, …);
return query.getResultList();
}
Automatische Filterung von JPA Queries und Criterias!
#WISSENTEILEN
162. @PermitAny({
@Permit(access = AccessType.READ, rule
= "this IN (SELECT p"
+ " FROM Course course"
+ " JOIN course.participants p"
+ " WHERE course.lecturer"
+ " = CURRENT_PRINCIPAL)"),
@Permit(…)})
@Entity
public Student {
…
Entity-Security mit JPA Security
#WISSENTEILEN
163. Entity-Security mit JPA Security
public List<Student> findAll() {
TypedQuery<Student> query
= entityManager.createQuery("SELECT s FROM Student s", …);
return query.getResultList();
}
erzeugt
SELECT s FROM Student s WHERE s IN (SELECT p FROM Course course
JOIN course.participants p
WHERE course.lecturer
= CURRENT_PRINCIPAL) …
#WISSENTEILEN