KEYCLOAK-9836 Deprecate keycloak-servlet-oauth-clien

This commit is contained in:
mposolda 2019-03-27 20:02:04 +01:00 committed by Bruno Oliveira da Silva
parent 2fa2437555
commit a516a795a2
30 changed files with 16 additions and 1254 deletions

View file

@ -25,6 +25,9 @@ import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
* @deprecated Class is deprecated and may be removed in the future. If you want to maintain this class for Keycloak community, please
* contact Keycloak team on keycloak-dev mailing list. You can fork it into your github repository and
* Keycloak team will reference it from "Keycloak Extensions" page.
*/
public class KeycloakDeploymentDelegateOAuthClient extends AbstractOAuthClient {

View file

@ -51,7 +51,11 @@ import java.security.SecureRandom;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
* @deprecated Class is deprecated and may be removed in the future. If you want to maintain this class for Keycloak community, please
* contact Keycloak team on keycloak-dev mailing list. You can fork it into your github repository and
* Keycloak team will reference it from "Keycloak Extensions" page.
*/
@Deprecated
public class ServletOAuthClient extends KeycloakDeploymentDelegateOAuthClient {
// https://tools.ietf.org/html/rfc7636#section-4

View file

@ -26,6 +26,9 @@ import java.io.InputStream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
* @deprecated Class is deprecated and may be removed in the future. If you want to maintain this class for Keycloak community, please
* contact Keycloak team on keycloak-dev mailing list. You can fork it into your github repository and
* Keycloak team will reference it from "Keycloak Extensions" page.
*/
public class ServletOAuthClientBuilder {

View file

@ -18,8 +18,6 @@ machine on the network or Internet.
* **admin-access-app** A WAR application that does remote REST login to admin console to obtain a list of realm roles from Admin REST API
* **angular-product-app** An Angular JS pure HTML5/Javascript application.
* **database-service** JAX-RS services authenticated by bearer tokens only. The customer and product app invoke on it to get data
* **third-party** Simple WAR that obtain a bearer token using OAuth2 using browser redirects to the auth-server.
* **third-party-cdi** Simple CDI/JSF WAR that obtain a bearer token using OAuth2 using browser redirects to the auth-server.
The UI of each of these applications is very crude and exists just to show our OAuth2 implementation in action.
@ -160,17 +158,7 @@ If you click on the logout link of either of the product or customer app, you'll
The example also shows different methods of client authentication. The customer-portal example is using traditional authentication with client_id and client_secret,
but the product-portal example is using client authentication with JWT signed by client private key, which is retrieved from the keystore file inside the product-portal WAR.
Step 6: Traditional OAuth2 Example
----------------------------------
The customer and product apps are logins. The third-party app is the traditional OAuth2 usecase of a client wanting
to get permission to access a user's data. To run this example open
[http://localhost:8080/oauth-client](http://localhost:8080/oauth-client)
If you are already logged in, you will not be asked for a username and password, but you will be redirected to
an oauth grant page. This page asks you if you want to grant certain permissions to the third-part app.
Step 7: Try the CLI Example
Step 6: Try the CLI Example
---------------------------
To try the CLI example run the following commands:
@ -183,7 +171,7 @@ The CLI example has two alternative methods for login. When a browser is availab
temporary web server on a free port. If a browser is not available the URL to login is displayed on the CLI. The user can copy this URL to another computer that has a browser available. The code
is displayed to the user after login and the user has to copy this code back to the application.
Step 8: Admin REST API
Step 7: Admin REST API
----------------------------------
Keycloak has a Admin REST API. This example shows an application making a remote direct login to Keycloak to obtain a token
then using that token to access the Admin REST API.
@ -193,7 +181,7 @@ then using that token to access the Admin REST API.
If you are already logged in, you will not be asked for a username and password, but you will be redirected to
an oauth grant page. This page asks you if you want to grant certain permissions to the third-part app.
Step 9: Angular JS Example
Step 8: Angular JS Example
----------------------------------
An Angular JS example using Keycloak to secure it.
@ -202,7 +190,7 @@ An Angular JS example using Keycloak to secure it.
If you are already logged in, you will not be asked for a username and password, but you will be redirected to
an oauth grant page. This page asks you if you want to grant certain permissions to the third-part app.
Step 10: Pure HTML5/Javascript Example
Step 9: Pure HTML5/Javascript Example
----------------------------------
An pure HTML5/Javascript example using Keycloak to secure it.
@ -211,7 +199,7 @@ An pure HTML5/Javascript example using Keycloak to secure it.
If you are already logged in, you will not be asked for a username and password, but you will be redirected to
an oauth grant page. This page asks you if you want to grant certain permissions to the third-part app.
Step 11: Service Account Example
Step 10: Service Account Example
================================
An example for retrieve service account dedicated to the Client Application itself (not to any user).
@ -219,7 +207,7 @@ An example for retrieve service account dedicated to the Client Application itse
Client authentication is done with OAuth2 Client Credentials Grant in out-of-bound request (Not Keycloak login screen displayed) .
Step 12: Offline Access Example
Step 11: Offline Access Example
===============================
An example for retrieve offline token, which is then saved to the database and can be used by application anytime later. Offline token
is valid even if user is already logged out from SSO. Server restart also won't invalidate offline token. Offline token can be revoked by the user in

View file

@ -41,8 +41,6 @@
<module>admin-access-app</module>
<module>angular-product-app</module>
<module>database-service</module>
<module>third-party</module>
<module>third-party-cdi</module>
<module>service-account</module>
<module>offline-access-app</module>
</modules>

View file

@ -1,98 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-examples-demo-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>5.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.keycloak.example.demo</groupId>
<artifactId>oauth-client-cdi-example</artifactId>
<packaging>war</packaging>
<name>Simple OAuth Client Using CDI and JSF</name>
<description/>
<dependencies>
<dependency>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0.SP1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.faces</groupId>
<artifactId>jboss-jsf-api_2.3_spec</artifactId>
<version>2.3.9.SP01</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-oauth-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>oauth-client-cdi</finalName>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -1,68 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.example.oauth;
import org.jboss.logging.Logger;
import org.keycloak.servlet.ServletOAuthClient;
import org.keycloak.servlet.ServletOAuthClientBuilder;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@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);
}
}
ServletOAuthClientBuilder.build(is, oauthClient);
logger.info("OAuth client configured and started");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
oauthClient.stop();
logger.info("OAuth client stopped");
}
}

View file

@ -1,58 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.example.oauth;
import org.keycloak.servlet.ServletOAuthClient;
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;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class CDIResourcesProducer {
@Produces
@RequestScoped
public FacesContext produceFacesContext() {
return FacesContext.getCurrentInstance();
}
@Produces
@RequestScoped
@ServletRequestQualifier
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();
}
}

View file

@ -1,129 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.apache.http.impl.client.DefaultHttpClient;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.common.util.UriUtils;
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
* @version $Revision: 1 $
*/
@ApplicationScoped
@Named("databaseClient")
public class DatabaseClient {
@Inject
@ServletRequestQualifier
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<String> {}
public void sendCustomersRequest() {
List<String> customers = sendRequestToDBApplication(getBaseUrl() + "/database/customers");
userData.setCustomers(customers);
}
public void sendProductsRequest() {
List<String> products = sendRequestToDBApplication(getBaseUrl() + "/database/products");
userData.setProducts(products);
}
protected List<String> sendRequestToDBApplication(String dbUri) {
HttpClient client = new DefaultHttpClient();
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;
}
}
public String getBaseUrl() {
KeycloakSecurityContext session = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
return UriUtils.getOrigin(request.getRequestURL().toString());
}
}

View file

@ -1,51 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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 <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@RequestScoped
@Named("messagesChecker")
public class MessagesChecker {
@Inject
@ServletRequestQualifier
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;
}
}

View file

@ -1,79 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.example.oauth;
import org.keycloak.OAuth2Constants;
import org.keycloak.adapters.ServerRequest;
import org.keycloak.servlet.ServletOAuthClient;
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 java.io.IOException;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@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<String, String[]> reqParams = request.getParameterMap();
if (reqParams.containsKey(OAuth2Constants.CODE)) {
try {
String accessToken = oauthClient.getBearerToken(request).getToken();
userData.setAccessToken(accessToken);
} catch (ServerRequest.HttpFailure e) {
throw new ServletException(e);
}
} else if (reqParams.containsKey(OAuth2Constants.ERROR)) {
String oauthError = reqParams.get(OAuth2Constants.ERROR)[0];
request.setAttribute(OAUTH_ERROR_ATTR, oauthError);
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}

View file

@ -1,35 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.example.oauth;
import javax.inject.Qualifier;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* This is needed to have same code working in AS7 and Wildfly. In Wildfly is HttpServletRequest injected automatically, in AS7 it's not
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
public @interface ServletRequestQualifier {
}

View file

@ -1,79 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.example.oauth;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import java.io.Serializable;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@SessionScoped
@Named("userData")
public class UserData implements Serializable {
private String accessToken;
private List<String> products;
private List<String> 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<String> getProducts() {
return products;
}
public void setProducts(List<String> products) {
this.products = products;
}
public boolean isHasProducts() {
return products != null;
}
public List<String> getCustomers() {
return customers;
}
public void setCustomers(List<String> customers) {
this.customers = customers;
}
public boolean isHasCustomers() {
return customers != null;
}
}

View file

@ -1,23 +0,0 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- Marker file indicating CDI should be enabled -->
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

View file

@ -1,23 +0,0 @@
<?xml version="1.0"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- Marker file indicating JSF should be enabled -->
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
</faces-config>

View file

@ -1,31 +0,0 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<jboss-deployment-structure>
<deployment>
<dependencies>
<!-- the Demo code uses classes in these modules. These are optional to import if you are not using
Apache Http Client or the HttpClientBuilder that comes with the adapter core -->
<module name="org.apache.httpcomponents"/>
<module name="org.keycloak.keycloak-servlet-oauth-client"/>
<module name="org.keycloak.keycloak-adapter-spi"/>
<module name="org.keycloak.keycloak-adapter-core"/>
<module name="org.keycloak.keycloak-common"/>
<module name="org.keycloak.keycloak-core"/>
</dependencies>
</deployment>
</jboss-deployment-structure>

View file

@ -1,9 +0,0 @@
{
"realm" : "demo",
"resource" : "third-party",
"auth-server-url" : "/auth",
"ssl-required" : "external",
"credentials" : {
"secret": "password"
}
}

View file

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<module-name>oauth-client-cdi</module-name>
<!--
<security-constraint>
<web-resource-collection>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
-->
</web-app>

View file

@ -1,55 +0,0 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
>
<body>
<h1>Third Party App That Pulls Data Using OAuth</h1>
<h:form>
#{userData.accessTokenAvailabilityMessage}
<br />
<h:commandButton id="retrieve_token" value="Retrieve/refresh access token" action="#{databaseClient.retrieveAccessToken}"/>
<h:commandButton id="products_request" value="Load products list" action="#{databaseClient.sendProductsRequest}"/>
<h:commandButton id="customers_request" value="Load customers list" action="#{databaseClient.sendCustomersRequest}"/>
</h:form>
<ui:fragment rendered="#{userData.hasProducts}">
<hr />
<h3>Products data available</h3>
<ui:repeat value="#{userData.products}" var="product">
#{product}<br/>
</ui:repeat>
</ui:fragment>
<ui:fragment rendered="#{userData.hasCustomers}">
<hr />
<h3>Customers data available</h3>
<ui:repeat value="#{userData.customers}" var="customer">
#{customer}<br/>
</ui:repeat>
</ui:fragment>
<div style="color: red">
#{messagesChecker.checkMessage}
<h:messages globalOnly="true"/>
</div>
</body>
</html>

View file

@ -1,22 +0,0 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<html>
<head>
<meta http-equiv="Refresh" content="0; URL=client.jsf">
</head>
</html>

View file

@ -1,81 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-examples-demo-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>5.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.keycloak.example.demo</groupId>
<artifactId>oauth-client-example</artifactId>
<packaging>war</packaging>
<name>Simple OAuth Client</name>
<description/>
<dependencies>
<dependency>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-oauth-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>oauth-client</finalName>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -1,70 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.example.oauth;
import org.keycloak.servlet.ServletOAuthClient;
import org.keycloak.servlet.ServletOAuthClientBuilder;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* 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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Bootstrap implements ServletContextListener {
private ServletOAuthClient client;
@Override
public void contextInitialized(ServletContextEvent sce) {
client = new ServletOAuthClient();
ServletContext context = sce.getServletContext();
configureClient(context);
context.setAttribute(ServletOAuthClient.class.getName(), client);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
client.stop();
}
private void configureClient(ServletContext context) {
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);
}
}
client = ServletOAuthClientBuilder.build(is);
}
}

View file

@ -1,121 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.apache.http.impl.client.DefaultHttpClient;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.ServerRequest;
import org.keycloak.common.util.UriUtils;
import org.keycloak.representations.AccessTokenResponse;
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ProductDatabaseClient {
public static class Failure extends Exception {
private int status;
public Failure(int status) {
this.status = status;
}
public int getStatus() {
return status;
}
}
public static void redirect(HttpServletRequest request, HttpServletResponse response) {
// The ServletOAuthClient is obtained by getting a context attribute
// that is set in the Bootstrap context listener 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. You can also take a look at third-party-cdi example
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<String> {}
public static AccessTokenResponse getTokenResponse(HttpServletRequest request) {
// The ServletOAuthClient is obtained by getting a context attribute
// that is set in the Bootstrap context listener 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. You can also take a look at third-party-cdi example
ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
try {
return oAuthClient.getBearerToken(request);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ServerRequest.HttpFailure failure) {
throw new RuntimeException(failure);
}
}
public static List<String> getProducts(HttpServletRequest request, String accessToken) throws Failure {
KeycloakSecurityContext session = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
// The ServletOAuthClient is obtained by getting a context attribute
// that is set in the Bootstrap context listener 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. You can also take a look at third-party-cdi example
ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(UriUtils.getOrigin(request.getRequestURL().toString()) + "/database/products");
get.addHeader("Authorization", "Bearer " + accessToken);
try {
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() != 200) {
throw new Failure(response.getStatusLine().getStatusCode());
}
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);
}
}
}

View file

@ -1,31 +0,0 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<jboss-deployment-structure>
<deployment>
<dependencies>
<!-- the Demo code uses classes in these modules. These are optional to import if you are not using
Apache Http Client or the HttpClientBuilder that comes with the adapter core -->
<module name="org.apache.httpcomponents"/>
<module name="org.keycloak.keycloak-servlet-oauth-client"/>
<module name="org.keycloak.keycloak-adapter-spi"/>
<module name="org.keycloak.keycloak-adapter-core"/>
<module name="org.keycloak.keycloak-common"/>
<module name="org.keycloak.keycloak-core"/>
</dependencies>
</deployment>
</jboss-deployment-structure>

View file

@ -1,10 +0,0 @@
{
"realm" : "demo",
"resource" : "third-party",
"auth-server-url" : "/auth",
"ssl-required" : "external",
"credentials" : {
"secret": "password"
},
"enable-pkce" : true
}

View file

@ -1,46 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<module-name>oauth-client</module-name>
<listener>
<listener-class>org.keycloak.example.oauth.Bootstrap</listener-class>
</listener>
<error-page>
<exception-type>java.lang.RuntimeException</exception-type>
<location>/error.jsp</location>
</error-page>
<!--
<security-constraint>
<web-resource-collection>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
-->
</web-app>

View file

@ -1 +0,0 @@
An error occurred. Click <a href="index.html"> to try again.

View file

@ -1,23 +0,0 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<html>
<body>
<h1>Third Party App That Pulls Data Using OAuth</h1>
<a href="redirect.jsp">Pull Data</a>
</body>
</html>

View file

@ -1,49 +0,0 @@
<%@ page import="org.keycloak.example.oauth.ProductDatabaseClient" %>
<%@ page import="org.keycloak.representations.AccessTokenResponse" %>
<%@ page import="org.keycloak.representations.IDToken" %>
<%@ page import="org.keycloak.servlet.ServletOAuthClient" %>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ page session="false" %>
<html>
<head>
<title>Pull Page</title>
</head>
<body>
<%
java.util.List<String> list = null;
try {
AccessTokenResponse tokenResponse = ProductDatabaseClient.getTokenResponse(request);
if (tokenResponse.getIdToken() != null) {
IDToken idToken = ServletOAuthClient.extractIdToken(tokenResponse.getIdToken());
if (idToken.getPreferredUsername() != null) {
out.println("<p>Username: " + idToken.getPreferredUsername() + "</p>");
}
if (idToken.getName() != null) {
out.println("<p>Full Name: " + idToken.getName() + "</p>");
}
if (idToken.getEmail() != null) {
out.println("<p>Email: " + idToken.getEmail() + "</p>");
}
}
list = ProductDatabaseClient.getProducts(request, tokenResponse.getToken());
} catch (ProductDatabaseClient.Failure failure) {
out.println("There was a failure processing request. You either didn't configure Keycloak properly, or maybe" +
"you just forgot to secure the database service?");
out.println("Status from database service invocation was: " + failure.getStatus());
return;
}
%>
<h2>Pulled Product Listing</h2>
<%
for (String prod : list)
{
out.print("<p>");
out.print(prod);
out.println("</p>");
}
%>
<br><br>
</body>
</html>

View file

@ -1,5 +0,0 @@
<%@ page import="org.keycloak.example.oauth.ProductDatabaseClient" %>
<%@ page session="false" %>
<%
ProductDatabaseClient.redirect(request, response);
%>