keycloak-uncached
Changes
adapters/oidc/js/pom.xml 19(+19 -0)
Details
adapters/oidc/js/pom.xml 19(+19 -0)
diff --git a/adapters/oidc/js/pom.xml b/adapters/oidc/js/pom.xml
index 315f4b7..b03ccea 100755
--- a/adapters/oidc/js/pom.xml
+++ b/adapters/oidc/js/pom.xml
@@ -58,6 +58,25 @@
<goal>minify</goal>
</goals>
</execution>
+ <execution>
+ <id>min-authz-js</id>
+ <phase>compile</phase>
+ <configuration>
+ <charset>utf-8</charset>
+ <webappSourceDir>${basedir}/src/main/resources</webappSourceDir>
+ <jsSourceDir>.</jsSourceDir>
+ <jsSourceFiles>
+ <jsSourceFile>keycloak-authz.js</jsSourceFile>
+ </jsSourceFiles>
+
+ <webappTargetDir>${project.build.directory}/classes</webappTargetDir>
+ <jsTargetDir>.</jsTargetDir>
+ <jsFinalFile>keycloak-authz.js</jsFinalFile>
+ </configuration>
+ <goals>
+ <goal>minify</goal>
+ </goals>
+ </execution>
</executions>
</plugin>
</plugins>
diff --git a/adapters/oidc/js/src/main/resources/keycloak-authz.js b/adapters/oidc/js/src/main/resources/keycloak-authz.js
new file mode 100644
index 0000000..7658352
--- /dev/null
+++ b/adapters/oidc/js/src/main/resources/keycloak-authz.js
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+(function( window, undefined ) {
+
+ var KeycloakAuthorization = function (keycloak) {
+ var _instance = this;
+ this.rpt = null;
+
+ this.init = function () {
+ var request = new XMLHttpRequest();
+
+ request.open('GET', keycloak.authServerUrl + '/realms/' + keycloak.realm + '/.well-known/uma-configuration');
+ request.onreadystatechange = function () {
+ if (request.readyState == 4) {
+ if (request.status == 200) {
+ _instance.config = JSON.parse(request.responseText);
+ } else {
+ console.error('Could not obtain configuration from server.');
+ }
+ }
+ }
+
+ request.send(null);
+ };
+
+ /**
+ * This method enables client applications to better integrate with resource servers protected by a Keycloak
+ * policy enforcer.
+ *
+ * In this case, the resource server will respond with a 401 status code and a WWW-Authenticate header holding the
+ * necessary information to ask a Keycloak server for authorization data using both UMA and Entitlement protocol,
+ * depending on how the policy enforcer at the resource server was configured.
+ */
+ this.authorize = function (wwwAuthenticateHeader) {
+ this.then = function (onGrant, onDeny, onError) {
+ if (wwwAuthenticateHeader.startsWith('UMA')) {
+ var params = wwwAuthenticateHeader.split(',');
+
+ for (i = 0; i < params.length; i++) {
+ var param = params[i].split('=');
+
+ if (param[0] == 'ticket') {
+ var request = new XMLHttpRequest();
+
+ request.open('POST', _instance.config.rpt_endpoint, true);
+ request.setRequestHeader('Content-Type', 'application/json')
+ request.setRequestHeader('Authorization', 'Bearer ' + keycloak.token)
+
+ request.onreadystatechange = function () {
+ if (request.readyState == 4) {
+ var status = request.status;
+
+ if (status >= 200 && status < 300) {
+ var rpt = JSON.parse(request.responseText).rpt;
+ _instance.rpt = rpt;
+ onGrant(rpt);
+ } else if (status == 403) {
+ if (onDeny) {
+ onDeny();
+ } else {
+ console.error('Authorization request was denied by the server.');
+ }
+ } else {
+ if (onError) {
+ onError();
+ } else {
+ console.error('Could not obtain authorization data from server.');
+ }
+ }
+ }
+ };
+
+ var ticket = param[1].substring(1, param[1].length - 1).trim();
+
+ request.send(JSON.stringify(
+ {
+ ticket: ticket,
+ rpt: _instance.rpt
+ }
+ ));
+ }
+ }
+ } else if (wwwAuthenticateHeader.startsWith('KC_ETT')) {
+ var params = wwwAuthenticateHeader.substring('KC_ETT'.length).trim().split(',');
+ var clientId = null;
+
+ for (i = 0; i < params.length; i++) {
+ var param = params[i].split('=');
+
+ if (param[0] == 'realm') {
+ clientId = param[1].substring(1, param[1].length - 1).trim();
+ }
+ }
+
+ _instance.entitlement(clientId).then(onGrant, onDeny, onError);
+ }
+ };
+
+ /**
+ * Obtains all entitlements from a Keycloak Server based on a give resourceServerId.
+ */
+ this.entitlement = function (resourceSeververId) {
+ this.then = function (onGrant, onDeny, onError) {
+ var request = new XMLHttpRequest();
+
+ request.open('GET', keycloak.authServerUrl + '/realms/' + keycloak.realm + '/authz/entitlement/' + resourceSeververId, true);
+ request.setRequestHeader('Authorization', 'Bearer ' + keycloak.token)
+
+ request.onreadystatechange = function () {
+ if (request.readyState == 4) {
+ var status = request.status;
+
+ if (status >= 200 && status < 300) {
+ var rpt = JSON.parse(request.responseText).rpt;
+ _instance.rpt = rpt;
+ onGrant(rpt);
+ } else if (status == 403) {
+ if (onDeny) {
+ onDeny();
+ } else {
+ console.error('Authorization request was denied by the server.');
+ }
+ } else {
+ if (onError) {
+ onError();
+ } else {
+ console.error('Could not obtain authorization data from server.');
+ }
+ }
+ }
+ };
+
+ request.send(null);
+ };
+
+ return this;
+ };
+
+ return this;
+ };
+
+ this.init(this);
+ };
+
+ if ( typeof module === "object" && module && typeof module.exports === "object" ) {
+ module.exports = KeycloakAuthorization;
+ } else {
+ window.KeycloakAuthorization = KeycloakAuthorization;
+
+ if ( typeof define === "function" && define.amd ) {
+ define( "keycloak-authorization", [], function () { return KeycloakAuthorization; } );
+ }
+ }
+})( window );
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/services/resources/JsResource.java b/services/src/main/java/org/keycloak/services/resources/JsResource.java
index 32161a4..c74abf0 100755
--- a/services/src/main/java/org/keycloak/services/resources/JsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/JsResource.java
@@ -44,55 +44,90 @@ public class JsResource {
@GET
@Path("/keycloak.js")
@Produces("text/javascript")
- public Response getJs() {
- InputStream inputStream = getClass().getClassLoader().getResourceAsStream("keycloak.js");
- if (inputStream != null) {
- CacheControl cacheControl = new CacheControl();
- cacheControl.setNoTransform(false);
- cacheControl.setMaxAge(Config.scope("theme").getInt("staticMaxAge", -1));
+ public Response getKeycloakJs() {
+ return getJs("keycloak.js");
+ }
- return Response.ok(inputStream).type("text/javascript").cacheControl(cacheControl).build();
- } else {
+ @GET
+ @Path("/{version}/keycloak.js")
+ @Produces("text/javascript")
+ public Response getKeycloakJsWithVersion(@PathParam("version") String version) {
+ if (!version.equals(Version.RESOURCES_VERSION)) {
return Response.status(Response.Status.NOT_FOUND).build();
}
+
+ return getKeycloakJs();
}
@GET
- @Path("/{version}/keycloak.js")
+ @Path("/keycloak.min.js")
+ @Produces("text/javascript")
+ public Response getKeycloakMinJs() {
+ return getJs("keycloak.min.js");
+ }
+
+ @GET
+ @Path("/{version}/keycloak.min.js")
@Produces("text/javascript")
- public Response getJsWithVersion(@PathParam("version") String version) {
+ public Response getKeycloakMinJsWithVersion(@PathParam("version") String version) {
if (!version.equals(Version.RESOURCES_VERSION)) {
return Response.status(Response.Status.NOT_FOUND).build();
}
- return getJs();
+ return getKeycloakMinJs();
}
+ /**
+ * Get keycloak-authz.js file for javascript clients
+ *
+ * @return
+ */
@GET
- @Path("/keycloak.min.js")
+ @Path("/keycloak-authz.js")
@Produces("text/javascript")
- public Response getMinJs() {
- InputStream inputStream = getClass().getClassLoader().getResourceAsStream("keycloak.min.js");
- if (inputStream != null) {
- CacheControl cacheControl = new CacheControl();
- cacheControl.setNoTransform(false);
- cacheControl.setMaxAge(Config.scope("theme").getInt("staticMaxAge", -1));
+ public Response getKeycloakAuthzJs() {
+ return getJs("keycloak-authz.js");
+ }
- return Response.ok(inputStream).type("text/javascript").cacheControl(cacheControl).build();
- } else {
+ @GET
+ @Path("/{version}/keycloak-authz.js")
+ @Produces("text/javascript")
+ public Response getKeycloakAuthzJsWithVersion(@PathParam("version") String version) {
+ if (!version.equals(Version.RESOURCES_VERSION)) {
return Response.status(Response.Status.NOT_FOUND).build();
}
+
+ return getKeycloakAuthzJs();
}
@GET
- @Path("/{version}/keycloak.min.js")
+ @Path("/keycloak-authz.min.js")
@Produces("text/javascript")
- public Response getMinJsWithVersion(@PathParam("version") String version) {
+ public Response getKeycloakAuthzMinJs() {
+ return getJs("keycloak-authz.min.js");
+ }
+
+ @GET
+ @Path("/{version}/keycloak-authz.min.js")
+ @Produces("text/javascript")
+ public Response getKeycloakAuthzMinJsWithVersion(@PathParam("version") String version) {
if (!version.equals(Version.RESOURCES_VERSION)) {
return Response.status(Response.Status.NOT_FOUND).build();
}
- return getMinJs();
+ return getKeycloakAuthzMinJs();
}
+ private Response getJs(String name) {
+ InputStream inputStream = getClass().getClassLoader().getResourceAsStream(name);
+ if (inputStream != null) {
+ CacheControl cacheControl = new CacheControl();
+ cacheControl.setNoTransform(false);
+ cacheControl.setMaxAge(Config.scope("theme").getInt("staticMaxAge", -1));
+
+ return Response.ok(inputStream).type("text/javascript").cacheControl(cacheControl).build();
+ } else {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+ }
}