Skip to content

Commit

Permalink
Merge pull request #71 from arjantijms/restFormAuthCustomStoreRememberMe
Browse files Browse the repository at this point in the history
JETUT-114 Add example for remember-me applied to provided authentication
  • Loading branch information
arjantijms committed Jun 14, 2023
2 parents 71f7b31 + 1d610cf commit 74ac6cd
Show file tree
Hide file tree
Showing 13 changed files with 434 additions and 0 deletions.
1 change: 1 addition & 0 deletions focused/security/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<module>restBasicAuthCustomStoreHandler</module>
<module>restFormAuthCustomStore</module>
<module>restCustomAuthCustomStore</module>
<module>restFormAuthCustomStoreRememberMe</module>
<module>basicAuth</module>
<module>customFormWithJsf</module>
<module>filter</module>
Expand Down
4 changes: 4 additions & 0 deletions focused/security/restFormAuthCustomStoreRememberMe/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# A RESTful form authentication with custom identity store and remember-me example

This example demonstrates how to use Jakarta Security to secure a REST endpoint with form authentication
a custom (user provided) identity store, and remember-me.
37 changes: 37 additions & 0 deletions focused/security/restFormAuthCustomStoreRememberMe/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
-->
<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>
<groupId>jakarta.examples.focused.eesecurity</groupId>
<artifactId>project</artifactId>
<version>10-SNAPSHOT</version>
</parent>

<artifactId>restFormAuthCustomStoreRememberMe</artifactId>
<packaging>war</packaging>

<name>A Jakarta Security RESTful form authentication with custom identity store example and remember-me.</name>

<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package jakartaee.examples.focused.security.restformauthcustomatorerememberme;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension;
import jakarta.enterprise.inject.build.compatible.spi.ClassConfig;
import jakarta.enterprise.inject.build.compatible.spi.Enhancement;
import jakarta.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition;
import jakarta.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism;
import jakarta.security.enterprise.authentication.mechanism.http.LoginToContinue;
import jakarta.security.enterprise.authentication.mechanism.http.RememberMe;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationScoped
@FormAuthenticationMechanismDefinition(
loginToContinue = @LoginToContinue(
loginPage="/login.html",
errorPage="/login-error.html"
)
)
@ApplicationPath("/rest")
public class ApplicationConfig extends Application implements BuildCompatibleExtension {

@Enhancement(types = HttpAuthenticationMechanism.class, withSubtypes = true)
public void addRememberMe(ClassConfig httpAuthenticationMechanism) {
httpAuthenticationMechanism.addAnnotation(
RememberMe.Literal.INSTANCE);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package jakartaee.examples.focused.security.restformauthcustomatorerememberme;

import static jakarta.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT;

import java.util.Set;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.security.enterprise.credential.UsernamePasswordCredential;
import jakarta.security.enterprise.identitystore.CredentialValidationResult;
import jakarta.security.enterprise.identitystore.IdentityStore;

/**
* A custom identity store that will be picked up automatically by Jakarta Security.
*
* <p>
* Jakarta Security picks up any enabled CDI bean that implements <code>IdentityStore</code>.
*
* @author Arjan Tijms
*
*/
@ApplicationScoped
public class CustomIdentityStore implements IdentityStore {

public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) {
if (usernamePasswordCredential.compareTo("john", "secret1")) {
return new CredentialValidationResult("john", Set.of("user", "caller"));
}

return INVALID_RESULT;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/

package jakartaee.examples.focused.security.restformauthcustomatorerememberme;


import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.security.enterprise.CallerPrincipal;
import jakarta.security.enterprise.credential.RememberMeCredential;
import jakarta.security.enterprise.identitystore.CredentialValidationResult;
import jakarta.security.enterprise.identitystore.RememberMeIdentityStore;

import static jakarta.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT;

/**
* A custom remember-me identity store that will be picked up automatically by Jakarta Security.
*
* <p>
* Jakarta Security picks up any enabled CDI bean that implements <code>RememberMeIdentityStore</code>.
*
* @author Arjan Tijms
*
*/
@ApplicationScoped
public class CustomRememberMeIdentityStore implements RememberMeIdentityStore {

private final Map<String, CredentialValidationResult> tokenToIdentityMap = new ConcurrentHashMap<>();

@Override
public CredentialValidationResult validate(RememberMeCredential credential) {
if (tokenToIdentityMap.containsKey(credential.getToken())) {
return tokenToIdentityMap.get(credential.getToken());
}

return INVALID_RESULT;
}

@Override
public String generateLoginToken(CallerPrincipal callerPrincipal, Set<String> groups) {
var token = UUID.randomUUID().toString();

tokenToIdentityMap.put(token, new CredentialValidationResult(callerPrincipal, groups));

return token;
}

@Override
public void removeLoginToken(String token) {
tokenToIdentityMap.remove(token);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package jakartaee.examples.focused.security.restformauthcustomatorerememberme;

import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN;

import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.security.enterprise.SecurityContext;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;

@Path("/resource")
@RequestScoped
public class Resource {

@Inject
private SecurityContext securityContext;

@GET
@Produces(TEXT_PLAIN)
public String getCallerAndRole() {
return
securityContext.getCallerPrincipal().getName() + " : " +
securityContext.isCallerInRole("user");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jakartaee.examples.focused.security.restformauthcustomatorerememberme.ApplicationConfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
-->
<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="all"
version="4.0">
</beans>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
-->
<web-app 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"
version="6.0">

<security-constraint>
<web-resource-collection>
<web-resource-name>protected</web-resource-name>
<url-pattern>/rest/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>user</role-name>
</security-role>

</web-app>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>

<!--
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
-->

<html>
<head>
<title>Failure</title>
</head>
<body>
Login failed!
<a href="login.html">Try again</a>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE html>

<!--
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
-->

<html>
<head>
<title>Login</title>
</head>
<body>
Login to continue
<form method="POST" action="j_security_check">
<p>
<label>Username </label> <input type="text" name="j_username">
<p>
<label>Password </label> <input type="password" name="j_password">
<p>
<input type="submit" value="Submit">
</form>
</body>
</html>


Loading

0 comments on commit 74ac6cd

Please sign in to comment.