Merge pull request #86 from patriot1burke/master

cors
This commit is contained in:
Bill Burke 2013-10-30 05:33:34 -07:00
commit bc3961af56
48 changed files with 912 additions and 107 deletions

View file

@ -192,6 +192,19 @@ module.factory('ApplicationCredentials', function($resource) {
});
});
module.factory('ApplicationOrigins', function($resource) {
return $resource('/auth-server/rest/saas/admin/realms/:realm/applications/:application/allowed-origins', {
realm : '@realm',
application : '@application'
}, {
update : {
method : 'PUT',
isArray : true
}
});
});
module.factory('Current', function($resource) {

View file

@ -1,5 +1,7 @@
package org.keycloak;
import org.keycloak.representations.SkeletonKeyToken;
import java.io.Serializable;
/**
@ -7,21 +9,27 @@ import java.io.Serializable;
* @version $Revision: 1 $
*/
public class SkeletonKeySession implements Serializable {
protected String token;
protected String tokenString;
protected SkeletonKeyToken token;
protected transient ResourceMetadata metadata;
public SkeletonKeySession() {
}
public SkeletonKeySession(String token, ResourceMetadata metadata) {
public SkeletonKeySession(String tokenString, SkeletonKeyToken token, ResourceMetadata metadata) {
this.tokenString = tokenString;
this.token = token;
this.metadata = metadata;
}
public String getToken() {
public SkeletonKeyToken getToken() {
return token;
}
public String getTokenString() {
return tokenString;
}
public ResourceMetadata getMetadata() {
return metadata;
}

View file

@ -67,7 +67,7 @@ public class JaxrsBearerTokenFilter implements ContainerRequestFilter {
try {
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata);
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, resourceMetadata);
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, token, resourceMetadata);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
String callerPrincipal = securityContext.getUserPrincipal() != null ? securityContext.getUserPrincipal().getName() : null;

View file

@ -4,10 +4,7 @@ import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.jboss.resteasy.jwt.JsonWebToken;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -57,6 +54,8 @@ public class SkeletonKeyToken extends JsonWebToken {
@JsonProperty("trusted-certs")
protected Set<String> trustedCertificates;
@JsonProperty("allowed-origins")
protected Set<String> allowedOrigins;
@JsonProperty("realm_access")
protected Access realmAccess;
@ -144,6 +143,14 @@ public class SkeletonKeyToken extends JsonWebToken {
return (SkeletonKeyToken) super.type(type);
}
public Set<String> getAllowedOrigins() {
return allowedOrigins;
}
public void setAllowedOrigins(Set<String> allowedOrigins) {
this.allowedOrigins = allowedOrigins;
}
public Access getRealmAccess() {
return realmAccess;
}

View file

@ -25,7 +25,7 @@ public class CustomerDatabaseClient
try
{
Response response = client.target("http://localhost:8080/database/customers").request()
.header(HttpHeaders.AUTHORIZATION, "Bearer " + session.getToken()).get();
.header(HttpHeaders.AUTHORIZATION, "Bearer " + session.getTokenString()).get();
return response.readEntity(new GenericType<List<String>>(){});
}
finally

View file

@ -4,7 +4,8 @@
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
"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,
"ssl-not-required" : true,
"expose-token" : true,
"credentials" : {
"password" : "password"
}

View file

@ -0,0 +1,38 @@
<!doctype html>
<html lang="en">
<body>
<script type="text/javascript">
console.log('here!!!!!');
var xhr1 = new XMLHttpRequest();
xhr1.open('GET', '/customer-portal/K_QUERY_BEARER_TOKEN');
xhr1.onreadystatechange = function () {
console.log('got here');
if (this.status == 200 && this.readyState == 4) {
var token = this.responseText;
console.log('Access token: ' + token);
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/database/customers');
xhr.withCredentials = true;
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.onreadystatechange = function () {
console.log('got auth success');
if (this.status == 200 && this.readyState == 4) {
console.log('db response: ' + this.responseText);
} else if (this.status != 200) {
console.log('there was an error:' + this.status);
}
};
xhr.send();
} else if (this.status != 200) {
console.log('there was an error on get bearer token:' + this.status);
}
};
xhr1.send();
</script>
</body>
</html>

View file

@ -1,5 +1,7 @@
{
"realm" : "demo",
"resource" : "database-service",
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
"enable-cors" : true
}

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-1</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.keycloak.example.as7.demo</groupId>
<artifactId>customer-portal-example</artifactId>
<packaging>war</packaging>
<name>Customer Portal - Secured via Valve</name>
<description/>
<repositories>
<repository>
<id>jboss</id>
<name>jboss repo</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-adapter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<finalName>customer-portal</finalName>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.4.Final</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,11 @@
<jboss-deployment-structure>
<deployment>
<!-- This allows you to define additional dependencies, it is the same as using the Dependencies: manifest attribute -->
<dependencies>
<module name="org.bouncycastle"/>
<module name="org.jboss.resteasy.resteasy-jaxrs" services="import"/>
<module name="org.jboss.resteasy.resteasy-jackson-provider" services="import"/>
<module name="org.jboss.resteasy.jose-jwt" />
</dependencies>
</deployment>
</jboss-deployment-structure>

View file

@ -0,0 +1,5 @@
<jboss-web>
<valve>
<class-name>org.keycloak.adapters.as7.OAuthManagedResourceValve</class-name>
</valve>
</jboss-web>

View file

@ -0,0 +1,12 @@
{
"realm" : "demo",
"resource" : "customer-portal",
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
"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,
"expose-token" : true,
"credentials" : {
"password" : "password"
}
}

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>customer-portal</module-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admins</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Customers</web-resource-name>
<url-pattern>/customers/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<!--
<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> -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>commerce</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
</web-app>

View file

@ -0,0 +1,11 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<title>Customer Admin Iterface</title>
</head>
<body bgcolor="#E3F6CE">
<h1>Customer Admin Interface</h1>
User <b><%=request.getUserPrincipal().getName()%></b> made this request.
</body>
</html>

View file

@ -0,0 +1,38 @@
<!doctype html>
<html lang="en">
<body>
<script type="text/javascript">
console.log('here!!!!!');
var xhr1 = new XMLHttpRequest();
xhr1.open('GET', '/customer-portal/K_QUERY_BEARER_TOKEN');
xhr1.onreadystatechange = function () {
console.log('got here');
if (this.status == 200 && this.readyState == 4) {
var token = this.responseText;
console.log('Access token: ' + token);
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/database/customers');
xhr.withCredentials = true;
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.onreadystatechange = function () {
console.log('got auth success');
if (this.status == 200 && this.readyState == 4) {
console.log('db response: ' + this.responseText);
} else if (this.status != 200) {
console.log('there was an error:' + this.status);
}
};
xhr.send();
} else if (this.status != 200) {
console.log('there was an error on get bearer token:' + this.status);
}
};
xhr1.send();
</script>
</body>
</html>

View file

@ -0,0 +1,27 @@
<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<title>Customer View Page</title>
</head>
<body bgcolor="#E3F6CE">
<%
String logoutUri = UriBuilder.fromUri("http://localhost:8080/auth-server/rest/realms/demo/tokens/logout")
.queryParam("redirect_uri", "http://localhost:8080/customer-portal").build().toString();
%>
<p>Goto: <a href="http://localhost:8080/product-portal">products</a> | <a href="<%=logoutUri%>">logout</a></p>
User <b><%=request.getUserPrincipal().getName()%></b> made this request.
<h2>Customer Listing</h2>
<%
java.util.List<String> list = org.jboss.resteasy.example.oauth.CustomerDatabaseClient.getCustomers(request);
for (String cust : list)
{
out.print("<p>");
out.print(cust);
out.println("</p>");
}
%>
<br><br>
</body>
</html>

View file

@ -0,0 +1,14 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
</head>
<body bgcolor="#E3F6CE">
<h1>Customer Portal</h1>
<p><a href="customers/view.jsp">Customer Listing</a></p>
<p><a href="admin/admin.html">Customer Admin Interface</a></p>
</body>
</html>

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-1</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.keycloak.example.as7.demo</groupId>
<artifactId>database-service</artifactId>
<packaging>war</packaging>
<name>JAX-RS Database Service Using OAuth Bearer Tokens</name>
<description/>
<url>http://maven.apache.org</url>
<repositories>
<repository>
<id>jboss</id>
<name>jboss repo</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-adapter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<finalName>database</finalName>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.4.Final</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,26 @@
package org.jboss.resteasy.example.oauth;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Path("customers")
public class CustomerService
{
@GET
@Produces("application/json")
public List<String> getCustomers()
{
ArrayList<String> rtn = new ArrayList<String>();
rtn.add("Bill Burke");
rtn.add("Ron Sigal");
rtn.add("Weinan Li");
return rtn;
}
}

View file

@ -0,0 +1,13 @@
package org.jboss.resteasy.example.oauth;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@ApplicationPath("/")
public class DataApplication extends Application
{
}

View file

@ -0,0 +1,26 @@
package org.jboss.resteasy.example.oauth;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Path("products")
public class ProductService
{
@GET
@Produces("application/json")
public List<String> getProducts()
{
ArrayList<String> rtn = new ArrayList<String>();
rtn.add("iphone");
rtn.add("ipad");
rtn.add("ipod");
return rtn;
}
}

View file

@ -0,0 +1,9 @@
<jboss-deployment-structure>
<deployment>
<!-- This allows you to define additional dependencies, it is the same as using the Dependencies: manifest attribute -->
<dependencies>
<module name="org.bouncycastle"/>
<module name="org.jboss.resteasy.jose-jwt" />
</dependencies>
</deployment>
</jboss-deployment-structure>

View file

@ -0,0 +1,5 @@
<jboss-web>
<valve>
<class-name>org.keycloak.adapters.as7.BearerTokenAuthenticatorValve</class-name>
</valve>
</jboss-web>

View file

@ -0,0 +1,7 @@
{
"realm" : "demo",
"resource" : "database-service",
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
"enable-cors" : true
}

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>database</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> -->
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>commerce</realm-name>
</login-config>
<security-role>
<role-name>user</role-name>
</security-role>
</web-app>

View file

@ -68,6 +68,7 @@
"enabled": true,
"adminUrl": "http://localhost:8080/customer-portal/j_admin_request",
"useRealmMappings": true,
"webOrigins" : [ "http://localhost1:8080"],
"credentials": [
{
"type": "password",

View file

@ -0,0 +1,123 @@
package org.keycloak.adapters.as7;
import org.apache.catalina.Container;
import org.apache.catalina.Session;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.SkeletonKeySession;
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
import org.keycloak.representations.SkeletonKeyToken;
import javax.management.ObjectName;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Set;
/**
* Pre-installed actions that must be authenticated
*
* Actions include:
*
* CORS Origin Check and Response headers
* K_QUERY_BEARER_TOKEN: Get bearer token from server for Javascripts CORS requests
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AuthenticatedActionsValve extends ValveBase {
private static final Logger log = Logger.getLogger(AuthenticatedActionsValve.class);
protected ManagedResourceConfig config;
public AuthenticatedActionsValve(ManagedResourceConfig config, Valve next, Container container, ObjectName controller) {
this.config = config;
if (next == null) throw new RuntimeException("WTF is next null?!");
setNext(next);
setContainer(container);
setController(controller);
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI());
SkeletonKeySession session = getSkeletonKeySession(request);
if (corsRequest(request, response, session)) return;
String requestUri = request.getRequestURI();
if (requestUri.endsWith("K_QUERY_BEARER_TOKEN")) {
queryBearerToken(request, response, session);
return;
}
getNext().invoke(request, response);
}
public SkeletonKeySession getSkeletonKeySession(Request request) {
SkeletonKeySession skSession = (SkeletonKeySession)request.getAttribute(SkeletonKeySession.class.getName());
if (skSession != null) return skSession;
Session session = request.getSessionInternal();
if (session != null) {
return (SkeletonKeySession) session.getNote(SkeletonKeySession.class.getName());
}
return null;
}
protected void queryBearerToken(Request request, Response response, SkeletonKeySession session) throws IOException, ServletException {
log.debugv("queryBearerToken {0}",request.getRequestURI());
if (abortTokenResponse(request, response, session)) return;
response.setContentType("text/plain");
response.getOutputStream().write(session.getTokenString().getBytes());
response.getOutputStream().flush();
}
protected boolean abortTokenResponse(Request request, Response response, SkeletonKeySession session) throws IOException {
if (session == null) {
log.debugv("session was null, sending back 401: {0}",request.getRequestURI());
response.sendError(401);
return true;
}
if (!config.isExposeToken()) {
response.setStatus(200);
return true;
}
if (!config.isCors() && request.getHeader("Origin") != null) {
response.setStatus(200);
return true;
}
return false;
}
protected boolean corsRequest(Request request, Response response, SkeletonKeySession session) throws IOException {
if (!config.isCors()) return false;
log.debugv("CORS enabled + request.getRequestURI()");
String origin = request.getHeader("Origin");
log.debugv("Origin: {0} uri: {1}", origin, request.getRequestURI());
if (session != null && origin != null) {
SkeletonKeyToken token = session.getToken();
Set<String> allowedOrigins = token.getAllowedOrigins();
if (log.isDebugEnabled()) {
for (String a : allowedOrigins) log.debug(" " + a);
}
if (allowedOrigins == null || (!allowedOrigins.contains("*") && !allowedOrigins.contains(origin))) {
if (allowedOrigins == null) {
log.debugv("allowedOrigins was null in token");
}
if (!allowedOrigins.contains("*") && !allowedOrigins.contains(origin)) {
log.debugv("allowedOrigins did not contain origin");
}
response.sendError(403);
return true;
}
log.debugv("returning origin: {0}", origin);
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Credentials", "true");
} else {
log.debugv("session or origin was null: {0}", request.getRequestURI());
}
return false;
}
}

View file

@ -49,11 +49,17 @@ public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
managedResourceConfigLoader.init(false);
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(remoteSkeletonKeyConfig, getNext(), getContainer(), getController());
setNext(actions);
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
log.debugv("{0} {1}", request.getMethod(), request.getRequestURI());
if (remoteSkeletonKeyConfig.isCors() && new CorsPreflightChecker(remoteSkeletonKeyConfig).checkCorsPreflight(request, response)) {
return;
}
super.invoke(request, response);
} finally {
ResteasyProviderFactory.clearContextData(); // to clear push of SkeletonKeySession
@ -63,7 +69,7 @@ public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements
@Override
protected boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
try {
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, !remoteSkeletonKeyConfig.isCancelPropagation(), true, remoteSkeletonKeyConfig.isUseResourceRoleMappings());
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, true, remoteSkeletonKeyConfig.isUseResourceRoleMappings());
if (bearer.login(request, response)) {
return true;
}

View file

@ -29,13 +29,11 @@ public class CatalinaBearerTokenAuthenticator {
protected String tokenString;
protected SkeletonKeyToken token;
private Principal principal;
protected boolean propagateToken;
protected boolean useResourceRoleMappings;
public CatalinaBearerTokenAuthenticator(ResourceMetadata resourceMetadata, boolean propagateToken, boolean challenge, boolean useResourceRoleMappings) {
public CatalinaBearerTokenAuthenticator(ResourceMetadata resourceMetadata, boolean challenge, boolean useResourceRoleMappings) {
this.resourceMetadata = resourceMetadata;
this.challenge = challenge;
this.propagateToken = propagateToken;
this.useResourceRoleMappings = useResourceRoleMappings;
}
@ -109,11 +107,9 @@ public class CatalinaBearerTokenAuthenticator {
principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles);
request.setUserPrincipal(principal);
request.setAuthType("OAUTH_BEARER");
if (propagateToken) {
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, resourceMetadata);
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
}
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, token, resourceMetadata);
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
return true;
}

View file

@ -0,0 +1,56 @@
package org.keycloak.adapters.as7;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.jboss.logging.Logger;
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CorsPreflightChecker {
private static final Logger log = Logger.getLogger(CorsPreflightChecker.class);
protected ManagedResourceConfig config;
public CorsPreflightChecker(ManagedResourceConfig config) {
this.config = config;
}
public boolean checkCorsPreflight(Request request, Response response) {
log.debugv("checkCorsPreflight {0}", request.getRequestURI());
if (!request.getMethod().equalsIgnoreCase("OPTIONS")) {
log.debug("checkCorsPreflight: not options ");
return false;
}
if (request.getHeader("Origin") == null) {
log.debug("checkCorsPreflight: no origin header");
return false;
}
log.debug("Preflight request returning");
response.setStatus(200);
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Credentials", "true");
String requestMethods = request.getHeader("Access-Control-Request-Method");
if (requestMethods != null) {
if (config.getCorsAllowedMethods() != null) {
requestMethods = config.getCorsAllowedMethods();
}
response.setHeader("Access-Control-Allow-Methods", requestMethods);
}
String allowHeaders = request.getHeader("Access-Control-Request-Headers");
if (allowHeaders != null) {
if (config.getCorsAllowedHeaders() != null) {
allowHeaders = config.getCorsAllowedHeaders();
}
response.setHeader("Access-Control-Allow-Headers", allowHeaders);
}
if (config.getCorsMaxAge() > -1) {
response.setHeader("Access-Control-Max-Age", Integer.toString(config.getCorsMaxAge()));
}
return true;
}
}

View file

@ -561,7 +561,7 @@ public class OAuthAuthenticationServerValve extends FormAuthenticator implements
public boolean bearer(Request request, HttpServletResponse response, boolean propagate) throws IOException {
if (request.getHeader("Authorization") != null) {
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, true, false, false);
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, false, false);
try {
if (bearer.login(request, response)) {
return true;
@ -582,7 +582,7 @@ public class OAuthAuthenticationServerValve extends FormAuthenticator implements
if (gp != null) {
SkeletonKeyToken token = buildToken(gp);
String stringToken = buildTokenString(realmPrivateKey, token);
SkeletonKeySession skSession = new SkeletonKeySession(stringToken, resourceMetadata);
SkeletonKeySession skSession = new SkeletonKeySession(stringToken, token, resourceMetadata);
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
request.getSessionInternal(true).setNote(SkeletonKeySession.class.getName(), skSession);

View file

@ -70,6 +70,7 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
managedResourceConfigLoader.init(true);
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
realmConfiguration = new RealmConfiguration();
String authUrl = remoteSkeletonKeyConfig.getAuthUrl();
if (authUrl == null) {
@ -91,11 +92,16 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
realmConfiguration.setClient(client);
realmConfiguration.setAuthUrl(UriBuilder.fromUri(authUrl).queryParam("client_id", resourceMetadata.getResourceName()));
realmConfiguration.setCodeUrl(client.target(tokenUrl));
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(remoteSkeletonKeyConfig, getNext(), getContainer(), getController());
setNext(actions);
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
if (remoteSkeletonKeyConfig.isCors() && new CorsPreflightChecker(remoteSkeletonKeyConfig).checkCorsPreflight(request, response)) {
return;
}
String requestURI = request.getDecodedRequestURI();
if (requestURI.endsWith("j_admin_request")) {
adminRequest(request, response);
@ -163,7 +169,7 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
protected void remoteLogout(JWSInput token, HttpServletResponse response) throws IOException {
try {
log.info("->> remoteLogout: ");
log.debug("->> remoteLogout: ");
LogoutAction action = JsonSerialization.fromBytes(LogoutAction.class, token.getContent());
if (action.isExpired()) {
log.warn("admin request failed, expired token");
@ -183,10 +189,10 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
}
String user = action.getUser();
if (user != null) {
log.info("logout of session for: " + user);
log.debug("logout of session for: " + user);
userSessionManagement.logout(user);
} else {
log.info("logout of all sessions");
log.debug("logout of all sessions");
userSessionManagement.logoutAll();
}
} catch (Exception e) {
@ -197,7 +203,7 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
}
protected boolean bearer(boolean challenge, Request request, HttpServletResponse response) throws LoginException, IOException {
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(realmConfiguration.getMetadata(), !remoteSkeletonKeyConfig.isCancelPropagation(), challenge, remoteSkeletonKeyConfig.isUseResourceRoleMappings());
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(realmConfiguration.getMetadata(), challenge, remoteSkeletonKeyConfig.isUseResourceRoleMappings());
if (bearer.login(request, response)) {
return true;
}
@ -212,7 +218,7 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
request.setUserPrincipal(principal);
request.setAuthType("OAUTH");
Session session = request.getSessionInternal();
if (session != null && !remoteSkeletonKeyConfig.isCancelPropagation()) {
if (session != null) {
SkeletonKeySession skSession = (SkeletonKeySession) session.getNote(SkeletonKeySession.class.getName());
if (skSession != null) {
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
@ -256,10 +262,8 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
Session session = request.getSessionInternal(true);
session.setPrincipal(principal);
session.setAuthType("OAUTH");
if (!remoteSkeletonKeyConfig.isCancelPropagation()) {
SkeletonKeySession skSession = new SkeletonKeySession(oauth.getTokenString(), realmConfiguration.getMetadata());
session.setNote(SkeletonKeySession.class.getName(), skSession);
}
SkeletonKeySession skSession = new SkeletonKeySession(oauth.getTokenString(), token, realmConfiguration.getMetadata());
session.setNote(SkeletonKeySession.class.getName(), skSession);
String username = token.getPrincipal();
log.debug("userSessionManage.login: " + username);

View file

@ -76,7 +76,7 @@ public class ServletOAuthLogin {
protected void sendRedirect(String url) {
try {
log.info("Sending redirect to: " + url);
log.debugv("Sending redirect to: {0}", url);
response.sendRedirect(url);
} catch (IOException e) {
throw new RuntimeException(e);
@ -175,7 +175,7 @@ public class ServletOAuthLogin {
return false;
}
// reset the cookie
log.info("** reseting application state cookie");
log.debug("** reseting application state cookie");
Cookie reset = new Cookie(realmInfo.getStateCookieName(), "");
reset.setPath(getDefaultCookiePath());
reset.setMaxAge(0);
@ -257,7 +257,7 @@ public class ServletOAuthLogin {
tokenString = tokenResponse.getToken();
try {
token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata());
log.info("Token Verification succeeded!");
log.debug("Token Verification succeeded!");
} catch (VerificationException e) {
log.error("failed verification of token");
sendError(Response.Status.FORBIDDEN.getStatusCode());

View file

@ -5,6 +5,7 @@ import org.codehaus.jackson.annotate.JsonPropertyOrder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -49,8 +50,16 @@ public class ManagedResourceConfig {
protected Map<String, String> credentials = new HashMap<String, String>();
@JsonProperty("connection-pool-size")
protected int connectionPoolSize;
@JsonProperty("cancel-propagation")
protected boolean cancelPropagation;
@JsonProperty("enable-cors")
protected boolean cors;
@JsonProperty("cors-max-age")
protected int corsMaxAge = -1;
@JsonProperty("cors-allowed-headers")
protected String corsAllowedHeaders;
@JsonProperty("cors-allowed-methods")
protected String corsAllowedMethods;
@JsonProperty("expose-token")
protected boolean exposeToken;
public boolean isUseResourceRoleMappings() {
return useResourceRoleMappings;
@ -184,14 +193,6 @@ public class ManagedResourceConfig {
this.connectionPoolSize = connectionPoolSize;
}
public boolean isCancelPropagation() {
return cancelPropagation;
}
public void setCancelPropagation(boolean cancelPropagation) {
this.cancelPropagation = cancelPropagation;
}
public String getAdminRole() {
return adminRole;
}
@ -199,4 +200,44 @@ public class ManagedResourceConfig {
public void setAdminRole(String adminRole) {
this.adminRole = adminRole;
}
public boolean isCors() {
return cors;
}
public void setCors(boolean cors) {
this.cors = cors;
}
public int getCorsMaxAge() {
return corsMaxAge;
}
public void setCorsMaxAge(int corsMaxAge) {
this.corsMaxAge = corsMaxAge;
}
public String getCorsAllowedHeaders() {
return corsAllowedHeaders;
}
public void setCorsAllowedHeaders(String corsAllowedHeaders) {
this.corsAllowedHeaders = corsAllowedHeaders;
}
public String getCorsAllowedMethods() {
return corsAllowedMethods;
}
public void setCorsAllowedMethods(String corsAllowedMethods) {
this.corsAllowedMethods = corsAllowedMethods;
}
public boolean isExposeToken() {
return exposeToken;
}
public void setExposeToken(boolean exposeToken) {
this.exposeToken = exposeToken;
}
}

View file

@ -5,6 +5,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.models.*;
import org.keycloak.representations.idm.*;
@ -13,6 +14,7 @@ import org.keycloak.representations.idm.*;
* @version $Revision: 1 $
*/
public class ApplicationManager {
protected Logger logger = Logger.getLogger(ApplicationManager.class);
protected RealmManager realmManager;
@ -21,6 +23,7 @@ public class ApplicationManager {
}
public ApplicationModel createApplication(RealmModel realm, RoleModel loginRole, ApplicationRepresentation resourceRep) {
logger.debug("************ CREATE APPLICATION: {0}" + resourceRep.getName());
ApplicationModel applicationModel = realm.addApplication(resourceRep.getName());
applicationModel.setEnabled(resourceRep.isEnabled());
applicationModel.setManagementUrl(resourceRep.getAdminUrl());
@ -44,6 +47,7 @@ public class ApplicationManager {
}
if (resourceRep.getWebOrigins() != null) {
for (String webOrigin : resourceRep.getWebOrigins()) {
logger.debug("Application: {0} webOrigin: {1}", resourceUser.getLoginName(), webOrigin);
resourceUser.addWebOrigin(webOrigin);
}
}

View file

@ -72,7 +72,7 @@ public class AuthenticationManager {
SkeletonKeyToken identityToken = createIdentityToken(realm, user.getLoginName());
String encoded = encodeToken(realm, identityToken);
boolean secureOnly = !realm.isSslNotRequired();
logger.info("creatingLoginCookie - name: " + cookieName + " path: " + cookiePath);
logger.debug("creatingLoginCookie - name: {0} path: {1}", cookieName, cookiePath);
NewCookie cookie = new NewCookie(cookieName, encoded, cookiePath, null, null, NewCookie.DEFAULT_MAX_AGE, secureOnly, true);
return cookie;
}
@ -93,7 +93,7 @@ public class AuthenticationManager {
public void expireIdentityCookie(RealmModel realm, UriInfo uriInfo) {
URI uri = RealmsResource.realmBaseUrl(uriInfo).build(realm.getId());
logger.info("Expiring identity cookie");
logger.debug("Expiring identity cookie");
String path = uri.getPath();
String cookieName = KEYCLOAK_IDENTITY_COOKIE;
expireCookie(cookieName, path);
@ -113,10 +113,10 @@ public class AuthenticationManager {
public void expireCookie(String cookieName, String path) {
HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
if (response == null) {
logger.info("can't expire identity cookie, no HttpResponse");
logger.debug("can't expire identity cookie, no HttpResponse");
return;
}
logger.info("Expiring cookie: " + cookieName + " path: " + path);
logger.debug("Expiring cookie: {0} path: {1}", cookieName, path);
NewCookie expireIt = new NewCookie(cookieName, "", path, null, "Expiring cookie", 0, false);
response.addNewCookie(expireIt);
}
@ -147,7 +147,7 @@ public class AuthenticationManager {
protected UserModel authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers, String cookieName) {
Cookie cookie = headers.getCookies().get(cookieName);
if (cookie == null) {
logger.info("authenticateCookie could not find cookie: " + cookieName);
logger.debug("authenticateCookie could not find cookie: {0}", cookieName);
return null;
}
@ -155,19 +155,19 @@ public class AuthenticationManager {
try {
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getId());
if (!token.isActive()) {
logger.info("identity cookie expired");
logger.debug("identity cookie expired");
expireIdentityCookie(realm, uriInfo);
return null;
}
UserModel user = realm.getUser(token.getPrincipal());
if (user == null || !user.isEnabled()) {
logger.info("Unknown user in identity cookie");
logger.debug("Unknown user in identity cookie");
expireIdentityCookie(realm, uriInfo);
return null;
}
return user;
} catch (VerificationException e) {
logger.info("Failed to verify identity cookie", e);
logger.debug("Failed to verify identity cookie", e);
expireIdentityCookie(realm, uriInfo);
}
return null;
@ -204,12 +204,12 @@ public class AuthenticationManager {
public AuthenticationStatus authenticateForm(RealmModel realm, UserModel user, MultivaluedMap<String, String> formData) {
if (user == null) {
logger.info("Not Authenticated! Incorrect user name");
logger.debug("Not Authenticated! Incorrect user name");
return AuthenticationStatus.INVALID_USER;
}
if (!user.isEnabled()) {
logger.info("Account is disabled, contact admin.");
logger.debug("Account is disabled, contact admin.");
return AuthenticationStatus.ACCOUNT_DISABLED;
}
@ -241,12 +241,12 @@ public class AuthenticationManager {
logger.warn("TOTP token not provided");
return AuthenticationStatus.MISSING_TOTP;
}
logger.info("validating TOTP");
logger.debug("validating TOTP");
if (!realm.validateTOTP(user, password, token)) {
return AuthenticationStatus.INVALID_CREDENTIALS;
}
} else {
logger.info("validating password for user: " + user.getLoginName());
logger.debug("validating password for user: " + user.getLoginName());
if (!realm.validatePassword(user, password)) {
return AuthenticationStatus.INVALID_CREDENTIALS;
}

View file

@ -30,7 +30,7 @@ public class ResourceAdminManager {
.build();
List<ApplicationModel> resources = realm.getApplications();
logger.info("logging out " + resources.size() + " resoures.");
logger.debug("logging out {0} resources ", resources.size());
for (ApplicationModel resource : resources) {
logoutResource(realm, resource, user, client);
}
@ -43,7 +43,7 @@ public class ResourceAdminManager {
String token = new TokenManager().encodeToken(realm, adminAction);
Form form = new Form();
form.param("token", token);
logger.info("logout user: " + user + " resource: " + resource.getName() + " url" + managementUrl);
logger.debug("logout user: {0} resource: {1} url: {2}", user, resource.getName(), managementUrl);
Response response = client.target(managementUrl).queryParam("action", "logout").request().post(Entity.form(form));
boolean success = response.getStatus() == 204;
response.close();

View file

@ -11,6 +11,7 @@ import org.keycloak.representations.SkeletonKeyToken;
import javax.ws.rs.core.MultivaluedMap;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -88,8 +89,6 @@ public class TokenManager {
createToken(code, realm, client, user);
logger.info("tokenmanager: access code id: " + code.getId());
logger.info("accesscode setExpiration: " + (System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
code.setRealm(realm);
code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
code.setClient(client);
@ -117,6 +116,10 @@ public class TokenManager {
if (realm.getTokenLifespan() > 0) {
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
}
Set<String> allowedOrigins = client.getWebOrigins();
if (allowedOrigins != null) {
token.setAllowedOrigins(allowedOrigins);
}
return token;
}

View file

@ -142,13 +142,13 @@ public class RequiredActionsService {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response updatePassword(final MultivaluedMap<String, String> formData) {
logger.info("updatePassword");
logger.debug("updatePassword");
AccessCodeEntry accessCode = getAccessCodeEntry(RequiredAction.UPDATE_PASSWORD);
if (accessCode == null) {
logger.info("updatePassword access code is null");
logger.debug("updatePassword access code is null");
return forwardToErrorPage();
}
logger.info("updatePassword has access code");
logger.debug("updatePassword has access code");
UserModel user = getUser(accessCode);
@ -168,7 +168,7 @@ public class RequiredActionsService {
realm.updateCredential(user, credentials);
logger.info("updatePassword updated credential");
logger.debug("updatePassword updated credential");
user.removeRequiredAction(RequiredAction.UPDATE_PASSWORD);
if (accessCode != null) {
@ -269,7 +269,7 @@ public class RequiredActionsService {
private AccessCodeEntry getAccessCodeEntry(RequiredAction requiredAction) {
String code = uriInfo.getQueryParameters().getFirst(FormFlows.CODE);
if (code == null) {
logger.info("getAccessCodeEntry code as not in query param");
logger.debug("getAccessCodeEntry code as not in query param");
return null;
}
@ -278,31 +278,31 @@ public class RequiredActionsService {
try {
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
} catch (Exception ignored) {
logger.info("getAccessCodeEntry code failed verification");
logger.debug("getAccessCodeEntry code failed verification");
return null;
}
if (!verifiedCode) {
logger.info("getAccessCodeEntry code failed verification2");
logger.debug("getAccessCodeEntry code failed verification2");
return null;
}
String key = input.readContent(String.class);
AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key);
if (accessCodeEntry == null) {
logger.info("getAccessCodeEntry access code entry null");
logger.debug("getAccessCodeEntry access code entry null");
return null;
}
if (accessCodeEntry.isExpired()) {
logger.info("getAccessCodeEntry: access code id: " + accessCodeEntry.getId());
logger.info("getAccessCodeEntry access code entry expired: " + accessCodeEntry.getExpiration());
logger.info("getAccessCodeEntry current time: " + (System.currentTimeMillis() / 1000));
logger.debug("getAccessCodeEntry: access code id: {0}", accessCodeEntry.getId());
logger.debug("getAccessCodeEntry access code entry expired: {0}", accessCodeEntry.getExpiration());
logger.debug("getAccessCodeEntry current time: {0}", (System.currentTimeMillis() / 1000));
return null;
}
if (accessCodeEntry.getRequiredActions() == null || !accessCodeEntry.getRequiredActions().contains(requiredAction)) {
logger.info("getAccessCodeEntry required actions null || entry does not contain required action: " + (accessCodeEntry.getRequiredActions() == null) + "|" + !accessCodeEntry.getRequiredActions().contains(requiredAction) );
logger.debug("getAccessCodeEntry required actions null || entry does not contain required action: {0}|{1}", (accessCodeEntry.getRequiredActions() == null),!accessCodeEntry.getRequiredActions().contains(requiredAction) );
return null;
}
@ -323,7 +323,7 @@ public class RequiredActionsService {
return Flows.forms(realm, request, uriInfo).setAccessCode(accessCode).setUser(user)
.forwardToAction(requiredActions.iterator().next());
} else {
logger.info("redirectOauth: redirecting to: " + accessCode.getRedirectUri());
logger.debug("redirectOauth: redirecting to: {0}", accessCode.getRedirectUri());
accessCode.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
return Flows.oauth(realm, request, uriInfo, authManager, tokenManager).redirectAccessCode(accessCode,
accessCode.getState(), accessCode.getRedirectUri());

View file

@ -95,6 +95,67 @@ public class SaasService {
}
}
/** CORS TESTING, Keep for later
@Path("ping")
@GET
@NoCache
@Produces("text/plain")
public Response ping(@Context HttpHeaders headers) {
logger.info("************** GET PING");
for (String header : headers.getRequestHeaders().keySet()) {
logger.info(" header --- " + header + ": " + headers.getHeaderString(header));
}
for (String cookieName : headers.getCookies().keySet()) {
logger.info(" cookie --- " + cookieName);
}
return Response.ok("ping", MediaType.TEXT_PLAIN_TYPE).header("Access-Control-Allow-Origin", headers.getHeaderString("Origin")).build();
}
@Path("ping")
@DELETE
@NoCache
@Produces("text/plain")
public Response deletePing(@Context HttpHeaders headers) {
logger.info("************** DELETE PING");
for (String header : headers.getRequestHeaders().keySet()) {
logger.info(" header --- " + header + ": " + headers.getHeaderString(header));
}
for (String cookieName : headers.getCookies().keySet()) {
logger.info(" cookie --- " + cookieName);
}
return Response.ok("ping", MediaType.TEXT_PLAIN_TYPE).header("Access-Control-Allow-Origin", headers.getHeaderString("Origin")).build();
}
@Path("ping")
@OPTIONS
@NoCache
@Produces("text/plain")
public Response optionsPing(@Context HttpHeaders headers) {
logger.info("************** OPTIONS PING");
for (String header : headers.getRequestHeaders().keySet()) {
logger.info(" " + header + ": " + headers.getHeaderString(header));
}
for (String cookieName : headers.getCookies().keySet()) {
logger.info(" cookie --- " + cookieName);
}
Response.ResponseBuilder ok = Response.ok();
ok
.header("Access-Control-Allow-Origin", headers.getHeaderString("Origin"));
if (headers.getHeaderString("Access-Control-Request-Method") != null) {
ok.header("Access-Control-Allow-Methods", headers.getHeaderString("Access-Control-Request-Method"));
}
return ok.header("Access-Control-Allow-Headers", HttpHeaders.AUTHORIZATION)
.header("Access-Control-Allow-Credentials", "true")
.build();
}
*/
@Path("keepalive")
@GET
@NoCache
@ -191,11 +252,11 @@ public class SaasService {
JaxrsOAuthClient oauth = new JaxrsOAuthClient();
String authUrl = TokenService.loginPageUrl(uriInfo).build(Constants.ADMIN_REALM).toString();
logger.info("authUrl: " + authUrl);
logger.debug("authUrl: {0}", authUrl);
oauth.setAuthUrl(authUrl);
oauth.setClientId(Constants.ADMIN_CONSOLE_APPLICATION);
URI redirectUri = uriInfo.getBaseUriBuilder().path(SaasService.class).path(SaasService.class, "loginRedirect").build();
logger.info("redirectUri: " + redirectUri.toString());
logger.debug("redirectUri: {0}", redirectUri.toString());
oauth.setStateCookiePath(redirectUri.getPath());
return oauth.redirect(uriInfo, redirectUri.toString());
}
@ -210,7 +271,7 @@ public class SaasService {
) {
try {
logger.info("loginRedirect ********************** <---");
logger.debug("loginRedirect ********************** <---");
if (error != null) {
logger.debug("error from oauth");
throw new ForbiddenException("error");
@ -276,7 +337,7 @@ public class SaasService {
logger.debug("not allowed");
throw new ForbiddenException();
}
logger.info("loginRedirect SUCCESS");
logger.debug("loginRedirect SUCCESS");
NewCookie cookie = authManager.createSaasIdentityCookie(realm, accessCode.getUser(), uriInfo);
return Response.status(302).cookie(cookie).location(contextRoot(uriInfo).path(adminPath).build()).build();
} finally {
@ -308,7 +369,7 @@ public class SaasService {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processLogin(final MultivaluedMap<String, String> formData) {
logger.info("processLogin start");
logger.debug("processLogin start");
RealmManager realmManager = new RealmManager(session);
RealmModel realm = getAdminstrationRealm(realmManager);
if (realm == null)

View file

@ -192,8 +192,8 @@ public class SocialResource {
socialRequestManager.addRequest(requestId, reqDetailsBuilder.build());
boolean secureOnly = !realm.isSslNotRequired();
String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath();
logger.info("creating cookie for social registration - name: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE
+ " path: " + cookiePath);
logger.debug("creating cookie for social registration - name: {0} path: {1}", SocialConstants.SOCIAL_REGISTRATION_COOKIE,
cookiePath);
NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, requestId,
cookiePath, null, "Added social cookie", NewCookie.DEFAULT_MAX_AGE, secureOnly);
response.addNewCookie(newCookie);
@ -303,7 +303,7 @@ public class SocialResource {
String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath();
NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, "", cookiePath, null,
"Expire social cookie", 0, false);
logger.info("Expiring social registration cookie: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE + ", path: " + cookiePath);
logger.debug("Expiring social registration cookie: {0}, path: {1}", SocialConstants.SOCIAL_REGISTRATION_COOKIE, cookiePath);
response.addNewCookie(newCookie);
socialRequestManager.retrieveData(requestId);

View file

@ -175,7 +175,7 @@ public class TokenService {
public Response processLogin(@QueryParam("client_id") final String clientId, @QueryParam("scope") final String scopeParam,
@QueryParam("state") final String state, @QueryParam("redirect_uri") final String redirect,
final MultivaluedMap<String, String> formData) {
logger.info("TokenService.processLogin");
logger.debug("TokenService.processLogin");
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
if (!realm.isEnabled()) {
@ -228,7 +228,7 @@ public class TokenService {
for (RequiredCredentialModel c : realm.getRequiredCredentials()) {
if (c.getType().equals(CredentialRepresentation.TOTP) && !user.isTotp()) {
user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
logger.info("User is required to configure totp");
logger.debug("User is required to configure totp");
}
}
}
@ -236,7 +236,7 @@ public class TokenService {
private void isEmailVerificationRequired(UserModel user) {
if (realm.isVerifyEmail() && !user.isEmailVerified()) {
user.addRequiredAction(RequiredAction.VERIFY_EMAIL);
logger.info("User is required to verify email");
logger.debug("User is required to verify email");
}
}
@ -320,7 +320,7 @@ public class TokenService {
@POST
@Produces("application/json")
public Response accessCodeToToken(final MultivaluedMap<String, String> formData) {
logger.info("accessRequest <---");
logger.debug("accessRequest <---");
if (!realm.isEnabled()) {
throw new NotAuthorizedException("Realm not enabled");
}
@ -410,7 +410,7 @@ public class TokenService {
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
.build();
}
logger.info("accessRequest SUCCESS");
logger.debug("accessRequest SUCCESS");
AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken());
return Cors.add(request, Response.ok(res)).allowedOrigins(client.getWebOrigins()).build();
@ -476,7 +476,7 @@ public class TokenService {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
logger.info(user.getLoginName() + " already logged in.");
logger.debug(user.getLoginName() + " already logged in.");
return oauth.processAccessCode(scopeParam, state, redirect, client, user);
}
@ -523,7 +523,7 @@ public class TokenService {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
logger.info("Logging out: " + user.getLoginName());
logger.debug("Logging out: {0}", user.getLoginName());
authManager.expireIdentityCookie(realm, uriInfo);
resourceAdminManager.singleLogOut(realm, user.getLoginName());
}

View file

@ -12,10 +12,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -54,7 +51,7 @@ public class ApplicationResource extends RoleContainerResource {
@PUT
@Consumes("application/json")
public void updateCredentials(List<CredentialRepresentation> credentials) {
logger.info("updateCredentials");
logger.debug("updateCredentials");
if (credentials == null) return;
for (CredentialRepresentation rep : credentials) {
@ -68,5 +65,32 @@ public class ApplicationResource extends RoleContainerResource {
return new ScopeMappedResource(realm, application.getApplicationUser(), session);
}
@Path("allowed-origins")
@GET
@Produces("application/json")
public Set<String> getAllowedOrigins()
{
return application.getApplicationUser().getWebOrigins();
}
@Path("allowed-origins")
@PUT
@Consumes("application/json")
public void updateAllowedOrigins(Set<String> allowedOrigins)
{
application.getApplicationUser().setWebOrigins(allowedOrigins);
}
@Path("allowed-origins")
@DELETE
@Consumes("application/json")
public void deleteAllowedOrigins(Set<String> allowedOrigins)
{
for (String origin : allowedOrigins) {
application.getApplicationUser().removeWebOrigin(origin);
}
}
}

View file

@ -50,7 +50,7 @@ public class OAuthClientResource {
@PUT
@Consumes("application/json")
public void updateCredentials(List<CredentialRepresentation> credentials) {
logger.info("updateCredentials");
logger.debug("updateCredentials");
if (credentials == null) return;
for (CredentialRepresentation rep : credentials) {

View file

@ -60,7 +60,7 @@ public class RealmAdminResource extends RoleContainerResource {
@PUT
@Consumes("application/json")
public void updateRealm(final RealmRepresentation rep) {
logger.info("updating realm: " + realm.getName());
logger.debug("updating realm: " + realm.getName());
new RealmManager(session).updateRealm(rep, realm);
}

View file

@ -43,7 +43,7 @@ public class RealmsAdminResource {
@NoCache
@Produces("application/json")
public List<RealmRepresentation> getRealms() {
logger.info(("getRealms()"));
logger.debug(("getRealms()"));
RealmManager realmManager = new RealmManager(session);
List<RealmModel> realms = session.getRealms(admin);
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
@ -64,11 +64,11 @@ public class RealmsAdminResource {
@POST
@Consumes("application/json")
public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
logger.info("importRealm: " + rep.getRealm());
logger.debug("importRealm: {0}", rep.getRealm());
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.importRealm(rep, admin);
URI location = realmUrl(uriInfo).build(realm.getId());
logger.info("imported realm success, sending back: " + location.toString());
logger.debug("imported realm success, sending back: {0}", location.toString());
return Response.created(location).build();
}

View file

@ -189,7 +189,7 @@ public class UsersResource {
@POST
@Consumes("application/json")
public void addRealmRoleMappings(@PathParam("username") String username, List<RoleRepresentation> roles) {
logger.info("** addRealmRoleMappings: " + roles);
logger.debug("** addRealmRoleMappings: {0}", roles);
UserModel user = realm.getUser(username);
if (user == null) {
throw new NotFoundException();
@ -210,7 +210,7 @@ public class UsersResource {
@DELETE
@Consumes("application/json")
public void deleteRealmRoleMappings(@PathParam("username") String username, List<RoleRepresentation> roles) {
logger.info("deleteRealmRoleMappings");
logger.debug("deleteRealmRoleMappings");
UserModel user = realm.getUser(username);
if (user == null) {
throw new NotFoundException();
@ -238,7 +238,7 @@ public class UsersResource {
@Produces("application/json")
@NoCache
public List<RoleRepresentation> getApplicationRoleMappings(@PathParam("username") String username, @PathParam("appId") String appId) {
logger.info("getApplicationRoleMappings");
logger.debug("getApplicationRoleMappings");
UserModel user = realm.getUser(username);
if (user == null) {
@ -256,7 +256,7 @@ public class UsersResource {
for (RoleModel roleModel : mappings) {
mapRep.add(RealmManager.toRepresentation(roleModel));
}
logger.info("getApplicationRoleMappings.size() = " + mapRep.size());
logger.debug("getApplicationRoleMappings.size() = {0}", mapRep.size());
return mapRep;
}
@ -264,7 +264,7 @@ public class UsersResource {
@POST
@Consumes("application/json")
public void addApplicationRoleMapping(@PathParam("username") String username, @PathParam("appId") String appId, List<RoleRepresentation> roles) {
logger.info("addApplicationRoleMapping");
logger.debug("addApplicationRoleMapping");
UserModel user = realm.getUser(username);
if (user == null) {
throw new NotFoundException();

View file

@ -75,7 +75,7 @@ public class OAuthFlows {
String code = accessCode.getCode();
UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam("code", code);
log.info("redirectAccessCode: state: " + state);
log.debug("redirectAccessCode: state: {0}", state);
if (state != null)
redirectUri.queryParam("state", state);
Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
@ -107,9 +107,9 @@ public class OAuthFlows {
return forwardToSecurityFailure("Login requester not allowed to request login.");
}
AccessCodeEntry accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, realm, client, user);
log.info("processAccessCode: isResource: " + isResource);
log.info("processAccessCode: go to oauth page?: "
+ (!isResource && (accessCode.getRealmRolesRequested().size() > 0 || accessCode.getResourceRolesRequested()
log.debug("processAccessCode: isResource: {0}", isResource);
log.debug("processAccessCode: go to oauth page?: {0}",
(!isResource && (accessCode.getRealmRolesRequested().size() > 0 || accessCode.getResourceRolesRequested()
.size() > 0)));
Set<RequiredAction> requiredActions = user.getRequiredActions();