Build A Java REST API With Java EE and OIDC - Okta Developer
Build A Java REST API With Java EE and OIDC - Okta Developer
September 12, 2018
Matt Raible
Java EE allows you to build Java REST APIs quickly and easily with JAX-RS and JPA. Java
EE is an umbrella standards specification that describes a number of Java technologies,
including EJB, JPA, JAX-RS, and many others. It was originally designed to allow portability
between Java application servers, and flourished in the early 2000s. Back then, application
servers were all the rage and provided by many well-known companies such as IBM, BEA,
and Sun. JBoss was a startup that disrupted the status quo and showed it was possible to
develop a Java EE application server as an open source project, and give it away for free.
JBoss was bought by RedHat in 2006.
In the early 2000s, Java developers used servlets and EJBs to develop their server
applications. Hibernate and Spring came along in 2002 and 2004, respectively. Both
technologies had a huge impact on Java developers everywhere, showing them it was
possible to write distributed, robust applications without EJBs. Hibernate’s POJO model
was eventually adopted as the JPA standard and heavily influenced EJB as well.
Fast forward to 2018, and Java EE certainly doesn’t look like it used to! Now, it’s mostly
POJOs and annotations and far simpler to use.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 1/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
For this reason, I thought it’d be fun to build a Java REST API (using Java EE) that’s the
same as a Spring Boot REST API I developed in the past. Namely, the “good-beers” API
from my Bootiful Angular and Bootiful React posts.
I liked the jaxrs-starter project because it showed how to create a REST API with JAX-RS.
The TomEE Maven archetype was helpful too, especially since it showed how to use JPA,
H2, and JSF. I combined the two to create my own minimal starter that you can use to
implement secure Java EE APIs on TomEE. You don’t have to use TomEE for these
examples, but I haven’t tested them on other implementations.
If you get these examples working on other app servers, please let me know and I’ll update
this blog post.
In these examples, I’ll be using Java 8 and Java EE 7.0 with TomEE 7.1.0. TomEE 7.x is the EE
7 compatible version; a TomEE 8.x branch exists for EE8 compatibility work, but there are
no releases yet. I expect you to have Apache Maven installed too.
To begin, clone our Java EE REST API repository to your hard drive, and run it:
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 2/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
cd javaee-rest-api
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 3/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
You can also view the list of good beers in the system at
http://localhost:8080/good-beers . Below is the output when using HTTPie.
$ http :8080/good-beers
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
"id": 101,
},
"id": 102,
},
"id": 103,
},
"id": 104,
},
"id": 108,
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 4/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
$ tree .
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
└── test
└── resources
└── arquillian.xml
12 directories, 16 files
The most important XML files is the pom.xml that defines dependencies and allows you
to run the TomEE Maven Plugin. It’s pretty short and sweet, with only one dependency and
one plugin.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 5/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
<groupId>com.okta.developer</groupId>
<artifactId>java-ee-rest-api</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<url>http://developer.okta.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<failOnMissingWebXml>false</failOnMissingWebXml>
<javaee-api.version>7.0</javaee-api.version>
<tomee.version>7.1.0</tomee.version>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>${javaee-api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>${tomee.version}</version>
<configuration>
<context>ROOT</context>
</configuration>
</plugin>
</plugins>
</build>
</project>
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 6/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
package com.okta.developer;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Beer() {}
this.name = name;
return id;
this.id = id;
return name;
this.name = beerName;
@Override
return "Beer{" +
"id=" + id +
'}';
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 7/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml
<persistence-unit name="beer-pu" transaction-type="JTA">
<jta-data-source>beerDatabase</jta-data-source>
<class>com.okta.developer.Beer</class>
<properties>
</persistence-unit>
</persistence>
The BeerService.java class handles reading and saving this entity to the database
using JPA’s EntityManager .
package com.okta.developer;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import java.util.List;
@Stateless
@PersistenceContext(unitName = "beer-pu")
entityManager.persist(beer);
CriteriaQuery<Beer> cq = entityManager.getCriteriaBuilder().createQuery(Beer.class);
cq.select(cq.from(Beer.class));
return entityManager.createQuery(cq).getResultList();
removeAll.executeUpdate();
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 8/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
package com.okta.developer;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
import java.util.stream.Stream;
@Singleton
@Startup
@Inject
this.beerService = beerService;
@PostConstruct
beerService.addBeer(new Beer(name))
);
beerService.getAllBeers().forEach(System.out::println);
@PreDestroy
beerService.clear();
These three classes make up the foundation of the app, plus there’s a
BeerResource.java class that uses JAX-RS to expose the /good-beers endpoint.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 9/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
package com.okta.developer;
import javax.ejb.Lock;
import javax.ejb.Singleton;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import java.util.List;
import java.util.stream.Collectors;
@Lock(READ)
@Singleton
@Path("/good-beers")
@Inject
this.beerService = beerService;
@GET
@Produces({APPLICATION_JSON})
return beerService.getAllBeers().stream()
.filter(this::isGreat)
.collect(Collectors.toList());
!beer.getName().equals("PBR");
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 10/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
package com.okta.developer;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.List;
@Named
@RequestScoped
@Inject
return name;
this.name = name;
return beersAvailable;
beersAvailable = beerService.getAllBeers();
return "success";
beer.setName(name);
beerService.addBeer(beer);
return "success";
You now have a REST API built with Java EE! However, it’s not secure. In the following
sections, I’ll show you how to secure it using Okta’s JWT Verifier for Java, Spring Security,
and Pac4j.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 11/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
Are you sold? Register for a forever-free developer account today! When you’re finished,
complete the steps below to create an OIDC app.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 12/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
<properties>
...
<okta-jwt.version>0.3.0</okta-jwt.version>
</properties>
<dependencies>
...
<dependency>
<groupId>com.okta.jwt</groupId>
<artifactId>okta-jwt-verifier</artifactId>
<version>${okta-jwt.version}</version>
</dependency>
</dependencies>
Make sure to replace {yourOktaDomain} and {clientId} with the settings from the
app you created.
package com.okta.developer;
import com.nimbusds.oauth2.sdk.ParseException;
import com.okta.jwt.JoseException;
import com.okta.jwt.Jwt;
import com.okta.jwt.JwtHelper;
import com.okta.jwt.JwtVerifier;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Override
try {
.setIssuerUrl("https://{yourOktaDomain}/oauth2/default")
.setClientId("{yourClientId}")
.build();
e.printStackTrace();
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 13/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
@Override
if (authHeader == null) {
return;
} else {
try {
} catch (JoseException e) {
e.printStackTrace();
return;
chain.doFilter(request, response);
@Override
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 14/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
To prove it works with a valid JWT, you can clone my Bootiful React project, and run its UI:
npm install
Edit this project’s client/src/App.tsx file and change the issuer and clientId to
match your application.
const config = {
issuer: 'https://{yourOktaDomain}/oauth2/default',
clientId: '{yourClientId}'
};
npm start
You should then be able to login at http://localhost:3000 with the credentials you
created your account with. However, you won’t be able to load any beers from the API
because of a CORS error (in your browser’s developer console).
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 15/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
TIP: If you see a 401 and no CORS error, it likely means your client IDs don’t match.
To fix this CORS error, add a CorsFilter.java alongside your JwtFilter.java class.
The filter below will allow an OPTIONS request, and send access-control headers back
that allow any origin, GET methods, and any headers. I recommend you to make these
settings a bit more specific in production.
package com.okta.developer;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "corsFilter")
@Override
response.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");
response.addHeader("Access-Control-Allow-Methods", "GET");
response.addHeader("Access-Control-Allow-Headers", "*");
// For HTTP OPTIONS verb/method reply with ACCEPTED status code -- per CORS handshake
if (request.getMethod().equals("OPTIONS")) {
response.setStatus(HttpServletResponse.SC_ACCEPTED);
return;
chain.doFilter(request, response);
@Override
@Override
Both of the filters you’ve added use @WebFilter to register themselves. This is a
convenient annotation, but it doesn’t provide any filter ordering capabilities. To workaround
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 16/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
@WebFilter(filterName = "jwtFilter")
<web-app version="3.1"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/jav
<filter-mapping>
<filter-name>corsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>jwtFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 17/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
Hello, demo@okta.com
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 18/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
Using a filter with Okta’s JWT Verifier is an easy way to implement a resource server (in
OAuth 2.0 nomenclature). However, it doesn’t provide you with any information about the
user. The JwtVerifier interface does have a
decodeIdToken(String idToken, String nonce) method, but you’d have to pass
the ID token in from your client to use it.
In the next two sections, I’ll show you how you can use Spring Security and Pac4j to
implement similar security. As a bonus, I’ll show you how to prompt the user to login (when
they try to access the API directly) and get the user’s information.
Revert your changes to add JWT Verifier, or simply delete web.xml to continue.
Modify your pom.xml to have the necessary dependencies for Spring Security. You’ll also
need to add Spring’s snapshot repositories to get the release candidate.
<properties>
...
<spring-security.version>5.1.0.RC2</spring-security.version>
<spring.version>5.1.0.RC3</spring.version>
<jackson.version>2.9.6</jackson.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>${spring.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-bom</artifactId>
<version>${spring-security.version}</version>
<scope>import</scope>
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 19/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
p p p
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshot</name>
<url>https://repo.spring.io/libs-snapshot</url>
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 20/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
</repository>
</repositories>
package com.okta.developer;
import org.springframework.security.web.context.*;
extends AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(SecurityConfiguration.class);
package com.okta.developer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAd
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationReposi
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@Configuration
@EnableWebSecurity
@PropertySource("classpath:application.properties")
@Autowired
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 21/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
this.issuerUri = issuerUri;
this.clientId = clientId;
this.clientSecret = clientSecret;
@Override
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
@Bean
@Bean
.map(this::getRegistration)
.filter(Objects::nonNull)
.collect(Collectors.toList());
@Bean
ClientRegistrations.fromOidcIssuerLocation(Objects.requireNonNull(issuerUri))
.registrationId("okta")
.clientId(clientId)
.clientSecret(clientSecret)
.build();
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 22/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
okta.client-id={clientId}
okta.client-secret={clientSecret}
okta.issuer-uri=https://{yourOktaDomain}/oauth2/default
Because you enabled CSRF, you have to add the following hidden field for CSRF
protection inside any <h:form> tags. I added the following to
src/main/webapp/beer.xhtml and result.xhtml .
Enter valid credentials and you should see JSON in your browser. Nice looking JSON is
provided by the JSON Viewer Chrome Plugin.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 23/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
Requiring users to login to view your API data is handy, but it’s better to make it a resource
server for the React UI example. OAuth 2.0 Resource Server support is new in Spring
Security 5.1.0 RC1, so I’ll show you how to use it.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 24/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
@Override
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.cors()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.and()
.oauth2ResourceServer()
.jwt();
@Bean
JwtDecoder jwtDecoder() {
return JwtDecoders.fromOidcIssuerLocation(this.issuerUri);
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
configuration.setAllowedMethods(Collections.singletonList("GET"));
configuration.setAllowedHeaders(Collections.singletonList("*"));
source.registerCorsConfiguration("/**", configuration);
return source;
After making these changes, restart your API and verify your React UI can talk to it. Pretty
slick, eh?
HttpServletRequest.getRemoteUser()
HttpServletRequest.getUserPrincipal()
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 25/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
Once you have the Principal , you can get details about the user, including their roles
(a.k.a., authorities).
Please see Spring Security’s Servlet API integration documentation for more information.
Edit pom.xml to add the Pac4j libraries you’ll need to complete this section.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 26/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
<properties>
...
<pac4j-j2e.version>4.0.0</pac4j-j2e.version>
<pac4j.version>3.0.0</pac4j.version>
</properties>
<dependencies>
...
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>j2e-pac4j</artifactId>
<version>${pac4j-j2e.version}</version>
</dependency>
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-oidc</artifactId>
<version>${pac4j.version}</version>
</dependency>
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-http</artifactId>
<version>${pac4j.version}</version>
</dependency>
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-jwt</artifactId>
<version>${pac4j.version}</version>
</dependency>
</dependencies>
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 27/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
package com.okta.developer;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "corsFilter")
@Override
response.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");
response.addHeader("Access-Control-Allow-Methods", "GET");
response.addHeader("Access-Control-Allow-Headers", "*");
// For HTTP OPTIONS verb/method reply with ACCEPTED status code -- per CORS handshake
if (request.getMethod().equals("OPTIONS")) {
response.setStatus(HttpServletResponse.SC_ACCEPTED);
return;
chain.doFilter(request, response);
@Override
@Override
package com.okta.developer;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.pac4j.core.client.Clients;
import org.pac4j.core.client.direct.AnonymousClient;
import org.pac4j.core.config.Config;
import org.pac4j.core.config.ConfigFactory;
import org.pac4j.core.credentials.TokenCredentials;
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 28/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
import org.pac4j.core.profile.CommonProfile;
import org.pac4j.http.client.direct.HeaderClient;
import org.pac4j.jwt.config.signature.RSASignatureConfiguration;
import org.pac4j.jwt.credentials.authenticator.JwtAuthenticator;
import org.pac4j.jwt.util.JWKHelper;
import org.pac4j.oidc.client.OidcClient;
import org.pac4j.oidc.config.OidcConfiguration;
import org.pac4j.oidc.profile.OidcProfile;
import java.io.IOException;
import java.net.URL;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Override
oidcConfiguration.setClientId("{yourClientId}");
oidcConfiguration.setSecret("{yourClientSecret}");
oidcConfiguration.setDiscoveryURI("https://{yourOktaDomain}/oauth2/default/.well-known/
oidcConfiguration.setUseNonce(true);
profile.addRole("ROLE_USER");
return profile;
});
if (token != null) {
try {
// Get JWK
jwtAuthenticator.addSignatureConfiguration(new RSASignatureConfiguration(rs
CommonProfile profile = jwtAuthenticator.validateToken(token);
credentials.setUserProfile(profile);
} catch (IOException e) {
e.printStackTrace();
});
The oidcClient in the code above will make users log in to Okta if they try to directly
access your API. The headerClient sets up a resource server that authorizes the user
based on their access token.
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/jav
version="3.1">
<display-name>javaee-pac4j-demo</display-name>
<absolute-ordering/>
<filter-mapping>
<filter-name>corsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>callbackFilter</filter-name>
<filter-class>org.pac4j.j2e.filter.CallbackFilter</filter-class>
<init-param>
<param-name>defaultUrl</param-name>
<param-value>/</param-value>
</init-param>
<init-param>
<param-name>renewSession</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>multiProfile</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>callbackFilter</filter-name>
<url-pattern>/callback</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter>
<filter-name>OidcFilter</filter-name>
<filter-class>org.pac4j.j2e.filter.SecurityFilter</filter-class>
<i it >
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 30/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
<init-param>
<param-name>configFactory</param-name>
<param-value>com.okta.developer.SecurityConfigFactory</param-value>
</init-param>
<init-param>
<param-name>clients</param-name>
<param-value>oidcClient,headerClient</param-value>
</init-param>
<init-param>
<param-name>authorizers</param-name>
<param-value>securityHeaders</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>OidcFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
</web-app>
To visualize the user’s information a bit better, you’ll need to create a few more files. These
JSF-related files are copied from j2e-pac4j-cdi-demo.
NOTE: I tried to get j2e-pac4j-cdi-demo (with no web.xml ) running on TomEE, but it fails
with an error:
Filters cannot be added to context [] as the context has been initialised
. It does work when using the Payara Maven plugins.
package com.okta.developer;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.profile.ProfileManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.List;
/**
* JSF views such as facelets can reference this to view the contents of profiles.
*
*/
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 31/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
*/
@Named
@RequestScoped
@Inject
@Inject
public ProfileView() {
/**
* Gets the first profile (if it exists) contained in the profile manager.
*/
/**
*/
return profileManager.getAll(true);
@PostConstruct
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 32/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="/WEB-INF/template.xhtml">
<ui:define name="content">
<div class="ui-g">
<div class="ui-g-12">
<div class="ui-container">
<h1>Protected Area</h1>
</div>
<ui:include src="/WEB-INF/facelets/includes/pac4j-profiles-list.xhtml"/>
</div>
</div>
</ui:define>
</ui:composition>
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 33/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<div class="ui-container">
</h:panelGroup>
</div>
<h2>Profile Details</h2>
<ul>
</ul>
</h:panelGroup>
<ul>
<li><h:outputText value="#{role}"/></li>
</ui:repeat>
</ul>
</h:panelGroup>
<ul>
</ui:repeat>
</ul>
</h:panelGroup>
</h:panelGroup>
</ui:composition>
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 34/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<f:facet name="first">
</f:facet>
<ui:insert name="head"/>
</h:head>
<h:body styleClass="main-body">
<div class="layout-wrapper">
<div class="layout-main">
<ui:insert name="content"/>
</div>
</div>
</h:body>
</html>
After adding these files, rebuild your project and restart TomEE.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 35/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
If you’re wondering why the images aren’t stacked, it’s because I changed the beer list’s
JSX in the React app’s BeerList.tsx to be inline.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 36/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
<h2>Beer List</h2>
{beer.name}<br/>
<GiphyImage name={beer.name}/>
</span>
)}
David: The main focus right now is to create a version of Jakarta EE that is
compatible with Java EE 8. We hope to have that out by the end of the year.
After that’s released, we’ll start working on Jakarta EE 9 and iterating as
needed.
Jakarta EE has a working group that decides the direction of the platform.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 37/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
As I mentioned previously, most of the Java tutorials we have on this blog show how to use
Spring Boot. In case you’re interested in learning Spring Boot, here are some tutorials I’ve
written that will show you the gist of things.
If you’re new to OIDC, I’d recommend you check out the following posts:
For more about Java REST APIs and TomEE, I recommend these sources:
If you’ve made it this far, I suspect you might be interested in seeing future blog posts.
Follow me and my whole team on Twitter, like us on Facebook, or check out our YouTube
channel. For questions, please leave a comment below, or post it to our Developer Forums.
Matt Raible
Matt Raible is a well-known figure in the Java community and has been building web
applications for most of his adult life. For over 20 years, he has helped developers learn
and adopt open source frameworks and use them effectively. He's a web developer, Java
Champion, and Developer Advocate at Okta. Matt has been a speaker at many
conferences worldwide, including Devoxx Belgium, Devoxx France, Jfokus, and Devnexus.
He is the author of The JHipster Mini-Book, Spring Live, and contributed to Pro JSP. He is
frequent contributor to open source and a member of the JHipster development team. You
can find him online @mraible and raibledesigns.com.
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 38/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
Okta Developer Blog Comment Policy
We welcome relevant and respectful comments. Off-topic comments may be removed.
LOG IN WITH
OR SIGN UP WITH DISQUS ?
Name
⛺
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 39/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
△ ▽ • Reply • Share ›
⛺
error when i click Login on React App, after setup backend as pac4j and frontend
react js and i also added client_id,issure_id and domain, but may be i am doing
something wrong in okta side
△ ▽ • Reply • Share ›
When you get this error, it means that the redirect URIs in your app don't match
what you're passing in. In this case, you're passing in
"http://localhost:3000/implicit/callback". I can see it in your browser's address
bar. If you add this URL to your app's redirect URIs, it should work.
△ ▽ • Reply • Share ›
I am try to implement okta SSO using java spring without spring boot.
For e.g.
1) JwtFilter doesn't contains logic to redirect to login page if authorization is null, how it
work, in my case it is keep on getting loop for some time, as initial load multiple .js file
I tried using spring security, it is not working as I see compilation error for
SecurityConfiguration, below method defined twice without overload.
@Bean
.map(this::getRegistration)
.filter(Objects::nonNull)
.collect(Collectors.toList());
@Bean
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 40/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
}
△ ▽ • Reply • Share ›
The repo's README has instructions on how to configure it to work with your
Okta org.
△ ▽ • Reply • Share ›
I have done the procedures under the heading "Protect Your Java REST API with JWT
Verifier". But I got the error in browser developer console. I think I got some issues with
filter procedures you have mentioned. The error is like this "Cross-Origin Request
Blocked: The Same Origin Policy disallows reading the remote resource at
http://localhost:8080/good-beers. (Reason: CORS request did not succeed)". Any help
would be appreciable.
△ ▽ • Reply • Share ›
Hello Melvin, it sounds like your CorsFilter isn't getting invoked. Did you make
sure and create a web.xml and add it? You might try comparing your code with
the jwt-verifier branch on GitHub.
△ ▽ • Reply • Share ›
⛺
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 41/43
10/11/21, 6:37 PM Build a Java REST API with Java EE and OIDC | Okta Developer
Thanks Matt,
I have checked the github codes but I got problems like "missing token
‘authorization’ in CORS header " and "Invalid value for 'client_id'
parameter.". I have rechecked the client id parameter but it still the
same. I'm here uploading the developer console. Please check.
△ ▽ • Reply • Share ›
Did you change the code from GitHub to use your Okta tenant?
The settings in the code on GitHub won't work because I
regularly delete apps on Okta after I post the code (as a security
measure). The getting started instructions (or this blog post) will
show you how to setup an app on Okta.
△ ▽ • Reply • Share ›
I think I have followed all your steps correctly. I have changed the
clientId and issuer url in JwtFilter and App.tsx with my app
created in okta. Is anything need to change. Anyway what I want
is I have an application having angular js 1.2 as front end and
java rest webservice and spring 2 as back end Can you please
Auth0 platform
O K TA . C O M
HELP CENTER
https://developer.okta.com/blog/2018/09/12/secure-java-ee-rest-api 43/43