-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A proposal for injectable built-in auth mechanisms
Signed-off-by:Ondro Mihalyi <[email protected]>
- Loading branch information
Showing
10 changed files
with
272 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,3 +28,4 @@ target/ | |
/**/.classpath | ||
/**/.project | ||
/**/.gitignore | ||
/injectable-ham/src/main/webapp/WEB-INF/glassfish-web.xml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Proposal to inject built-in HttpAuthenticationMechanism beans | ||
|
||
This is to make it possible to choose programmatically which of the built-in authentication mechanisms should be used based on configuration or user input. It would be possible to inject one or more mechanisms configured using the existing definition annotations (e.g. `@BasicAuthenticationMechanismDefinition`) and delegate authentication to them from a custom HttpAuthenticationMechanism bean. | ||
|
||
## Example | ||
|
||
``` | ||
@ApplicationScoped | ||
public class CustomAuth implements HttpAuthenticationMechanism { | ||
@Inject | ||
@FormAuthenticationMechanismDefinition(loginToContinue = @LoginToContinue(loginPage = "/login.xhtml")) | ||
HttpAuthenticationMechanism formAuthentication; | ||
@Override | ||
public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext context) throws AuthenticationException { | ||
return formAuthentication.validateRequest(request, response, context); | ||
} | ||
} | ||
``` | ||
|
||
## Use cases | ||
|
||
### Select which OpenID provider to use | ||
|
||
When an application wants to support multiple OpenID providers (Google, Auth0, a custom provider). The user should be able to select which provider they want to use to authenticate. E.g. if they already have a Google account, they would select Google as their provider. Their selection can be implemented for example as a cookie or a query parameter in the login action URL. A custom auth mechanism would detect this selection from the request object and delegate to one of the injected built-in OpenID mechanisms. | ||
|
||
### Select between OpenID authentication and form-based (user/password) authentication | ||
|
||
When an application wants to support OpenID on top of it's own form/based authentication mechanism. Users already have accounts in the system, can log in using user/password. Additionally, they have an option to connect their OpenID account with their existing account and log in using the OpenID acocunt besides using user/password. | ||
|
||
### Multitenant applications | ||
|
||
When the application supports multiple tenants (customers, user groups, etc.), it's desirable that each group of users using a different authentication mechanism. If at least one of the mechanisms uses a built-in mechanism (e.g. form-based or OpenID-Connect), these mechanisms can be simply injected into a custom mechanism and reused for the specific tenant. | ||
|
||
A simple multitenancy with a fixed number of tenants can be implemented simply by injecting an authentication mechanism per tenant. | ||
|
||
Dynamic multitenancy (with configurable number of tenants) is not possible using this approach and is out of scope of this proposal. Dynamic multitenancy would require some API (e.g. a CDI bean) which would provide configuration based on the current tenant. It would also be required that the built-in mechanisms, which are application-scoped, support reconfiguration per session/request. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<artifactId>javaee-security-examples</artifactId> | ||
<groupId>net.java.jsr375</groupId> | ||
<version>1.0-SNAPSHOT</version> | ||
</parent> | ||
<groupId>net.java.jsr375</groupId> | ||
<artifactId>injectable-ham</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
<packaging>war</packaging> | ||
<name>injectable-ham-1.0-SNAPSHOT</name> | ||
|
||
<properties> | ||
<maven.compiler.source>11</maven.compiler.source> | ||
<maven.compiler.target>11</maven.compiler.target> | ||
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
<failOnMissingWebXml>false</failOnMissingWebXml> | ||
<jakartaee>10.0.0</jakartaee> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>jakarta.platform</groupId> | ||
<artifactId>jakarta.jakartaee-api</artifactId> | ||
<version>${jakartaee}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>3.8.1</version> | ||
<configuration> | ||
<source>11</source> | ||
<target>11</target> | ||
<compilerArguments> | ||
<endorseddirs>${endorsed.dir}</endorseddirs> | ||
</compilerArguments> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-war-plugin</artifactId> | ||
<version>3.3.2</version> | ||
<configuration> | ||
<failOnMissingWebXml>false</failOnMissingWebXml> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-dependency-plugin</artifactId> | ||
<version>2.6</version> | ||
<executions> | ||
<execution> | ||
<phase>validate</phase> | ||
<goals> | ||
<goal>copy</goal> | ||
</goals> | ||
<configuration> | ||
<outputDirectory>${endorsed.dir}</outputDirectory> | ||
<silent>true</silent> | ||
<artifactItems> | ||
<artifactItem> | ||
<groupId>jakarta.platform</groupId> | ||
<artifactId>jakarta.jakartaee-api</artifactId> | ||
<version>${jakartaee}</version> | ||
<type>jar</type> | ||
</artifactItem> | ||
</artifactItems> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
52 changes: 52 additions & 0 deletions
52
injectable-ham/src/main/java/injectableham/CustomAuth.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package injectableham; | ||
|
||
import jakarta.enterprise.context.ApplicationScoped; | ||
import jakarta.enterprise.inject.spi.CDI; | ||
import jakarta.inject.Inject; | ||
import jakarta.security.enterprise.AuthenticationException; | ||
import jakarta.security.enterprise.AuthenticationStatus; | ||
import jakarta.security.enterprise.authentication.mechanism.http.BasicAuthenticationMechanismDefinition; | ||
import jakarta.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition; | ||
import jakarta.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism; | ||
import jakarta.security.enterprise.authentication.mechanism.http.HttpMessageContext; | ||
import jakarta.security.enterprise.authentication.mechanism.http.LoginToContinue; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.util.Set; | ||
|
||
@ApplicationScoped | ||
public class CustomAuth implements HttpAuthenticationMechanism { | ||
|
||
@Inject | ||
@FormAuthenticationMechanismDefinition(loginToContinue = @LoginToContinue(loginPage = "/login.xhtml")) | ||
HttpAuthenticationMechanism formAuthentication; | ||
|
||
@Inject | ||
@BasicAuthenticationMechanismDefinition | ||
HttpAuthenticationMechanism basicAuthentication; | ||
|
||
private HttpAuthenticationMechanism getMechanism(HttpServletRequest request) { | ||
if ("authType".equals(request.getParameter("form")) ) { | ||
return formAuthentication; | ||
} else { | ||
return basicAuthentication; | ||
} | ||
|
||
} | ||
|
||
@Override | ||
public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException { | ||
return getMechanism(request).validateRequest(request, response, httpMessageContext); | ||
} | ||
|
||
@Override | ||
public AuthenticationStatus secureResponse(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException { | ||
return getMechanism(request).secureResponse(request, response, httpMessageContext); | ||
} | ||
|
||
@Override | ||
public void cleanSubject(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) { | ||
getMechanism(request).cleanSubject(request, response, httpMessageContext); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd" | ||
bean-discovery-mode="annotated"> | ||
</beans> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<web-app version="6.0" xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"> | ||
<context-param> | ||
<param-name>jakarta.faces.PROJECT_STAGE</param-name> | ||
<param-value>Development</param-value> | ||
</context-param> | ||
<servlet> | ||
<servlet-name>Faces Servlet</servlet-name> | ||
<servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class> | ||
<load-on-startup>1</load-on-startup> | ||
</servlet> | ||
<servlet-mapping> | ||
<servlet-name>Faces Servlet</servlet-name> | ||
<url-pattern>/faces/*</url-pattern> | ||
</servlet-mapping> | ||
<session-config> | ||
<session-timeout> | ||
30 | ||
</session-timeout> | ||
</session-config> | ||
<security-role> | ||
<description>admin</description> | ||
<role-name>admin</role-name> | ||
</security-role> | ||
<welcome-file-list> | ||
<welcome-file>faces/index.xhtml</welcome-file> | ||
</welcome-file-list> | ||
<security-constraint> | ||
<display-name>admin</display-name> | ||
<web-resource-collection> | ||
<web-resource-name>secured</web-resource-name> | ||
<url-pattern>/secured/*</url-pattern> | ||
</web-resource-collection> | ||
<auth-constraint> | ||
<description>admin</description> | ||
<role-name>admin</role-name> | ||
</auth-constraint> | ||
</security-constraint> | ||
</web-app> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?xml version='1.0' encoding='UTF-8' ?> | ||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
<html> | ||
<head> | ||
<title>Start Page</title> | ||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | ||
</head> | ||
<body> | ||
<h1>Hello World!</h1> | ||
<p> | ||
<a href="secured/admin.xhtml">Secured admin - unauthorized</a> | ||
</p> | ||
<p> | ||
<a href="secured/admin.xhtml?user=admin">Secured admin - authorized</a> | ||
</p> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version='1.0' encoding='UTF-8' ?> | ||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
<html xmlns="http://www.w3.org/1999/xhtml" | ||
xmlns:h="http://xmlns.jcp.org/jsf/html"> | ||
<h:head> | ||
<title>Login form</title> | ||
</h:head> | ||
<h:body> | ||
|
||
|
||
<form style="margin: 1rem" method="POST" action="j_security_check"> | ||
<p>User: | ||
<input type="text" name="j_username"/> | ||
</p> | ||
<p>Password: | ||
<input type="password" name="j_password" autocomplete="off"/> | ||
</p> | ||
<p><button type="submit">Log in</button> | ||
</p> | ||
</form> | ||
|
||
|
||
</h:body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version='1.0' encoding='UTF-8' ?> | ||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
<html xmlns="http://www.w3.org/1999/xhtml" | ||
xmlns:h="http://xmlns.jcp.org/jsf/html"> | ||
<h:head> | ||
<title>Facelet Title</title> | ||
</h:head> | ||
<h:body> | ||
Hello from Facelets | ||
</h:body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters