diff --git a/examples/as7-eap-demo/database-service/src/main/java/org/jboss/resteasy/example/oauth/CustomerService.java b/examples/as7-eap-demo/database-service/src/main/java/org/keycloak/example/oauth/CustomerService.java
similarity index 92%
rename from examples/as7-eap-demo/database-service/src/main/java/org/jboss/resteasy/example/oauth/CustomerService.java
rename to examples/as7-eap-demo/database-service/src/main/java/org/keycloak/example/oauth/CustomerService.java
index c6a0efc9db..a041476b44 100644
--- a/examples/as7-eap-demo/database-service/src/main/java/org/jboss/resteasy/example/oauth/CustomerService.java
+++ b/examples/as7-eap-demo/database-service/src/main/java/org/keycloak/example/oauth/CustomerService.java
@@ -1,4 +1,4 @@
-package org.jboss.resteasy.example.oauth;
+package org.keycloak.example.oauth;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
diff --git a/examples/as7-eap-demo/database-service/src/main/java/org/jboss/resteasy/example/oauth/DataApplication.java b/examples/as7-eap-demo/database-service/src/main/java/org/keycloak/example/oauth/DataApplication.java
similarity index 85%
rename from examples/as7-eap-demo/database-service/src/main/java/org/jboss/resteasy/example/oauth/DataApplication.java
rename to examples/as7-eap-demo/database-service/src/main/java/org/keycloak/example/oauth/DataApplication.java
index 673ad167e6..4a2ce3e565 100644
--- a/examples/as7-eap-demo/database-service/src/main/java/org/jboss/resteasy/example/oauth/DataApplication.java
+++ b/examples/as7-eap-demo/database-service/src/main/java/org/keycloak/example/oauth/DataApplication.java
@@ -1,4 +1,4 @@
-package org.jboss.resteasy.example.oauth;
+package org.keycloak.example.oauth;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
diff --git a/examples/as7-eap-demo/database-service/src/main/java/org/jboss/resteasy/example/oauth/ProductService.java b/examples/as7-eap-demo/database-service/src/main/java/org/keycloak/example/oauth/ProductService.java
similarity index 92%
rename from examples/as7-eap-demo/database-service/src/main/java/org/jboss/resteasy/example/oauth/ProductService.java
rename to examples/as7-eap-demo/database-service/src/main/java/org/keycloak/example/oauth/ProductService.java
index 8515dfe934..c7f8f4d208 100644
--- a/examples/as7-eap-demo/database-service/src/main/java/org/jboss/resteasy/example/oauth/ProductService.java
+++ b/examples/as7-eap-demo/database-service/src/main/java/org/keycloak/example/oauth/ProductService.java
@@ -1,4 +1,4 @@
-package org.jboss.resteasy.example.oauth;
+package org.keycloak.example.oauth;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
diff --git a/examples/as7-eap-demo/third-party/pom.xml b/examples/as7-eap-demo/third-party/pom.xml
index 89372bcdf7..bda3d9f44c 100755
--- a/examples/as7-eap-demo/third-party/pom.xml
+++ b/examples/as7-eap-demo/third-party/pom.xml
@@ -21,6 +21,24 @@
1.0.1.Final
provided
+
+ javax.enterprise
+ cdi-api
+ 1.0-SP4
+ provided
+
+
+ org.jboss.spec.javax.faces
+ jboss-jsf-api_2.1_spec
+ 2.0.1.Final
+ provided
+
+
+ org.jboss.logging
+ jboss-logging
+ 3.1.2.GA
+ provided
+
org.keycloak
keycloak-servlet-oauth-client
diff --git a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/AppContextListener.java b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/AppContextListener.java
new file mode 100644
index 0000000000..f84019e530
--- /dev/null
+++ b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/AppContextListener.java
@@ -0,0 +1,57 @@
+package org.keycloak.example.oauth;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+
+import org.jboss.logging.Logger;
+import org.keycloak.servlet.ServletOAuthClient;
+import org.keycloak.servlet.ServletOAuthClientConfigLoader;
+
+/**
+ * @author Marek Posolda
+ */
+@WebListener
+public class AppContextListener implements ServletContextListener {
+
+ private static final Logger logger = Logger.getLogger(AppContextListener.class);
+
+ @Inject
+ private ServletOAuthClient oauthClient;
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ ServletContext context = sce.getServletContext();
+
+ InputStream is = null;
+ String path = context.getInitParameter("keycloak.config.file");
+ if (path == null) {
+ is = context.getResourceAsStream("/WEB-INF/keycloak.json");
+ } else {
+ try {
+ is = new FileInputStream(path);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ ServletOAuthClientConfigLoader loader = new ServletOAuthClientConfigLoader(is);
+ loader.initOAuthClientConfiguration(true);
+ loader.configureServletOAuthClient(oauthClient);
+
+ oauthClient.start();
+ logger.info("OAuth client configured and started");
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent sce) {
+ oauthClient.stop();
+ logger.info("OAuth client stopped");
+ }
+}
diff --git a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/Bootstrap.java b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/Bootstrap.java
deleted file mode 100755
index 121af39b0a..0000000000
--- a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/Bootstrap.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.keycloak.example.oauth;
-
-import org.keycloak.servlet.ServletOAuthClient;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import java.io.File;
-import java.io.FileInputStream;
-import java.security.KeyStore;
-
-/**
- * Stupid init code to load up the truststore so we can make appropriate SSL connections
- * You really should use a better way of initializing this stuff.
- *
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class Bootstrap implements ServletContextListener {
-
- private ServletOAuthClient client;
-
- private static KeyStore loadKeyStore(String filename, String password) throws Exception {
- KeyStore trustStore = KeyStore.getInstance(KeyStore
- .getDefaultType());
- File truststoreFile = new File(filename);
- FileInputStream trustStream = new FileInputStream(truststoreFile);
- trustStore.load(trustStream, password.toCharArray());
- trustStream.close();
- return trustStore;
- }
-
- @Override
- public void contextInitialized(ServletContextEvent sce) {
- client = new ServletOAuthClient();
-/*
- // hardcoded, WARNING, you should really have a better way of doing this
- // configuration. Either use something like Spring or CDI, or even pull
- // config vales from context-params
- String truststorePath = "${jboss.server.config.dir}/client-truststore.ts";
- String truststorePassword = "password";
- truststorePath = EnvUtil.replace(truststorePath);
- KeyStore truststore = null;
- try
- {
- truststore = loadKeyStore(truststorePath, truststorePassword);
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
- client.setTruststore(truststore);
- */
- client.setClientId("third-party");
- client.setPassword("password");
- client.setAuthUrl("http://localhost:8080/auth-server/rest/realms/demo/tokens/login");
- client.setCodeUrl("http://localhost:8080/auth-server/rest/realms/demo/tokens/access/codes");
- client.start();
- sce.getServletContext().setAttribute(ServletOAuthClient.class.getName(), client);
-
-
- }
-
- @Override
- public void contextDestroyed(ServletContextEvent sce) {
- client.stop();
- }
-}
diff --git a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/CDIResourcesProducer.java b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/CDIResourcesProducer.java
new file mode 100644
index 0000000000..daffcc0e1e
--- /dev/null
+++ b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/CDIResourcesProducer.java
@@ -0,0 +1,40 @@
+package org.keycloak.example.oauth;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Produces;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.keycloak.servlet.ServletOAuthClient;
+
+/**
+ * @author Marek Posolda
+ */
+public class CDIResourcesProducer {
+
+ @Produces
+ @RequestScoped
+ public FacesContext produceFacesContext() {
+ return FacesContext.getCurrentInstance();
+ }
+
+ @Produces
+ @RequestScoped
+ public HttpServletRequest produceServletRequest() {
+ return (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
+ }
+
+ @Produces
+ @RequestScoped
+ public HttpServletResponse produceServletResponse() {
+ return (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
+ }
+
+ @Produces
+ @ApplicationScoped
+ public ServletOAuthClient produceOAuthClient() {
+ return new ServletOAuthClient();
+ }
+}
diff --git a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/DatabaseClient.java b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/DatabaseClient.java
new file mode 100755
index 0000000000..004e218a47
--- /dev/null
+++ b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/DatabaseClient.java
@@ -0,0 +1,103 @@
+package org.keycloak.example.oauth;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.TokenGrantRequest;
+import org.keycloak.servlet.ServletOAuthClient;
+import org.keycloak.util.JsonSerialization;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Bill Burke
+ * @author Marek Posolda
+ * @version $Revision: 1 $
+ */
+@ApplicationScoped
+@Named("databaseClient")
+public class DatabaseClient {
+
+ @Inject
+ private HttpServletRequest request;
+
+ @Inject
+ private HttpServletResponse response;
+
+ @Inject
+ private FacesContext facesContext;
+
+ @Inject
+ private ServletOAuthClient oauthClient;
+
+ @Inject
+ private UserData userData;
+
+ private static final Logger logger = Logger.getLogger(DatabaseClient.class);
+
+ public void retrieveAccessToken() {
+ try {
+ oauthClient.redirectRelative("client.jsf", request, response);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ static class TypedList extends ArrayList {}
+
+ public void sendCustomersRequest() {
+ List customers = sendRequestToDBApplication("http://localhost:8080/database/customers");
+ userData.setCustomers(customers);
+ }
+
+ public void sendProductsRequest() {
+ List products = sendRequestToDBApplication("http://localhost:8080/database/products");
+ userData.setProducts(products);
+ }
+
+ protected List sendRequestToDBApplication(String dbUri) {
+ HttpClient client = oauthClient.getClient();
+ HttpGet get = new HttpGet(dbUri);
+ try {
+
+ if (userData.isHasAccessToken()) {
+ get.addHeader("Authorization", "Bearer " + userData.getAccessToken());
+ }
+
+ HttpResponse response = client.execute(get);
+ switch (response.getStatusLine().getStatusCode()) {
+ case 200: HttpEntity entity = response.getEntity();
+ InputStream is = entity.getContent();
+ try {
+ return JsonSerialization.readValue(is, TypedList.class);
+ } finally {
+ is.close();
+ }
+ case 401: facesContext.addMessage(null, new FacesMessage("Status: 401. Request not authenticated! You need to retrieve access token first."));
+ break;
+ case 403: facesContext.addMessage(null, new FacesMessage("Status: 403. Access token has insufficient privileges"));
+ break;
+ default: facesContext.addMessage(null, new FacesMessage("Status: " + response.getStatusLine() + ". Not able to retrieve data. See log for details"));
+ logger.warn("Error occured. Status: " + response.getStatusLine());
+ }
+
+ return null;
+ } catch (IOException e) {
+ e.printStackTrace();
+ facesContext.addMessage(null, new FacesMessage("Unknown error. See log for details"));
+ return null;
+ }
+ }
+}
diff --git a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/MessagesChecker.java b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/MessagesChecker.java
new file mode 100644
index 0000000000..59bb57cf12
--- /dev/null
+++ b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/MessagesChecker.java
@@ -0,0 +1,33 @@
+package org.keycloak.example.oauth;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * This is needed because Faces context is not available in HTTP filters
+ *
+ * @author Marek Posolda
+ */
+@RequestScoped
+@Named("messagesChecker")
+public class MessagesChecker {
+
+ @Inject
+ private HttpServletRequest request;
+
+ @Inject
+ private FacesContext facesContext;
+
+ public String getCheckMessage() {
+ String oauthError = (String)request.getAttribute(RefreshTokenFilter.OAUTH_ERROR_ATTR);
+ if (oauthError != null) {
+ facesContext.addMessage(null, new FacesMessage("OAuth error occured: " + oauthError));
+ }
+
+ return null;
+ }
+}
diff --git a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
deleted file mode 100755
index 2b4cbd5c72..0000000000
--- a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.keycloak.example.oauth;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.keycloak.adapters.TokenGrantRequest;
-import org.keycloak.servlet.ServletOAuthClient;
-import org.keycloak.util.JsonSerialization;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class ProductDatabaseClient {
- public static void redirect(HttpServletRequest request, HttpServletResponse response) {
- // This is really the worst code ever. The ServletOAuthClient is obtained by getting a context attribute
- // that is set in the Bootstrap context listenr in this project.
- // You really should come up with a better way to initialize
- // and obtain the ServletOAuthClient. I actually suggest downloading the ServletOAuthClient code
- // and take a look how it works.
- ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
- try {
- oAuthClient.redirectRelative("pull_data.jsp", request, response);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- static class TypedList extends ArrayList {}
-
- public static List getProducts(HttpServletRequest request) {
- // This is really the worst code ever. The ServletOAuthClient is obtained by getting a context attribute
- // that is set in the Bootstrap context listenr in this project.
- // You really should come up with a better way to initialize
- // and obtain the ServletOAuthClient. I actually suggest downloading the ServletOAuthClient code
- // and take a look how it works.
- ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
- String token = null;
- try {
- token = oAuthClient.getBearerToken(request);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } catch (TokenGrantRequest.HttpFailure failure) {
- throw new RuntimeException(failure);
- }
-
- HttpClient client = oAuthClient.getClient();
-
- HttpGet get = new HttpGet("http://localhost:8080/database/products");
- get.addHeader("Authorization", "Bearer " + token);
- try {
- HttpResponse response = client.execute(get);
- HttpEntity entity = response.getEntity();
- InputStream is = entity.getContent();
- try {
- return JsonSerialization.readValue(is, TypedList.class);
- } finally {
- is.close();
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/RefreshTokenFilter.java b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/RefreshTokenFilter.java
new file mode 100644
index 0000000000..7467959298
--- /dev/null
+++ b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/RefreshTokenFilter.java
@@ -0,0 +1,62 @@
+package org.keycloak.example.oauth;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.keycloak.adapters.TokenGrantRequest;
+import org.keycloak.servlet.ServletOAuthClient;
+
+/**
+ * @author Marek Posolda
+ */
+@WebFilter(value = "/client.jsf")
+public class RefreshTokenFilter implements Filter {
+
+ public static final String OAUTH_ERROR_ATTR = "oauthErrorAttr";
+
+ @Inject
+ private ServletOAuthClient oauthClient;
+
+ @Inject
+ private UserData userData;
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest request = (HttpServletRequest)req;
+ HttpServletResponse response = (HttpServletResponse)resp;
+ Map reqParams = request.getParameterMap();
+
+ if (reqParams.containsKey("code")) {
+ try {
+ String accessToken = oauthClient.getBearerToken(request);
+ userData.setAccessToken(accessToken);
+ } catch (TokenGrantRequest.HttpFailure e) {
+ throw new ServletException(e);
+ }
+ } else if (reqParams.containsKey("error")) {
+ String oauthError = reqParams.get("error")[0];
+ request.setAttribute(OAUTH_ERROR_ATTR, oauthError);
+ }
+
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy() {
+ }
+}
diff --git a/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/UserData.java b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/UserData.java
new file mode 100644
index 0000000000..6571b18f3a
--- /dev/null
+++ b/examples/as7-eap-demo/third-party/src/main/java/org/keycloak/example/oauth/UserData.java
@@ -0,0 +1,63 @@
+package org.keycloak.example.oauth;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+
+/**
+ * @author Marek Posolda
+ */
+@SessionScoped
+@Named("userData")
+public class UserData implements Serializable {
+
+ private String accessToken;
+ private List products;
+ private List customers;
+
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public void setAccessToken(String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ public boolean isHasAccessToken() {
+ return accessToken != null;
+ }
+
+ public String getAccessTokenAvailabilityMessage() {
+ StringBuilder builder = new StringBuilder("Access token ");
+ if (!isHasAccessToken()) {
+ builder.append("not ");
+ }
+ return builder.append("available!").toString();
+ }
+
+ public List getProducts() {
+ return products;
+ }
+
+ public void setProducts(List products) {
+ this.products = products;
+ }
+
+ public boolean isHasProducts() {
+ return products != null;
+ }
+
+ public List getCustomers() {
+ return customers;
+ }
+
+ public void setCustomers(List customers) {
+ this.customers = customers;
+ }
+
+ public boolean isHasCustomers() {
+ return customers != null;
+ }
+}
diff --git a/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/beans.xml b/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000000..c4feade019
--- /dev/null
+++ b/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,23 @@
+
+
+
+
\ No newline at end of file
diff --git a/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/faces-config.xml b/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000000..10787a09a9
--- /dev/null
+++ b/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/keycloak.json b/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/keycloak.json
new file mode 100644
index 0000000000..72f466db31
--- /dev/null
+++ b/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/keycloak.json
@@ -0,0 +1,9 @@
+{
+ "resource" : "third-party",
+ "auth-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/login",
+ "code-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/access/codes",
+ "ssl-not-required" : true,
+ "credentials" : {
+ "password" : "password"
+ }
+}
\ No newline at end of file
diff --git a/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/web.xml b/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/web.xml
index 958839db9f..d1762e2b00 100755
--- a/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/web.xml
+++ b/examples/as7-eap-demo/third-party/src/main/webapp/WEB-INF/web.xml
@@ -6,9 +6,6 @@
oauth-client
-
- org.keycloak.example.oauth.Bootstrap
-