keycloak-uncached

Merge pull request #2449 from grossws/KEYCLOAK-2236 KEYCLOAK-2236

4/7/2016 10:45:10 AM

Details

diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/Config.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/Config.java
index ae3edaa..4e628e5 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/Config.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/Config.java
@@ -17,6 +17,9 @@
 
 package org.keycloak.admin.client;
 
+import static org.keycloak.OAuth2Constants.CLIENT_CREDENTIALS;
+import static org.keycloak.OAuth2Constants.PASSWORD;
+
 /**
  * @author rodrigo.sasaki@icarros.com.br
  */
@@ -28,14 +31,21 @@ public class Config {
     private String password;
     private String clientId;
     private String clientSecret;
+    private String grantType;
 
     public Config(String serverUrl, String realm, String username, String password, String clientId, String clientSecret) {
+        this(serverUrl, realm, username, password, clientId, clientSecret, PASSWORD);
+    }
+
+    public Config(String serverUrl, String realm, String username, String password, String clientId, String clientSecret, String grantType) {
         this.serverUrl = serverUrl;
         this.realm = realm;
         this.username = username;
         this.password = password;
         this.clientId = clientId;
         this.clientSecret = clientSecret;
+        this.grantType = grantType;
+        checkGrantType(grantType);
     }
 
     public String getServerUrl() {
@@ -86,8 +96,23 @@ public class Config {
         this.clientSecret = clientSecret;
     }
 
-    public boolean isPublicClient(){
+    public boolean isPublicClient() {
         return clientSecret == null;
     }
 
+    public String getGrantType() {
+        return grantType;
+    }
+
+    public void setGrantType(String grantType) {
+        this.grantType = grantType;
+        checkGrantType(grantType);
+    }
+
+    public static void checkGrantType(String grantType) {
+        if (!PASSWORD.equals(grantType) && !CLIENT_CREDENTIALS.equals(grantType)) {
+            throw new IllegalArgumentException("Unsupported grantType: " + grantType +
+                    " (only " + PASSWORD + " and " + CLIENT_CREDENTIALS + " are supported)");
+        }
+    }
 }
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java
index 52c5561..5e30a66 100755
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java
@@ -28,25 +28,25 @@ import org.keycloak.admin.client.token.TokenManager;
 
 import java.net.URI;
 
+import static org.keycloak.OAuth2Constants.PASSWORD;
+
 /**
  * Provides a Keycloak client. By default, this implementation uses a {@link ResteasyClient RESTEasy client} with the
  * default {@link ResteasyClientBuilder} settings. To customize the underling client, use a {@link KeycloakBuilder} to
  * create a Keycloak client.
  *
- * @see KeycloakBuilder
- *
  * @author rodrigo.sasaki@icarros.com.br
+ * @see KeycloakBuilder
  */
 public class Keycloak {
-
     private final Config config;
     private final TokenManager tokenManager;
     private final ResteasyWebTarget target;
     private final ResteasyClient client;
 
-    Keycloak(String serverUrl, String realm, String username, String password, String clientId, String clientSecret, ResteasyClient resteasyClient){
-        config = new Config(serverUrl, realm, username, password, clientId, clientSecret);
-        client = resteasyClient != null ? resteasyClient : new ResteasyClientBuilder().connectionPoolSize(10).build();
+    Keycloak(String serverUrl, String realm, String username, String password, String clientId, String clientSecret, String grantType, ResteasyClient resteasyClient) {
+        config = new Config(serverUrl, realm, username, password, clientId, clientSecret, grantType);
+        client = resteasyClient != null ? resteasyClient : new ResteasyClientBuilder().build();
 
         tokenManager = new TokenManager(config, client);
 
@@ -55,27 +55,27 @@ public class Keycloak {
         target.register(new BearerAuthFilter(tokenManager));
     }
 
-    public static Keycloak getInstance(String serverUrl, String realm, String username, String password, String clientId, String clientSecret){
-        return new Keycloak(serverUrl, realm, username, password, clientId, clientSecret, null);
+    public static Keycloak getInstance(String serverUrl, String realm, String username, String password, String clientId, String clientSecret) {
+        return new Keycloak(serverUrl, realm, username, password, clientId, clientSecret, PASSWORD, null);
     }
 
-    public static Keycloak getInstance(String serverUrl, String realm, String username, String password, String clientId){
-        return new Keycloak(serverUrl, realm, username, password, clientId, null, null);
+    public static Keycloak getInstance(String serverUrl, String realm, String username, String password, String clientId) {
+        return new Keycloak(serverUrl, realm, username, password, clientId, null, PASSWORD, null);
     }
 
-    public RealmsResource realms(){
+    public RealmsResource realms() {
         return target.proxy(RealmsResource.class);
     }
 
-    public RealmResource realm(String realmName){
+    public RealmResource realm(String realmName) {
         return realms().realm(realmName);
     }
 
-    public ServerInfoResource serverInfo(){
+    public ServerInfoResource serverInfo() {
         return target.proxy(ServerInfoResource.class);
     }
 
-    public TokenManager tokenManager(){
+    public TokenManager tokenManager() {
         return tokenManager;
     }
 
@@ -98,5 +98,4 @@ public class Keycloak {
     public void close() {
         client.close();
     }
-
 }
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/KeycloakBuilder.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/KeycloakBuilder.java
index 5a61ffb..e192d9a 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/KeycloakBuilder.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/KeycloakBuilder.java
@@ -20,15 +20,17 @@ package org.keycloak.admin.client;
 import org.jboss.resteasy.client.jaxrs.ResteasyClient;
 import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
 
+import static org.keycloak.OAuth2Constants.CLIENT_CREDENTIALS;
+import static org.keycloak.OAuth2Constants.PASSWORD;
+
 /**
  * Provides a {@link Keycloak} client builder with the ability to customize the underlying
  * {@link ResteasyClient RESTEasy client} used to communicate with the Keycloak server.
- *
+ * <p>
  * <p>Example usage with a connection pool size of 20:</p>
- *
  * <pre>
  *   Keycloak keycloak = KeycloakBuilder.builder()
- *     .serverUrl("https:/sso.example.com/auth")
+ *     .serverUrl("https://sso.example.com/auth")
  *     .realm("realm")
  *     .username("user")
  *     .password("pass")
@@ -37,6 +39,16 @@ import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
  *     .resteasyClient(new ResteasyClientBuilder().connectionPoolSize(20).build())
  *     .build();
  * </pre>
+ * <p>Example usage with grant_type=client_credentials</p>
+ * <pre>
+ *   Keycloak keycloak = KeycloakBuilder.builder()
+ *     .serverUrl("https://sso.example.com/auth")
+ *     .realm("example")
+ *     .grantType(OAuth2Constants.CLIENT_CREDENTIALS)
+ *     .clientId("client")
+ *     .clientSecret("secret")
+ *     .build();
+ * </pre>
  *
  * @author Scott Rossillo
  * @see ResteasyClientBuilder
@@ -48,6 +60,7 @@ public class KeycloakBuilder {
     private String password;
     private String clientId;
     private String clientSecret;
+    private String grantType = PASSWORD;
     private ResteasyClient resteasyClient;
 
     public KeycloakBuilder serverUrl(String serverUrl) {
@@ -60,6 +73,12 @@ public class KeycloakBuilder {
         return this;
     }
 
+    public KeycloakBuilder grantType(String grantType) {
+        Config.checkGrantType(grantType);
+        this.grantType = grantType;
+        return this;
+    }
+
     public KeycloakBuilder username(String username) {
         this.username = username;
         return this;
@@ -97,19 +116,25 @@ public class KeycloakBuilder {
             throw new IllegalStateException("realm required");
         }
 
-        if (username == null) {
-            throw new IllegalStateException("username required");
-        }
-
-        if (password == null) {
-            throw new IllegalStateException("password required");
+        if (PASSWORD.equals(grantType)) {
+            if (username == null) {
+                throw new IllegalStateException("username required");
+            }
+
+            if (password == null) {
+                throw new IllegalStateException("password required");
+            }
+        } else if (CLIENT_CREDENTIALS.equals(grantType)) {
+            if (clientSecret == null) {
+                throw new IllegalStateException("clientSecret required with grant_type=client_credentials");
+            }
         }
 
         if (clientId == null) {
             throw new IllegalStateException("clientId required");
         }
 
-        return new Keycloak(serverUrl, realm, username, password, clientId, clientSecret, resteasyClient);
+        return new Keycloak(serverUrl, realm, username, password, clientId, clientSecret, grantType, resteasyClient);
     }
 
     private KeycloakBuilder() {
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/token/TokenManager.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/token/TokenManager.java
index e325681..bb32dae 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/token/TokenManager.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/token/TokenManager.java
@@ -27,11 +27,12 @@ import org.keycloak.representations.AccessTokenResponse;
 import javax.ws.rs.BadRequestException;
 import javax.ws.rs.core.Form;
 
+import static org.keycloak.OAuth2Constants.*;
+
 /**
  * @author rodrigo.sasaki@icarros.com.br
  */
 public class TokenManager {
-
     private static final long DEFAULT_MIN_VALIDITY = 30;
 
     private AccessTokenResponse currentToken;
@@ -39,61 +40,67 @@ public class TokenManager {
     private long minTokenValidity = DEFAULT_MIN_VALIDITY;
     private final Config config;
     private final TokenService tokenService;
+    private final String accessTokenGrantType;
 
-    public TokenManager(Config config, ResteasyClient client){
+    public TokenManager(Config config, ResteasyClient client) {
         this.config = config;
         ResteasyWebTarget target = client.target(config.getServerUrl());
-        if(!config.isPublicClient()){
+        if (!config.isPublicClient()) {
             target.register(new BasicAuthFilter(config.getClientId(), config.getClientSecret()));
         }
-        tokenService = target.proxy(TokenService.class);
+        this.tokenService = target.proxy(TokenService.class);
+        this.accessTokenGrantType = config.getGrantType();
+
+        if (CLIENT_CREDENTIALS.equals(accessTokenGrantType) && config.isPublicClient()) {
+            throw new IllegalArgumentException("Can't use " + GRANT_TYPE + "=" + CLIENT_CREDENTIALS + " with public client");
+        }
     }
 
-    public String getAccessTokenString(){
+    public String getAccessTokenString() {
         return getAccessToken().getToken();
     }
 
-    public synchronized AccessTokenResponse getAccessToken(){
-        if(currentToken == null){
+    public synchronized AccessTokenResponse getAccessToken() {
+        if (currentToken == null) {
             grantToken();
-        }else if(tokenExpired()){
+        } else if (tokenExpired()) {
             refreshToken();
         }
         return currentToken;
     }
 
-    public AccessTokenResponse grantToken(){
-        Form form = new Form()
-                .param("grant_type", "password")
-                .param("username", config.getUsername())
+    public AccessTokenResponse grantToken() {
+        Form form = new Form().param(GRANT_TYPE, accessTokenGrantType);
+        if (PASSWORD.equals(accessTokenGrantType)) {
+            form.param("username", config.getUsername())
                 .param("password", config.getPassword());
+        }
 
-        if(config.isPublicClient()){
-            form.param("client_id", config.getClientId());
+        if (config.isPublicClient()) {
+            form.param(CLIENT_ID, config.getClientId());
         }
 
         int requestTime = Time.currentTime();
         synchronized (this) {
-            currentToken = tokenService.grantToken( config.getRealm(), form.asMap() );
+            currentToken = tokenService.grantToken(config.getRealm(), form.asMap());
             expirationTime = requestTime + currentToken.getExpiresIn();
         }
         return currentToken;
     }
 
-    public AccessTokenResponse refreshToken(){
-        Form form = new Form()
-                .param("grant_type", "refresh_token")
-                .param("refresh_token", currentToken.getRefreshToken());
+    public AccessTokenResponse refreshToken() {
+        Form form = new Form().param(GRANT_TYPE, REFRESH_TOKEN)
+                              .param(REFRESH_TOKEN, currentToken.getRefreshToken());
 
-        if(config.isPublicClient()){
-            form.param("client_id", config.getClientId());
+        if (config.isPublicClient()) {
+            form.param(CLIENT_ID, config.getClientId());
         }
 
         try {
             int requestTime = Time.currentTime();
 
             synchronized (this) {
-                currentToken = tokenService.refreshToken( config.getRealm(), form.asMap() );
+                currentToken = tokenService.refreshToken(config.getRealm(), form.asMap());
                 expirationTime = requestTime + currentToken.getExpiresIn();
             }
             return currentToken;