keycloak-aplcache

Merge pull request #149 from stianst/master Added oauth

1/10/2014 3:07:15 PM

Changes

Details

diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/index.html b/admin-ui/src/main/resources/META-INF/resources/admin/index.html
index a890c6a..3ef1734 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/index.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/index.html
@@ -11,7 +11,7 @@
     <link rel="stylesheet" href="/auth-server/admin-ui/css/reset.css">
     <link rel="stylesheet" href="/auth-server/admin-ui/bootstrap-3.0.0-wip/css/bootstrap.css">
     <link rel="stylesheet" href="/auth-server/admin-ui/css/sprites.css">
-    <link rel="stylesheet" href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic'>
+    <link rel="stylesheet" href='//fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic'>
 
     <!-- RCUE styles -->
     <link rel="stylesheet" href="/auth-server/admin-ui/css/base.css">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
index d903db0..25f7e36 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
@@ -396,7 +396,21 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'OAuthClientScopeMappingCtrl'
         })
-
+        .when('/realms/:realm/oauth-clients/:oauth/installation', {
+            templateUrl : 'partials/oauth-client-installation.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                oauth : function(OAuthClientLoader) {
+                    return OAuthClientLoader();
+                },
+                installation : function(OAuthClientInstallationLoader) {
+                    return OAuthClientInstallationLoader();
+                }
+            },
+            controller : 'OAuthClientInstallationCtrl'
+        })
         .when('/create/oauth-client/:realm', {
             templateUrl : 'partials/oauth-client-detail.html',
             resolve : {
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js
index a0a8cd9..b13bc32 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js
@@ -294,3 +294,11 @@ module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm, 
 
 
 });
+
+
+module.controller('OAuthClientInstallationCtrl', function($scope, realm, installation, oauth, OAuthClientInstallation, $routeParams) {
+    $scope.realm = realm;
+    $scope.oauth = oauth;
+    $scope.installation = installation;
+    $scope.download = OAuthClientInstallation.url({ realm: $routeParams.realm, oauth: $routeParams.oauth });
+});
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
index 7b72c48..e3d1746 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
@@ -152,3 +152,12 @@ module.factory('OAuthClientListLoader', function(Loader, OAuthClient, $route, $q
         }
     });
 });
+
+module.factory('OAuthClientInstallationLoader', function(Loader, OAuthClientInstallation, $route, $q) {
+    return Loader.get(OAuthClientInstallation, function() {
+        return {
+            realm : $route.current.params.realm,
+            oauth : $route.current.params.oauth
+        }
+    });
+});
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
index 0147362..5bccc4c 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
@@ -291,6 +291,22 @@ module.factory('OAuthClientApplicationScopeMapping', function($resource) {
     });
 });
 
+module.factory('OAuthClientInstallation', function($resource) {
+    var url = '/auth-server/rest/saas/admin/realms/:realm/oauth-clients/:oauth/installation';
+    var resource = $resource('/auth-server/rest/saas/admin/realms/:realm/oauth-clients/:oauth/installation', {
+        realm : '@realm',
+        oauth : '@oauth'
+    },  {
+        update : {
+            method : 'PUT'
+        }
+    });
+    resource.url = function(parameters) {
+        return url.replace(':realm', parameters.realm).replace(':oauth', parameters.oauth);
+    }
+    return resource;
+});
+
 
 module.factory('Current', function(Realm, $route) {
     var current = {};
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html
index 01d63c5..2605f53 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html
@@ -7,6 +7,7 @@
                     <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
                     <li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
                     <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
                 </ul>
             </div>
             <div id="content">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html
index 22427f3..5f3ac72 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html
@@ -7,6 +7,7 @@
                     <li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
                     <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
                     <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
                 </ul>
             </div>
             <div class="top-nav" data-ng-show="create">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html
new file mode 100755
index 0000000..94708a9
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html
@@ -0,0 +1,25 @@
+<div id="wrapper" class="container">
+    <div class="row">
+        <div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="'partials/realm-menu.html'"></div>
+        <div id="content-area" class="col-md-9" role="main">
+            <div class="top-nav" data-ng-show="!create">
+                <ul class="rcue-tabs">
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+                    <li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
+                </ul>
+            </div>
+            <div class="top-nav" data-ng-show="create">
+                <ul class="rcue-tabs">
+                    <li></li>
+                </ul>
+            </div>
+            <div id="content">
+                <a class="button primary" href="{{download}}" download="keycloak.json" type="submit">Download</a></br>
+                <textarea style="width: 100%;" rows="20" onclick="this.select()">{{installation | json}}</textarea>
+            </div>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html
index c2d0308..0d8e856 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html
@@ -7,6 +7,7 @@
                     <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
                     <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
                     <li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+                    <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
                 </ul>
             </div>
             <div id="content">
diff --git a/core/src/main/java/org/keycloak/representations/JsonWebToken.java b/core/src/main/java/org/keycloak/representations/JsonWebToken.java
index 3d7252a..c5ca3f1 100755
--- a/core/src/main/java/org/keycloak/representations/JsonWebToken.java
+++ b/core/src/main/java/org/keycloak/representations/JsonWebToken.java
@@ -22,8 +22,8 @@ public class JsonWebToken implements Serializable {
     protected String issuer;
     @JsonProperty("aud")
     protected String audience;
-    @JsonProperty("prn")
-    protected String principal;
+    @JsonProperty("sub")
+    protected String subject;
     @JsonProperty("typ")
     protected String type;
 
@@ -116,12 +116,12 @@ public class JsonWebToken implements Serializable {
         return this;
     }
 
-    public String getPrincipal() {
-        return principal;
+    public String getSubject() {
+        return subject;
     }
 
     public JsonWebToken principal(String principal) {
-        this.principal = principal;
+        this.subject = principal;
         return this;
     }
 
diff --git a/core/src/main/java/org/keycloak/RSATokenVerifier.java b/core/src/main/java/org/keycloak/RSATokenVerifier.java
index 56fe140..f4d6896 100755
--- a/core/src/main/java/org/keycloak/RSATokenVerifier.java
+++ b/core/src/main/java/org/keycloak/RSATokenVerifier.java
@@ -32,7 +32,7 @@ public class RSATokenVerifier {
         if (!token.isActive()) {
             throw new VerificationException("Token is not active.");
         }
-        String user = token.getPrincipal();
+        String user = token.getSubject();
         if (user == null) {
             throw new VerificationException("Token user was null");
         }
diff --git a/core/src/test/java/org/keycloak/RSAVerifierTest.java b/core/src/test/java/org/keycloak/RSAVerifierTest.java
index 0aacbc8..ca0f46f 100755
--- a/core/src/test/java/org/keycloak/RSAVerifierTest.java
+++ b/core/src/test/java/org/keycloak/RSAVerifierTest.java
@@ -97,7 +97,7 @@ public class RSAVerifierTest {
                 .rsa256(idpPair.getPrivate());
         SkeletonKeyToken token = verifySkeletonKeyToken(encoded);
         Assert.assertTrue(token.getResourceAccess("service").getRoles().contains("admin"));
-        Assert.assertEquals("CN=Client", token.getPrincipal());
+        Assert.assertEquals("CN=Client", token.getSubject());
     }
 
     private SkeletonKeyToken verifySkeletonKeyToken(String encoded) throws VerificationException {
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/styles.css b/forms/src/main/resources/META-INF/resources/forms/theme/default/styles.css
index 161be89..2bd23a0 100644
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/styles.css
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/styles.css
@@ -3,7 +3,7 @@
 @IMPORT url("css/forms.css");
 @IMPORT url("css/zocial/zocial.css");
 @IMPORT url("css/login-register.css");
-@IMPORT url("http://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic");
+@IMPORT url("//fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic");
 
 .zocial.google {
   background-color: #dd4b39 !important;
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java
index da95481..c75704f 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java
@@ -102,7 +102,7 @@ public class CatalinaBearerTokenAuthenticator {
             }
             surrogate = chain[0].getSubjectX500Principal().getName();
         }
-        SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate);
+        SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getSubject(), surrogate);
         principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles);
         request.setUserPrincipal(principal);
         request.setAuthType("OAUTH_BEARER");
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java
index b939d19..8cfbcb5 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java
@@ -65,11 +65,11 @@ public class CatalinaSecurityContextHelper {
     }
 
     /**
-     * Get the Principal given the authenticated Subject. Currently the first principal that is not of type {@code Group} is
-     * considered or the single principal inside the CallerPrincipal group.
+     * Get the Principal given the authenticated Subject. Currently the first subject that is not of type {@code Group} is
+     * considered or the single subject inside the CallerPrincipal group.
      *
      * @param subject
-     * @return the authenticated principal
+     * @return the authenticated subject
      */
     protected Principal getPrincipal(Subject subject) {
         Principal principal = null;
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java
index b8b0688..01eb9aa 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java
@@ -227,7 +227,7 @@ public class OAuthAuthenticatorValve extends FormAuthenticator implements Lifecy
                 SkeletonKeyToken.Access access = token.getRealmAccess();
                 if (access != null) roles.addAll(access.getRoles());
             }
-            SkeletonKeyPrincipal skp = new SkeletonKeyPrincipal(token.getPrincipal(), null);
+            SkeletonKeyPrincipal skp = new SkeletonKeyPrincipal(token.getSubject(), null);
             GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(context.getRealm(), skp, roles);
             Session session = request.getSessionInternal(true);
             session.setPrincipal(principal);
@@ -235,7 +235,7 @@ public class OAuthAuthenticatorValve extends FormAuthenticator implements Lifecy
             SkeletonKeySession skSession = new SkeletonKeySession(oauth.getTokenString(), token, realmConfiguration.getMetadata());
             session.setNote(SkeletonKeySession.class.getName(), skSession);
 
-            String username = token.getPrincipal();
+            String username = token.getSubject();
             log.debug("userSessionManage.login: " + username);
             userSessionManagement.login(session, username);
         }
diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java
index 319b5ac..6a5cb02 100755
--- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java
+++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java
@@ -71,7 +71,7 @@ public class JaxrsBearerTokenFilter implements ContainerRequestFilter {
             ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
             String callerPrincipal = securityContext.getUserPrincipal() != null ? securityContext.getUserPrincipal().getName() : null;
 
-            final SkeletonKeyPrincipal principal = new SkeletonKeyPrincipal(token.getPrincipal(), callerPrincipal);
+            final SkeletonKeyPrincipal principal = new SkeletonKeyPrincipal(token.getSubject(), callerPrincipal);
             final boolean isSecure = securityContext.isSecure();
             final SkeletonKeyToken.Access access;
             if (resourceMetadata.getResourceName() != null) {
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java
index 120546f..8f0df9d 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java
@@ -98,7 +98,7 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism 
     }
 
     protected SkeletonKeyPrincipal completeAuthentication(SecurityContext securityContext, SkeletonKeyToken token, String surrogate) {
-        final SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate);
+        final SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getSubject(), surrogate);
         Set<String> roles = null;
         if (adapterConfig.isUseResourceRoleMappings()) {
             SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index a42b93a..6b6545b 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -172,7 +172,7 @@ public class AuthenticationManager {
 
             Auth auth = new Auth(token);
 
-            UserModel user = realm.getUser(token.getPrincipal());
+            UserModel user = realm.getUser(token.getSubject());
             if (user == null || !user.isEnabled()) {
                 logger.debug("Unknown user in identity cookie");
                 expireIdentityCookie(realm, uriInfo);
@@ -219,7 +219,7 @@ public class AuthenticationManager {
 
             Auth auth = new Auth(token);
 
-            UserModel user = realm.getUser(token.getPrincipal());
+            UserModel user = realm.getUser(token.getSubject());
             if (user == null || !user.isEnabled()) {
                 throw new NotAuthorizedException("invalid_user");
             }
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 651db2f..fa99940 100755
--- a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
@@ -1,17 +1,23 @@
 package org.keycloak.services.managers;
 
+import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.representations.adapters.config.BaseAdapterConfig;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.OAuthClientRepresentation;
+import org.keycloak.services.resources.flows.Urls;
 
+import java.net.URI;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -76,4 +82,26 @@ public class OAuthClientManager {
         }
         return rep;
     }
+
+    public BaseAdapterConfig toInstallationRepresentation(RealmModel realmModel, OAuthClientModel model, URI baseUri) {
+        BaseAdapterConfig rep = new BaseAdapterConfig();
+        rep.setRealm(realmModel.getId());
+        rep.setRealmKey(realmModel.getPublicKeyPem());
+        rep.setSslNotRequired(realmModel.isSslNotRequired());
+
+        rep.setAuthUrl(Urls.realmLoginPage(baseUri, realmModel.getId()).toString());
+        rep.setCodeUrl(Urls.realmCode(baseUri, realmModel.getId()).toString());
+        rep.setUseResourceRoleMappings(false);
+
+        rep.setResource(model.getOAuthAgent().getLoginName());
+
+        Map<String, String> creds = new HashMap<String, String>();
+        creds.put(CredentialRepresentation.PASSWORD, "INSERT CLIENT PASSWORD");
+        if (model.getOAuthAgent().isTotp()) {
+            creds.put(CredentialRepresentation.TOTP, "INSERT CLIENT TOTP");
+        }
+        rep.setCredentials(creds);
+
+        return rep;
+    }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
index 138bc3a..4cafbc7 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
@@ -6,10 +6,13 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserCredentialModel;
+import org.keycloak.representations.adapters.config.BaseAdapterConfig;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.OAuthClientRepresentation;
+import org.keycloak.services.managers.ApplicationManager;
 import org.keycloak.services.managers.OAuthClientManager;
 import org.keycloak.services.managers.RealmManager;
+import org.keycloak.util.JsonSerialization;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -17,7 +20,10 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
 import java.util.List;
 
 /**
@@ -29,6 +35,8 @@ public class OAuthClientResource  {
     protected RealmModel realm;
     protected OAuthClientModel oauthClient;
     protected KeycloakSession session;
+    @Context
+    protected UriInfo uriInfo;
 
     public OAuthClientResource(RealmModel realm, OAuthClientModel oauthClient, KeycloakSession session) {
         this.realm = realm;
@@ -51,6 +59,18 @@ public class OAuthClientResource  {
         return OAuthClientManager.toRepresentation(oauthClient);
     }
 
+    @GET
+    @NoCache
+    @Path("installation")
+    @Produces(MediaType.APPLICATION_JSON)
+    public String getInstallation() throws IOException {
+        OAuthClientManager manager = new OAuthClientManager(realm);
+        BaseAdapterConfig rep = manager.toInstallationRepresentation(realm, oauthClient, uriInfo.getBaseUri());
+
+        // TODO Temporary solution to pretty-print
+        return JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep);
+    }
+
     @DELETE
     @NoCache
     public void deleteOAuthClient() {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
index 6e4101b..eaacae6 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
@@ -15,6 +15,7 @@ import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.container.ResourceContext;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -32,6 +33,9 @@ public class OAuthClientsResource {
 
     protected KeycloakSession session;
 
+    @Context
+    protected ResourceContext resourceContext;
+
     public OAuthClientsResource(RealmModel realm, KeycloakSession session) {
         this.realm = realm;
         this.session = session;
@@ -64,6 +68,7 @@ public class OAuthClientsResource {
             throw new NotFoundException();
         }
         OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, oauth, session);
+        resourceContext.initResource(oAuthClientResource);
         return oAuthClientResource;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index a7f06ce..ab8cc39 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -43,6 +43,7 @@ public class RealmAdminResource extends RoleContainerResource {
     @Path("oauth-clients")
     public OAuthClientsResource getOAuthClients() {
         OAuthClientsResource oauth = new OAuthClientsResource(realm, session);
+        resourceContext.initResource(oauth);
         return oauth;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java
index 37cbec3..36bd3f4 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -32,6 +32,7 @@ import org.keycloak.services.validation.Validation;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
+import javax.ws.rs.NotAcceptableException;
 import javax.ws.rs.NotAuthorizedException;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -129,6 +130,10 @@ public class TokenService {
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     @Produces(MediaType.APPLICATION_JSON)
     public Response grantIdentityToken(final MultivaluedMap<String, String> form) {
+        if (!checkSsl()) {
+            throw new NotAcceptableException("HTTPS required");
+        }
+
         String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
         if (username == null) {
             throw new NotAuthorizedException("No user");
@@ -155,6 +160,10 @@ public class TokenService {
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     @Produces(MediaType.APPLICATION_JSON)
     public Response grantAccessToken(final MultivaluedMap<String, String> form) {
+        if (!checkSsl()) {
+            throw new NotAcceptableException("HTTPS required");
+        }
+
         String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
         if (username == null) {
             throw new NotAuthorizedException("No user");
@@ -187,6 +196,10 @@ public class TokenService {
         logger.debug("TokenService.processLogin");
         OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
 
+        if (!checkSsl()) {
+            return oauth.forwardToSecurityFailure("HTTPS required");
+        }
+
         if (!realm.isEnabled()) {
             return oauth.forwardToSecurityFailure("Realm not enabled.");
         }
@@ -360,6 +373,11 @@ public class TokenService {
     @Produces("application/json")
     public Response accessCodeToToken(final MultivaluedMap<String, String> formData) {
         logger.debug("accessRequest <---");
+
+        if (!checkSsl()) {
+            throw new NotAcceptableException("HTTPS required");
+        }
+
         if (!realm.isEnabled()) {
             throw new NotAuthorizedException("Realm not enabled");
         }
@@ -480,6 +498,10 @@ public class TokenService {
         logger.info("TokenService.loginPage");
         OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
 
+        if (!checkSsl()) {
+            return oauth.forwardToSecurityFailure("HTTPS required");
+        }
+
         if (!realm.isEnabled()) {
             logger.warn("Realm not enabled");
             return oauth.forwardToSecurityFailure("Realm not enabled");
@@ -529,6 +551,10 @@ public class TokenService {
         logger.info("**********registerPage()");
         OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
 
+        if (!checkSsl()) {
+            return oauth.forwardToSecurityFailure("HTTPS required");
+        }
+
         if (!realm.isEnabled()) {
             logger.warn("Realm not enabled");
             return oauth.forwardToSecurityFailure("Realm not enabled");
@@ -581,6 +607,10 @@ public class TokenService {
     public Response processOAuth(final MultivaluedMap<String, String> formData) {
         OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
 
+        if (!checkSsl()) {
+            return oauth.forwardToSecurityFailure("HTTPS required");
+        }
+
         String code = formData.getFirst("code");
         JWSInput input = new JWSInput(code);
         boolean verifiedCode = false;
@@ -628,4 +658,20 @@ public class TokenService {
         }
     }
 
+    private boolean checkSsl() {
+        if (realm.isSslNotRequired()) {
+            return true;
+        }
+
+        if (uriInfo.getBaseUri().getScheme().equals("https")) {
+            return true;
+        }
+
+        if ("https".equals(headers.getHeaderString("X-Forwarded-Proto"))) {
+            return true;
+        }
+
+        return false;
+    }
+
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
index 0b25e48..2dfdde3 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
@@ -69,7 +69,7 @@ public class AccessTokenTest {
 
         SkeletonKeyToken token = oauth.verifyToken(response.getAccessToken());
 
-        Assert.assertEquals("test-user@localhost", token.getPrincipal());
+        Assert.assertEquals("test-user@localhost", token.getSubject());
 
         Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
         Assert.assertTrue(token.getRealmAccess().isUserInRole("user"));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java
index e4c3c6f..d247d39 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java
@@ -102,7 +102,7 @@ public class SocialLoginTest {
 
         SkeletonKeyToken token = oauth.verifyToken(response.getAccessToken());
 
-        Assert.assertEquals("dummy-user", token.getPrincipal());
+        Assert.assertEquals("dummy-user", token.getSubject());
     }
 
     @Test