keycloak-aplcache

Merge branch 'objectiser-RTGOV-620'

12/1/2014 10:47:33 AM

Changes

examples/pom.xml 1(+1 -0)

Details

diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java
index 58d49ea..676a103 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java
@@ -16,7 +16,7 @@ import java.util.Map;
         "resource", "public-client", "credentials",
         "use-resource-role-mappings",
         "enable-cors", "cors-max-age", "cors-allowed-methods",
-        "expose-token", "bearer-only"})
+        "expose-token", "bearer-only", "enable-basic-auth"})
 public class BaseAdapterConfig extends BaseRealmConfig {
     @JsonProperty("resource")
     protected String resource;
@@ -34,6 +34,8 @@ public class BaseAdapterConfig extends BaseRealmConfig {
     protected boolean exposeToken;
     @JsonProperty("bearer-only")
     protected boolean bearerOnly;
+    @JsonProperty("enable-basic-auth")
+    protected boolean enableBasicAuth;
     @JsonProperty("public-client")
     protected boolean publicClient;
     @JsonProperty("credentials")
@@ -97,12 +99,20 @@ public class BaseAdapterConfig extends BaseRealmConfig {
      }
 
     public boolean isBearerOnly() {
-         return bearerOnly;
-     }
+        return bearerOnly;
+    }
 
     public void setBearerOnly(boolean bearerOnly) {
-         this.bearerOnly = bearerOnly;
-     }
+        this.bearerOnly = bearerOnly;
+    }
+
+    public boolean isEnableBasicAuth() {
+        return enableBasicAuth;
+    }
+
+    public void setEnableBasicAuth(boolean enableBasicAuth) {
+        this.enableBasicAuth = enableBasicAuth;
+    }
 
     public Map<String, String> getCredentials() {
         return credentials;
diff --git a/distribution/examples-docs-zip/build.xml b/distribution/examples-docs-zip/build.xml
index 16f93f5..503dc8e 100755
--- a/distribution/examples-docs-zip/build.xml
+++ b/distribution/examples-docs-zip/build.xml
@@ -50,6 +50,14 @@
                 <exclude name="**/subsystem-config.xml"/>
             </fileset>
         </copy>
+        <copy todir="target/examples/basic-auth" overwrite="true">
+            <fileset dir="../../examples/basic-auth">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
         <copy todir="target/examples/admin-client" overwrite="true">
             <fileset dir="../../examples/admin-client">
                 <exclude name="**/target/**"/>
diff --git a/distribution/modules/build.xml b/distribution/modules/build.xml
index 14ed2cd..a9da469 100755
--- a/distribution/modules/build.xml
+++ b/distribution/modules/build.xml
@@ -86,9 +86,6 @@
         <module-def name="org.keycloak.keycloak-subsystem">
             <maven-resource group="org.keycloak" artifact="keycloak-subsystem"/>
         </module-def>
-        <module-def name="org.keycloak.keycloak-as7-subsystem">
-            <maven-resource group="org.keycloak" artifact="keycloak-as7-subsystem"/>
-        </module-def>
         <module-def name="org.picketlink">
         </module-def>
         <module-def name="org.picketlink.common">
diff --git a/distribution/modules/pom.xml b/distribution/modules/pom.xml
index 5a286ab..f3a2a08 100755
--- a/distribution/modules/pom.xml
+++ b/distribution/modules/pom.xml
@@ -53,11 +53,6 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-as7-subsystem</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk16</artifactId>
         </dependency>
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml
index 5323ea3..2af6613 100755
--- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml
@@ -34,6 +34,7 @@
         <module name="org.apache.httpcomponents" />
         <module name="org.jboss.logging"/>
         <module name="org.keycloak.keycloak-core"/>
+        <module name="net.iharder.base64"/>
     </dependencies>
 
 </module>
diff --git a/docbook/reference/en/en-US/modules/adapter-config.xml b/docbook/reference/en/en-US/modules/adapter-config.xml
index 6eddb77..979a9d5 100755
--- a/docbook/reference/en/en-US/modules/adapter-config.xml
+++ b/docbook/reference/en/en-US/modules/adapter-config.xml
@@ -16,6 +16,7 @@
   "cors-max-age" : 1000,
   "cors-allowed-methods" : [ "POST", "PUT", "DELETE", "GET" ],
   "bearer-only" : false,
+  "enable-basic-auth" : false,
   "expose-token" : true,
    "credentials" : {
       "secret" : "234234-234234-234234"
@@ -158,6 +159,16 @@
                 </listitem>
             </varlistentry>
             <varlistentry>
+                <term>enable-basic-auth</term>
+                <listitem>
+                    <para>
+                        This tells the adapter to also support basic authentication. If this option is enabled,
+                        then <emphasis>secret</emphasis> must also be provided.
+                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
                 <term>expose-token</term>
                 <listitem>
                     <para>
diff --git a/examples/basic-auth/basicauthrealm.json b/examples/basic-auth/basicauthrealm.json
new file mode 100644
index 0000000..d738fd2
--- /dev/null
+++ b/examples/basic-auth/basicauthrealm.json
@@ -0,0 +1,56 @@
+{
+    "realm": "basic-auth",
+    "enabled": true,
+    "accessTokenLifespan": 60,
+    "accessCodeLifespan": 60,
+    "accessCodeLifespanUserAction": 300,
+    "ssoSessionIdleTimeout": 600,
+    "ssoSessionMaxLifespan": 36000,
+    "passwordCredentialGrantAllowed": true,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "social": false,
+    "updateProfileOnInitialSocialLogin": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "admin",
+            "enabled": true,
+            "email" : "admin@admin.com",
+            "firstName": "Admin",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user","admin" ],
+            "applicationRoles": {
+                "realm-management": [ "realm-admin" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "applications": [
+        {
+            "name": "basic-auth-service",
+            "enabled": true,
+            "adminUrl": "/basicauth",
+            "baseUrl": "/basicauth",
+            "secret": "password"
+        }
+    ]
+
+}
diff --git a/examples/basic-auth/pom.xml b/examples/basic-auth/pom.xml
new file mode 100644
index 0000000..5e7095d
--- /dev/null
+++ b/examples/basic-auth/pom.xml
@@ -0,0 +1,94 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.1.0.Beta2-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <name>Keycloak Examples - Basic Auth</name>
+    <artifactId>examples-basicauth</artifactId>
+    <packaging>war</packaging>
+
+    <description>
+        Keycloak Basic Auth Example
+    </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.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <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>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${keycloak.apache.httpcomponents.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>basicauth</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>
+            <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>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/basic-auth/README.md b/examples/basic-auth/README.md
new file mode 100644
index 0000000..c79becb
--- /dev/null
+++ b/examples/basic-auth/README.md
@@ -0,0 +1,29 @@
+Keycloak Example - Basic Authentication
+=======================================
+
+The following example was tested on Wildfly 8.1.0.Final and JBoss EAP 6.3. It should be compatible with any JBoss AS, JBoss EAP or Wildfly that supports Java EE 7.
+
+This example demonstrates basic authentication support for a Keycloak protected REST service. However, more importantly it enables a REST service to be secured using both basic and bearer token authentication, which is useful where the service needs to be accessed both as part of a single signon session, and also as a standalone REST service.
+
+
+Step 1: Setup a basic Keycloak server
+--------------------------------------------------------------
+Install Keycloak server and start it on port 8080. Check the Reference Guide if unsure on how to do it.
+
+Once the Keycloak server is up and running, import the realm basicauthrealm.json.
+
+
+Step 2: Deploy and run the example
+--------------------------------------------------------------
+
+- Build and deploy this sample's WAR file. For this example, deploy on the same server that is running the Keycloak Server, although this is not required for real world scenarios.
+
+- Open a command window and perform the following command:
+
+    curl http://admin:password@localhost:8080/basicauth/service/echo?value=hello
+
+This should result in the value 'hello' being returned as a response.
+
+Simply change the username (currently 'admin') or password (currently 'password') in the command to see an "Unauthorized" response.
+
+
diff --git a/examples/basic-auth/src/main/java/org/keycloak/example/basicauth/BasicAuthService.java b/examples/basic-auth/src/main/java/org/keycloak/example/basicauth/BasicAuthService.java
new file mode 100644
index 0000000..d722da9
--- /dev/null
+++ b/examples/basic-auth/src/main/java/org/keycloak/example/basicauth/BasicAuthService.java
@@ -0,0 +1,24 @@
+package org.keycloak.example.basicauth;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Path("service")
+public class BasicAuthService {
+    @GET
+    @NoCache
+    @Path("echo")
+    public String echo(@QueryParam("value") String value) {
+        return value;
+    }
+}
diff --git a/examples/basic-auth/src/main/java/org/keycloak/example/basicauth/BasicAuthServiceApplication.java b/examples/basic-auth/src/main/java/org/keycloak/example/basicauth/BasicAuthServiceApplication.java
new file mode 100644
index 0000000..c0c0382
--- /dev/null
+++ b/examples/basic-auth/src/main/java/org/keycloak/example/basicauth/BasicAuthServiceApplication.java
@@ -0,0 +1,12 @@
+package org.keycloak.example.basicauth;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * Basic auth app.
+ */
+@ApplicationPath("/")
+public class BasicAuthServiceApplication extends Application
+{
+}
diff --git a/examples/basic-auth/src/main/webapp/WEB-INF/keycloak.json b/examples/basic-auth/src/main/webapp/WEB-INF/keycloak.json
new file mode 100644
index 0000000..4502199
--- /dev/null
+++ b/examples/basic-auth/src/main/webapp/WEB-INF/keycloak.json
@@ -0,0 +1,11 @@
+{
+  "realm" : "basic-auth",
+  "resource" : "basic-auth-service",
+  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+  "auth-server-url": "/auth",
+  "ssl-required" : "external",
+  "enable-basic-auth" : "true",
+  "credentials": {
+      "secret": "password"
+  }
+}
diff --git a/examples/basic-auth/src/main/webapp/WEB-INF/web.xml b/examples/basic-auth/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..f25eb46
--- /dev/null
+++ b/examples/basic-auth/src/main/webapp/WEB-INF/web.xml
@@ -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>basicauth</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>KEYCLOAK</auth-method>
+        <realm-name>basic-auth</realm-name>
+    </login-config>
+
+    <security-role>
+        <role-name>user</role-name>
+    </security-role>
+</web-app>

examples/pom.xml 1(+1 -0)

diff --git a/examples/pom.xml b/examples/pom.xml
index 61c47af..97d1b9e 100755
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -31,5 +31,6 @@
         <module>providers</module>
         <module>js-console</module>
         <module>multi-tenant</module>
+        <module>basic-auth</module>
     </modules>
 </project>
diff --git a/integration/adapter-core/pom.xml b/integration/adapter-core/pom.xml
index 9262be1..e6f4b0b 100755
--- a/integration/adapter-core/pom.xml
+++ b/integration/adapter-core/pom.xml
@@ -42,6 +42,11 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
index 6258645..d8a2141 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
@@ -238,6 +238,16 @@ public class AdapterDeploymentContext {
         }
 
         @Override
+        public boolean isEnableBasicAuth() {
+            return delegate.isEnableBasicAuth();
+        }
+
+        @Override
+        public void setEnableBasicAuth(boolean enableBasicAuth) {
+            delegate.setEnableBasicAuth(enableBasicAuth);
+        }
+
+        @Override
         public boolean isPublicClient() {
             return delegate.isPublicClient();
         }
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/BasicAuthRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/BasicAuthRequestAuthenticator.java
new file mode 100644
index 0000000..55dc847
--- /dev/null
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/BasicAuthRequestAuthenticator.java
@@ -0,0 +1,112 @@
+package org.keycloak.adapters;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.message.BasicNameValuePair;
+import org.jboss.logging.Logger;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.constants.ServiceUrlConstants;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.util.BasicAuthHelper;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.KeycloakUriBuilder;
+
+import java.util.List;
+
+/**
+ * Basic auth request authenticator.
+ */
+public class BasicAuthRequestAuthenticator extends BearerTokenRequestAuthenticator {
+    protected Logger log = Logger.getLogger(BasicAuthRequestAuthenticator.class);
+    
+    public BasicAuthRequestAuthenticator(KeycloakDeployment deployment) {
+    	super(deployment);
+    }
+
+    public AuthOutcome authenticate(HttpFacade exchange)  {
+        List<String> authHeaders = exchange.getRequest().getHeaders("Authorization");
+        if (authHeaders == null || authHeaders.size() == 0) {
+            challenge = challengeResponse(exchange, null, null);
+            return AuthOutcome.NOT_ATTEMPTED;
+        }
+
+        tokenString = null;
+        for (String authHeader : authHeaders) {
+            String[] split = authHeader.trim().split("\\s+");
+            if (split == null || split.length != 2) continue;
+            if (!split[0].equalsIgnoreCase("Basic")) continue;
+            tokenString = split[1];
+        }
+
+        if (tokenString == null) {
+            challenge = challengeResponse(exchange, null, null);
+            return AuthOutcome.NOT_ATTEMPTED;
+        }
+
+        AccessTokenResponse atr=null;        
+        try {
+            String userpw=new String(net.iharder.Base64.decode(tokenString));
+            String[] parts=userpw.split(":");
+            
+            atr = getToken(parts[0], parts[1]);
+        } catch (Exception e) {
+            log.debug("Failed to obtain token", e);
+            challenge = challengeResponse(exchange, "no_token", e.getMessage());
+            return AuthOutcome.FAILED;
+        }
+
+        return authenticateToken(exchange, atr.getToken());
+    }
+    
+    private AccessTokenResponse getToken(String username, String password) throws Exception {
+    	AccessTokenResponse tokenResponse=null;
+    	HttpClient client = new HttpClientBuilder().disableTrustManager().build();
+
+    	try {
+    	    HttpPost post = new HttpPost(
+    	            KeycloakUriBuilder.fromUri(deployment.getAuthServerBaseUrl())
+    	            .path(ServiceUrlConstants.TOKEN_SERVICE_DIRECT_GRANT_PATH).build(deployment.getRealm()));
+    	    java.util.List <NameValuePair> formparams = new java.util.ArrayList <NameValuePair>();
+    	    formparams.add(new BasicNameValuePair("username", username));
+    	    formparams.add(new BasicNameValuePair("password", password));
+
+    	    if (deployment.isPublicClient()) {
+    	        formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, deployment.getResourceName()));
+    	    } else {
+    	        String authorization = BasicAuthHelper.createHeader(deployment.getResourceName(),
+    	                deployment.getResourceCredentials().get("secret"));
+    	        post.setHeader("Authorization", authorization);
+    	    }
+
+    	    UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+    	    post.setEntity(form);
+
+    	    HttpResponse response = client.execute(post);
+    	    int status = response.getStatusLine().getStatusCode();
+    	    HttpEntity entity = response.getEntity();
+    	    if (status != 200) {
+    	        throw new java.io.IOException("Bad status: " + status);
+    	    }
+    	    if (entity == null) {
+    	        throw new java.io.IOException("No Entity");
+    	    }
+    	    java.io.InputStream is = entity.getContent();
+    	    try {
+    	        tokenResponse = JsonSerialization.readValue(is, AccessTokenResponse.class);
+    	    } finally {
+    	        try {
+    	            is.close();
+    	        } catch (java.io.IOException ignored) { }
+    	    }
+    	} finally {
+    	    client.getConnectionManager().shutdown();
+    	}
+    	
+    	return (tokenResponse);
+    }
+
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
index 0aafa00..ccbe596 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
@@ -59,6 +59,10 @@ public class BearerTokenRequestAuthenticator {
             return AuthOutcome.NOT_ATTEMPTED;
         }
 
+        return (authenticateToken(exchange, tokenString));
+    }
+    
+    protected AuthOutcome authenticateToken(HttpFacade exchange, String tokenString) {
         try {
             token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealm());
         } catch (VerificationException e) {
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
index f4b9c90..e9dfaf6 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
@@ -38,6 +38,7 @@ public class KeycloakDeployment {
 
     protected String resourceName;
     protected boolean bearerOnly;
+    protected boolean enableBasicAuth;
     protected boolean publicClient;
     protected Map<String, String> resourceCredentials = new HashMap<String, String>();
     protected HttpClient client;
@@ -199,6 +200,14 @@ public class KeycloakDeployment {
         this.bearerOnly = bearerOnly;
     }
 
+    public boolean isEnableBasicAuth() {
+        return enableBasicAuth;
+    }
+
+    public void setEnableBasicAuth(boolean enableBasicAuth) {
+        this.enableBasicAuth = enableBasicAuth;
+    }
+
     public boolean isPublicClient() {
         return publicClient;
     }
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
index e03eb51..1f00b91 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
@@ -67,6 +67,7 @@ public class KeycloakDeploymentBuilder {
         }
 
         deployment.setBearerOnly(adapterConfig.isBearerOnly());
+        deployment.setEnableBasicAuth(adapterConfig.isEnableBasicAuth());
         deployment.setAlwaysRefreshToken(adapterConfig.isAlwaysRefreshToken());
         deployment.setRegisterNodeAtStartup(adapterConfig.isRegisterNodeAtStartup());
         deployment.setRegisterNodePeriod(adapterConfig.getRegisterNodePeriod());
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
index d5c7119..bd853da 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
@@ -36,10 +36,12 @@ public abstract class RequestAuthenticator {
         if (log.isTraceEnabled()) {
             log.trace("--> authenticate()");
         }
+
         BearerTokenRequestAuthenticator bearer = createBearerTokenAuthenticator();
         if (log.isTraceEnabled()) {
             log.trace("try bearer");
         }
+        
         AuthOutcome outcome = bearer.authenticate(facade);
         if (outcome == AuthOutcome.FAILED) {
             challenge = bearer.getChallenge();
@@ -47,7 +49,7 @@ public abstract class RequestAuthenticator {
             return AuthOutcome.FAILED;
         } else if (outcome == AuthOutcome.AUTHENTICATED) {
             if (verifySSL()) return AuthOutcome.FAILED;
-            completeAuthentication(bearer);
+            completeAuthentication(bearer, "KEYCLOAK");
             log.debug("Bearer AUTHENTICATED");
             return AuthOutcome.AUTHENTICATED;
         } else if (deployment.isBearerOnly()) {
@@ -56,6 +58,24 @@ public abstract class RequestAuthenticator {
             return AuthOutcome.NOT_ATTEMPTED;
         }
 
+        if (deployment.isEnableBasicAuth()) {
+            BasicAuthRequestAuthenticator basicAuth = createBasicAuthAuthenticator();
+            if (log.isTraceEnabled()) {
+                log.trace("try basic auth");
+            }
+    
+            outcome = basicAuth.authenticate(facade);
+            if (outcome == AuthOutcome.FAILED) {
+                challenge = basicAuth.getChallenge();
+                log.debug("BasicAuth FAILED");
+                return AuthOutcome.FAILED;
+            } else if (outcome == AuthOutcome.AUTHENTICATED) {
+                log.debug("BasicAuth AUTHENTICATED");
+                completeAuthentication(basicAuth, "BASIC");
+                return AuthOutcome.AUTHENTICATED;
+            }
+        }
+
         if (log.isTraceEnabled()) {
             log.trace("try oauth");
         }
@@ -104,6 +124,10 @@ public abstract class RequestAuthenticator {
         return new BearerTokenRequestAuthenticator(deployment);
     }
 
+    protected BasicAuthRequestAuthenticator createBasicAuthAuthenticator() {
+        return new BasicAuthRequestAuthenticator(deployment);
+    }
+
     protected void completeAuthentication(OAuthRequestAuthenticator oauth) {
         RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, tokenStore, oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), oauth.getRefreshToken());
         final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, oauth.getToken()), session);
@@ -111,13 +135,13 @@ public abstract class RequestAuthenticator {
     }
 
     protected abstract void completeOAuthAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal);
-    protected abstract void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal);
+    protected abstract void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method);
     protected abstract String getHttpSessionId(boolean create);
 
-    protected void completeAuthentication(BearerTokenRequestAuthenticator bearer) {
+    protected void completeAuthentication(BearerTokenRequestAuthenticator bearer, String method) {
         RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, null, bearer.getTokenString(), bearer.getToken(), null, null, null);
         final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, bearer.getToken()), session);
-        completeBearerAuthentication(principal);
+        completeBearerAuthentication(principal, method);
     }
 
 }
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java
index 74e0e63..7544e66 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java
@@ -84,7 +84,7 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
     }
 
     @Override
-    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
         RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
         Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
         if (log.isDebugEnabled()) {
@@ -92,7 +92,7 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
         }
         Principal generalPrincipal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), principal, roles, securityContext);
         request.setUserPrincipal(generalPrincipal);
-        request.setAuthType("KEYCLOAK");
+        request.setAuthType(method);
         request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
     }
 
diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilterImpl.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilterImpl.java
index 33795c2..1d070cf 100755
--- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilterImpl.java
+++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilterImpl.java
@@ -6,6 +6,7 @@ import org.keycloak.adapters.AdapterUtils;
 import org.keycloak.adapters.AuthChallenge;
 import org.keycloak.adapters.AuthOutcome;
 import org.keycloak.adapters.AuthenticatedActionsHandler;
+import org.keycloak.adapters.BasicAuthRequestAuthenticator;
 import org.keycloak.adapters.BearerTokenRequestAuthenticator;
 import org.keycloak.adapters.KeycloakConfigResolver;
 import org.keycloak.adapters.KeycloakDeployment;
@@ -188,10 +189,16 @@ public class JaxrsBearerTokenFilterImpl implements JaxrsBearerTokenFilter {
     }
 
     protected void bearerAuthentication(JaxrsHttpFacade facade, ContainerRequestContext request, KeycloakDeployment resolvedDeployment) {
-        BearerTokenRequestAuthenticator bearer = new BearerTokenRequestAuthenticator(resolvedDeployment);
-        AuthOutcome outcome = bearer.authenticate(facade);
+        BearerTokenRequestAuthenticator authenticator = new BearerTokenRequestAuthenticator(resolvedDeployment);
+        AuthOutcome outcome = authenticator.authenticate(facade);
+        
+        if (outcome == AuthOutcome.NOT_ATTEMPTED && resolvedDeployment.isEnableBasicAuth()) {
+            authenticator = new BasicAuthRequestAuthenticator(resolvedDeployment);
+            outcome = authenticator.authenticate(facade);
+        }
+        
         if (outcome == AuthOutcome.FAILED || outcome == AuthOutcome.NOT_ATTEMPTED) {
-            AuthChallenge challenge = bearer.getChallenge();
+            AuthChallenge challenge = authenticator.getChallenge();
             log.fine("Authentication outcome: " + outcome);
             boolean challengeSent = challenge.challenge(facade);
             if (!challengeSent) {
@@ -210,7 +217,7 @@ public class JaxrsBearerTokenFilterImpl implements JaxrsBearerTokenFilter {
             }
         }
 
-        propagateSecurityContext(facade, request, resolvedDeployment, bearer);
+        propagateSecurityContext(facade, request, resolvedDeployment, authenticator);
         handleAuthActions(facade, resolvedDeployment);
     }
 
diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java
index ee6ffae..c78169e 100755
--- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java
+++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java
@@ -79,7 +79,7 @@ public abstract class AbstractJettyRequestAuthenticator extends RequestAuthentic
     }
 
     @Override
-    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
         this.principal = principal;
         RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
         Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentDefinition.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentDefinition.java
index 2254dd6..9cd606c 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentDefinition.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentDefinition.java
@@ -65,6 +65,12 @@ public class SecureDeploymentDefinition extends SimpleResourceDefinition {
                     .setAllowExpression(true)
                     .setDefaultValue(new ModelNode(false))
                     .build();
+    protected static final SimpleAttributeDefinition ENABLE_BASIC_AUTH =
+            new SimpleAttributeDefinitionBuilder("enable-basic-auth", ModelType.BOOLEAN, true)
+                    .setXmlName("enable-basic-auth")
+                    .setAllowExpression(true)
+                    .setDefaultValue(new ModelNode(false))
+                    .build();
     protected static final SimpleAttributeDefinition PUBLIC_CLIENT =
             new SimpleAttributeDefinitionBuilder("public-client", ModelType.BOOLEAN, true)
                     .setXmlName("public-client")
@@ -78,6 +84,7 @@ public class SecureDeploymentDefinition extends SimpleResourceDefinition {
         DEPLOYMENT_ONLY_ATTRIBUTES.add(RESOURCE);
         DEPLOYMENT_ONLY_ATTRIBUTES.add(USE_RESOURCE_ROLE_MAPPINGS);
         DEPLOYMENT_ONLY_ATTRIBUTES.add(BEARER_ONLY);
+        DEPLOYMENT_ONLY_ATTRIBUTES.add(ENABLE_BASIC_AUTH);
         DEPLOYMENT_ONLY_ATTRIBUTES.add(PUBLIC_CLIENT);
     }
 
diff --git a/integration/keycloak-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties b/integration/keycloak-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties
index 1756381..46d254d 100755
--- a/integration/keycloak-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties
+++ b/integration/keycloak-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties
@@ -68,6 +68,7 @@ keycloak.secure-deployment.resource=Application name
 keycloak.secure-deployment.use-resource-role-mappings=Use resource level permissions from token
 keycloak.secure-deployment.credentials=Adapter credentials
 keycloak.secure-deployment.bearer-only=Bearer Token Auth only
+keycloak.secure-deployment.enable-basic-auth=Enable Basic Authentication
 keycloak.secure-deployment.public-client=Public client
 keycloak.secure-deployment.enable-cors=Enable Keycloak CORS support
 keycloak.secure-deployment.client-keystore=n/a
diff --git a/integration/keycloak-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd b/integration/keycloak-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd
index ff7c16e..17d6aa6 100755
--- a/integration/keycloak-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd
+++ b/integration/keycloak-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd
@@ -86,6 +86,7 @@
             <xs:element name="register-node-period" type="xs:integer" minOccurs="0" maxOccurs="1"/>
             <xs:element name="token-store" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="principal-attribute" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="enable-basic-auth" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
         </xs:all>
         <xs:attribute name="name" type="xs:string" use="required">
             <xs:annotation>
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaRequestAuthenticator.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaRequestAuthenticator.java
index fdfe16f..e7884b8 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaRequestAuthenticator.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaRequestAuthenticator.java
@@ -86,7 +86,7 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
     }
 
     @Override
-    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
         RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
         Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
         if (log.isLoggable(Level.FINE)) {
@@ -94,7 +94,7 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
         }
         Principal generalPrincipal = principalFactory.createPrincipal(request.getContext().getRealm(), principal, roles, securityContext);
         request.setUserPrincipal(generalPrincipal);
-        request.setAuthType("KEYCLOAK");
+        request.setAuthType(method);
         request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
     }
 
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java
index b9761e1..5ef0734 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java
@@ -20,6 +20,7 @@ import io.undertow.security.api.SecurityContext;
 import io.undertow.server.HttpServerExchange;
 import io.undertow.server.session.Session;
 import io.undertow.util.Sessions;
+
 import org.keycloak.KeycloakPrincipal;
 import org.keycloak.adapters.AdapterTokenStore;
 import org.keycloak.adapters.HttpFacade;
@@ -69,9 +70,9 @@ public abstract class AbstractUndertowRequestAuthenticator extends RequestAuthen
     }
 
     @Override
-    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
         KeycloakUndertowAccount account = createAccount(principal);
-        securityContext.authenticationComplete(account, "KEYCLOAK", false);
+        securityContext.authenticationComplete(account, method, false);
         propagateKeycloakContext(account);
     }
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java
new file mode 100644
index 0000000..252a253
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java
@@ -0,0 +1,144 @@
+package org.keycloak.testsuite.jaxrs;
+
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.UUID;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.jboss.resteasy.client.jaxrs.ResteasyClient;
+import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
+import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExternalResource;
+import org.keycloak.adapters.HttpClientBuilder;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.Constants;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.openqa.selenium.WebDriver;
+
+/**
+ * Test for basic authentication.
+ */
+public class JaxrsBasicAuthTest {
+
+    private static final String JAXRS_APP_URL = Constants.SERVER_ROOT + "/jaxrs-simple/res";
+
+    public static final String CONFIG_FILE_INIT_PARAM = "config-file";
+
+    @ClassRule
+    public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
+
+        @Override
+        public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+            ApplicationModel app = appRealm.addApplication("jaxrs-app");
+            app.setEnabled(true);
+            app.setSecret("password");
+            app.setFullScopeAllowed(true);
+
+            JaxrsBasicAuthTest.appRealm = appRealm;
+        }
+    });
+
+    @ClassRule
+    public static ExternalResource clientRule = new ExternalResource() {
+
+        @Override
+        protected void before() throws Throwable {
+            DefaultHttpClient httpClient = (DefaultHttpClient) new HttpClientBuilder().build();
+            ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
+            client = new ResteasyClientBuilder().httpEngine(engine).build();
+        }
+
+        @Override
+        protected void after() {
+            client.close();
+        }
+    };
+
+    private static ResteasyClient client;
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    protected WebDriver driver;
+
+    // Used for signing admin action
+    protected static RealmModel appRealm;
+
+
+    @Test
+    public void testBasic() {
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                Map<String,String> initParams = new TreeMap<String,String>();
+                initParams.put(CONFIG_FILE_INIT_PARAM, "classpath:jaxrs-test/jaxrs-keycloak-basicauth.json");
+                keycloakRule.deployJaxrsApplication("JaxrsSimpleApp", "/jaxrs-simple", JaxrsTestApplication.class, initParams);
+            }
+
+        });
+
+        // Send GET request without credentials, it should fail
+        Response getResp = client.target(JAXRS_APP_URL).request().get();
+        Assert.assertEquals(getResp.getStatus(), 401);
+        getResp.close();
+
+        // Send POST request without credentials, it should fail
+        Response postResp = client.target(JAXRS_APP_URL).request().post(Entity.form(new Form()));
+        Assert.assertEquals(postResp.getStatus(), 401);
+        postResp.close();
+
+        // Retrieve token
+        String incorrectAuthHeader = "Basic "+encodeCredentials("invalid-user", "password");
+
+        // Send GET request with incorrect credentials, it shojuld fail
+        getResp = client.target(JAXRS_APP_URL).request()
+                .header(HttpHeaders.AUTHORIZATION, incorrectAuthHeader)
+                .get();
+        Assert.assertEquals(getResp.getStatus(), 401);
+        getResp.close();
+        
+        // Retrieve token
+        String authHeader = "Basic "+encodeCredentials("test-user@localhost", "password");
+
+        // Send GET request with token and assert it's passing
+        JaxrsTestResource.SimpleRepresentation getRep = client.target(JAXRS_APP_URL).request()
+                .header(HttpHeaders.AUTHORIZATION, authHeader)
+                .get(JaxrsTestResource.SimpleRepresentation.class);
+        Assert.assertEquals("get", getRep.getMethod());
+        
+        Assert.assertTrue(getRep.getHasUserRole());
+        Assert.assertFalse(getRep.getHasAdminRole());
+        Assert.assertFalse(getRep.getHasJaxrsAppRole());
+        // Assert that principal is ID of user (should be in UUID format)
+        UUID.fromString(getRep.getPrincipal());
+
+        // Send POST request with token and assert it's passing
+        JaxrsTestResource.SimpleRepresentation postRep = client.target(JAXRS_APP_URL).request()
+                .header(HttpHeaders.AUTHORIZATION, authHeader)
+                .post(Entity.form(new Form()), JaxrsTestResource.SimpleRepresentation.class);
+        Assert.assertEquals("post", postRep.getMethod());
+        Assert.assertEquals(getRep.getPrincipal(), postRep.getPrincipal());
+    }
+
+    private String encodeCredentials(String username, String password) {
+        String text=username+":"+password;
+        return (net.iharder.Base64.encodeBytes(text.getBytes()));
+    }
+}
diff --git a/testsuite/integration/src/test/resources/jaxrs-test/jaxrs-keycloak-basicauth.json b/testsuite/integration/src/test/resources/jaxrs-test/jaxrs-keycloak-basicauth.json
new file mode 100644
index 0000000..949b720
--- /dev/null
+++ b/testsuite/integration/src/test/resources/jaxrs-test/jaxrs-keycloak-basicauth.json
@@ -0,0 +1,11 @@
+{
+    "realm": "test",
+    "resource": "jaxrs-app",
+    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "auth-server-url": "http://localhost:8081/auth",
+    "ssl-required" : "external",
+    "enable-basic-auth": true,
+    "credentials": {
+      "secret": "password"
+	}
+}
\ No newline at end of file