keycloak-aplcache

Details

diff --git a/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java
index 4f1f2ea..20cc452 100755
--- a/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java
@@ -15,34 +15,22 @@ import java.security.PublicKey;
  */
 public class PublishedRealmRepresentation {
     protected String realm;
-    protected String self;
 
     @JsonProperty("public_key")
     protected String publicKeyPem;
 
-    @JsonProperty("authorization")
-    protected String authorizationUrl;
+    @JsonProperty("token-service")
+    protected String tokenServiceUrl;
 
-    @JsonProperty("codes")
-    protected String codeUrl;
+    @JsonProperty("account-service")
+    protected String accountServiceUrl;
 
-    @JsonProperty("grants")
-    protected String grantUrl;
-
-    @JsonProperty("admin-role")
-    protected String adminRole;
+    @JsonProperty("admin-api")
+    protected String adminApiUrl;
 
     @JsonIgnore
     protected volatile transient PublicKey publicKey;
 
-    public String getAdminRole() {
-        return adminRole;
-    }
-
-    public void setAdminRole(String adminRole) {
-        this.adminRole = adminRole;
-    }
-
     public String getRealm() {
         return realm;
     }
@@ -51,14 +39,6 @@ public class PublishedRealmRepresentation {
         this.realm = realm;
     }
 
-    public String getSelf() {
-        return self;
-    }
-
-    public void setSelf(String self) {
-        this.self = self;
-    }
-
     public String getPublicKeyPem() {
         return publicKeyPem;
     }
@@ -97,28 +77,27 @@ public class PublishedRealmRepresentation {
         this.publicKeyPem = PemUtils.removeBeginEnd(s);
     }
 
-
-    public String getAuthorizationUrl() {
-        return authorizationUrl;
+    public String getTokenServiceUrl() {
+        return tokenServiceUrl;
     }
 
-    public void setAuthorizationUrl(String authorizationUrl) {
-        this.authorizationUrl = authorizationUrl;
+    public void setTokenServiceUrl(String tokenServiceUrl) {
+        this.tokenServiceUrl = tokenServiceUrl;
     }
 
-    public String getCodeUrl() {
-        return codeUrl;
+    public String getAccountServiceUrl() {
+        return accountServiceUrl;
     }
 
-    public void setCodeUrl(String codeUrl) {
-        this.codeUrl = codeUrl;
+    public void setAccountServiceUrl(String accountServiceUrl) {
+        this.accountServiceUrl = accountServiceUrl;
     }
 
-    public String getGrantUrl() {
-        return grantUrl;
+    public String getAdminApiUrl() {
+        return adminApiUrl;
     }
 
-    public void setGrantUrl(String grantUrl) {
-        this.grantUrl = grantUrl;
+    public void setAdminApiUrl(String adminApiUrl) {
+        this.adminApiUrl = adminApiUrl;
     }
 }
diff --git a/docbook/reference/en/en-US/modules/Overview.xml b/docbook/reference/en/en-US/modules/Overview.xml
index 3910cea..980c581 100755
--- a/docbook/reference/en/en-US/modules/Overview.xml
+++ b/docbook/reference/en/en-US/modules/Overview.xml
@@ -49,6 +49,9 @@
                 OAuth 2.0 Grant requests
             </listitem>
             <listitem>
+                OpenID Connect Support.
+            </listitem>
+            <listitem>
                 CORS Support
             </listitem>
             <listitem>
diff --git a/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java b/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
index 9ab51b2..f848909 100755
--- a/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
+++ b/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
@@ -5,6 +5,7 @@ import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.HttpGet;
 import org.keycloak.adapters.TokenGrantRequest;
+import org.keycloak.representations.AccessTokenResponse;
 import org.keycloak.servlet.ServletOAuthClient;
 import org.keycloak.util.JsonSerialization;
 
@@ -50,7 +51,7 @@ public class ProductDatabaseClient {
 
     static class TypedList extends ArrayList<String> {}
 
-    public static List<String> getProducts(HttpServletRequest request) throws Failure {
+    public static AccessTokenResponse getTokenResponse(HttpServletRequest request) {
         // The ServletOAuthClient is obtained by getting a context attribute
         // that is set in the Bootstrap context listener in this project.
         // You really should come up with a better way to initialize
@@ -59,17 +60,26 @@ public class ProductDatabaseClient {
         ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
         String token = null;
         try {
-            token = oAuthClient.getBearerToken(request).getToken();
+            return oAuthClient.getBearerToken(request);
         } catch (IOException e) {
             throw new RuntimeException(e);
         } catch (TokenGrantRequest.HttpFailure failure) {
             throw new RuntimeException(failure);
         }
 
+    }
+
+    public static List<String> getProducts(HttpServletRequest request, String accessToken) throws Failure {
+        // The ServletOAuthClient is obtained by getting a context attribute
+        // that is set in the Bootstrap context listener in this project.
+        // You really should come up with a better way to initialize
+        // and obtain the ServletOAuthClient.  I actually suggest downloading the ServletOAuthClient code
+        // and take a look how it works. You can also take a look at third-party-cdi example
+        ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
         HttpClient client = oAuthClient.getClient();
 
         HttpGet get = new HttpGet("http://localhost:8080/database/products");
-        get.addHeader("Authorization", "Bearer " + token);
+        get.addHeader("Authorization", "Bearer " + accessToken);
         try {
             HttpResponse response = client.execute(get);
             if (response.getStatusLine().getStatusCode() != 200) {
diff --git a/examples/demo-template/third-party/src/main/webapp/pull_data.jsp b/examples/demo-template/third-party/src/main/webapp/pull_data.jsp
index 0ccfbcb..6d998b7 100755
--- a/examples/demo-template/third-party/src/main/webapp/pull_data.jsp
+++ b/examples/demo-template/third-party/src/main/webapp/pull_data.jsp
@@ -1,4 +1,7 @@
 <%@ page import="org.keycloak.example.oauth.ProductDatabaseClient" %>
+<%@ page import="org.keycloak.representations.AccessTokenResponse" %>
+<%@ page import="org.keycloak.representations.IDToken" %>
+<%@ page import="org.keycloak.servlet.ServletOAuthClient" %>
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"%>
 <html>
@@ -6,17 +9,33 @@
     <title>Pull Page</title>
 </head>
 <body>
-<h2>Pulled Product Listing</h2>
 <%
     java.util.List<String> list = null;
     try {
-        list = ProductDatabaseClient.getProducts(request);
+        AccessTokenResponse tokenResponse = ProductDatabaseClient.getTokenResponse(request);
+        if (tokenResponse.getIdToken() != null) {
+            IDToken idToken = ServletOAuthClient.extractIdToken(tokenResponse.getIdToken());
+            out.println("<p><i>Change client claims in admin console to view personal info of user</i></p>");
+            if (idToken.getPreferredUsername() != null) {
+                out.println("<p>Username: " + idToken.getPreferredUsername() + "</p>");
+            }
+            if (idToken.getName() != null) {
+                out.println("<p>Full Name: " + idToken.getName() + "</p>");
+            }
+            if (idToken.getEmail() != null) {
+                out.println("<p>Email: " + idToken.getEmail() + "</p>");
+            }
+        }
+        list = ProductDatabaseClient.getProducts(request, tokenResponse.getToken());
     } catch (ProductDatabaseClient.Failure failure) {
         out.println("There was a failure processing request.  You either didn't configure Keycloak properly, or maybe" +
                 "you just forgot to secure the database service?");
         out.println("Status from database service invocation was: " + failure.getStatus());
         return;
     }
+%>
+<h2>Pulled Product Listing</h2>
+<%
     for (String prod : list)
 {
    out.print("<p>");
diff --git a/forms/common-themes/src/main/resources/theme/login/base/login-oauth-grant.ftl b/forms/common-themes/src/main/resources/theme/login/base/login-oauth-grant.ftl
index 5ca5a02..a44b2c7 100755
--- a/forms/common-themes/src/main/resources/theme/login/base/login-oauth-grant.ftl
+++ b/forms/common-themes/src/main/resources/theme/login/base/login-oauth-grant.ftl
@@ -9,6 +9,16 @@
         <div id="kc-oauth" class="content-area">
             <h3><strong>${oauth.client}</strong> ${rb.oauthGrantRequest}</h3>
             <ul>
+                <#if oauth.claimsRequested??>
+                    <li>
+                        <span>
+                        Personal Info:&nbsp;
+                            <#list oauth.claimsRequested as claim>
+                                ${claim}&nbsp;
+                            </#list>
+                        </span>
+                    </li>
+                </#if>
                 <#list oauth.realmRolesRequested as role>
                     <li>
                         <span><#if role.description??>${role.description}<#else>${role.name}</#if></span>
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java
index 94fdf8f..664b25b 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java
@@ -21,12 +21,14 @@
  */
 package org.keycloak.login.freemarker.model;
 
+import org.keycloak.models.ClaimMask;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 
 import javax.ws.rs.core.MultivaluedMap;
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -38,6 +40,7 @@ public class OAuthGrantBean {
     private MultivaluedMap<String, RoleModel> resourceRolesRequested;
     private String code;
     private ClientModel client;
+    private List<String> claimsRequested;
     private String oAuthCode;
     private String action;
 
@@ -46,6 +49,41 @@ public class OAuthGrantBean {
         this.client = client;
         this.realmRolesRequested = realmRolesRequested;
         this.resourceRolesRequested = resourceRolesRequested;
+
+        // todo support locale
+        List<String> claims = new LinkedList<String>();
+        long mask = client.getAllowedClaimsMask();
+        if (ClaimMask.hasEmail(mask)) {
+            claims.add("email");
+        }
+        if (ClaimMask.hasUsername(mask)) {
+            claims.add("username");
+        }
+        if (ClaimMask.hasName(mask)) {
+            claims.add("name");
+        }
+        if (ClaimMask.hasGender(mask)) {
+            claims.add("gender");
+        }
+        if (ClaimMask.hasAddress(mask)) {
+            claims.add("address");
+        }
+        if (ClaimMask.hasPhone(mask)) {
+            claims.add("phone");
+        }
+        if (ClaimMask.hasPicture(mask)) {
+            claims.add("picture");
+        }
+        if (ClaimMask.hasProfile(mask)) {
+            claims.add("profile page");
+        }
+        if (ClaimMask.hasLocale(mask)) {
+            claims.add("locale");
+        }
+        if (ClaimMask.hasWebsite(mask)) {
+            claims.add("website");
+        }
+        if (claims.size() > 0) this.claimsRequested = claims;
     }
 
     public String getCode() {
@@ -64,4 +102,7 @@ public class OAuthGrantBean {
         return client.getClientId();
     }
 
+    public List<String> getClaimsRequested() {
+        return claimsRequested;
+    }
 }
diff --git a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java
index 44c0b9c..365d469 100755
--- a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java
+++ b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java
@@ -4,7 +4,9 @@ import org.apache.http.client.HttpClient;
 import org.keycloak.AbstractOAuthClient;
 import org.keycloak.adapters.HttpClientBuilder;
 import org.keycloak.adapters.TokenGrantRequest;
+import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.IDToken;
 import org.keycloak.util.KeycloakUriBuilder;
 
 import javax.servlet.http.Cookie;
@@ -156,5 +158,15 @@ public class ServletOAuthClient extends AbstractOAuthClient {
         return TokenGrantRequest.invokeRefresh(client, refreshToken, refreshUrl, clientId, credentials);
     }
 
+    public static IDToken extractIdToken(String idToken) {
+        if (idToken == null) return null;
+        JWSInput input = new JWSInput(idToken);
+        try {
+            return input.readJsonContent(IDToken.class);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
 
 }
diff --git a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
index c8e7a84..7ed6f05 100755
--- a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
@@ -51,10 +51,7 @@ public class OAuthClientManager {
         model.setSecret(rep.getSecret());
         if (rep.getClaims() != null) {
             ClaimManager.setClaims(model, rep.getClaims());
-        } else {
-            model.setAllowedClaimsMask(ClaimMask.USERNAME);
         }
-
         return model;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 19f0071..3814691 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -74,6 +74,12 @@ public class AccountService {
         this.authManager =  new AppAuthManager("KEYCLOAK_ACCOUNT_IDENTITY", tokenManager);
     }
 
+    public static UriBuilder accountServiceBaseUrl(UriInfo uriInfo) {
+        UriBuilder base = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
+        return base;
+    }
+
+
     private Response forwardToPage(String path, AccountPages page) {
         Auth auth = getAuth(false);
         if (auth != null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
index 0b1aa12..afe2317 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
@@ -17,6 +17,7 @@ import org.keycloak.services.managers.AppAuthManager;
 import org.keycloak.services.managers.Auth;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.TokenManager;
+import org.keycloak.services.resources.RealmsResource;
 import org.keycloak.services.resources.TokenService;
 import org.keycloak.services.resources.flows.Flows;
 
@@ -75,6 +76,12 @@ public class AdminService {
         this.authManager = new AppAuthManager("KEYCLOAK_ADMIN_CONSOLE_IDENTITY", tokenManager);
     }
 
+    public static UriBuilder adminApiUrl(UriInfo uriInfo) {
+        UriBuilder base = uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "getRealmsAdmin").path(RealmsAdminResource.class, "getRealmAdmin");
+        return base;
+    }
+
+
     public static class WhoAmI {
         protected String userId;
         protected String displayName;
diff --git a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
index 944f1a9..81f12a2 100755
--- a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
@@ -4,6 +4,7 @@ import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.logging.Logger;
 import org.keycloak.models.RealmModel;
 import org.keycloak.representations.idm.PublishedRealmRepresentation;
+import org.keycloak.services.resources.admin.AdminService;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
@@ -19,7 +20,6 @@ import javax.ws.rs.core.UriInfo;
  */
 public class PublicRealmResource {
     protected static final  Logger logger = Logger.getLogger(PublicRealmResource.class);
-    public static final String ADMIN_ROLE = "$REALM-ADMIN$";
 
     @Context
     protected UriInfo uriInfo;
@@ -30,12 +30,6 @@ public class PublicRealmResource {
         this.realm = realm;
     }
 
-    public static UriBuilder realmUrl(UriInfo uriInfo) {
-        UriBuilder base = uriInfo.getBaseUriBuilder()
-                .path(RealmsResource.class).path(RealmsResource.class, "getRealmResource");
-        return base;
-    }
-
     @GET
     @NoCache
     @Produces("application/json")
@@ -43,38 +37,13 @@ public class PublicRealmResource {
         return realmRep(realm, uriInfo);
     }
 
-    @GET
-    @NoCache
-    @Path("html")
-    @Produces("text/html")
-    public String getRealmHtml(@PathParam("realm") String id) {
-        StringBuffer html = new StringBuffer();
-
-        String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getName()).toString();
-        String codeUri = TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getName()).toString();
-        String grantUrl = TokenService.grantAccessTokenUrl(uriInfo).build(realm.getName()).toString();
-
-        html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>");
-        html.append("<p>auth: ").append(authUri).append("</p>");
-        html.append("<p>code: ").append(codeUri).append("</p>");
-        html.append("<p>grant: ").append(grantUrl).append("</p>");
-        html.append("<p>public key: ").append(realm.getPublicKeyPem()).append("</p>");
-        html.append("</body></html>");
-
-        return html.toString();
-    }
-
-
     public static PublishedRealmRepresentation realmRep(RealmModel realm, UriInfo uriInfo) {
         PublishedRealmRepresentation rep = new PublishedRealmRepresentation();
         rep.setRealm(realm.getName());
-        rep.setSelf(realmUrl(uriInfo).build(realm.getId()).toString());
+        rep.setTokenServiceUrl(TokenService.tokenServiceBaseUrl(uriInfo).build(realm.getId()).toString());
+        rep.setAccountServiceUrl(AccountService.accountServiceBaseUrl(uriInfo).build(realm.getId()).toString());
+        rep.setAdminApiUrl(AdminService.adminApiUrl(uriInfo).build(realm.getId()).toString());
         rep.setPublicKeyPem(realm.getPublicKeyPem());
-        rep.setAdminRole(ADMIN_ROLE);
-
-        rep.setAuthorizationUrl(TokenService.loginPageUrl(uriInfo).build(realm.getName()).toString());
-        rep.setCodeUrl(TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getName()).toString());
-        rep.setGrantUrl(TokenService.grantAccessTokenUrl(uriInfo).build(realm.getName()).toString());
         return rep;
     }