KEYCLOAK-231 Support for sending scope parameter from applications and oauth clients

This commit is contained in:
mposolda 2014-01-02 17:20:20 +01:00
parent e904ca8b58
commit d309fab825
10 changed files with 77 additions and 11 deletions

View file

@ -17,6 +17,7 @@ public class AbstractOAuthClient {
protected KeyStore truststore;
protected String authUrl;
protected String codeUrl;
protected String scope;
protected String stateCookieName = OAUTH_TOKEN_REQUEST_STATE;
protected String stateCookiePath;
protected boolean isSecure;
@ -68,6 +69,14 @@ public class AbstractOAuthClient {
this.codeUrl = codeUrl;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getStateCookieName() {
return stateCookieName;
}

View file

@ -14,6 +14,7 @@ public class ResourceMetadata {
protected String clientKeyPassword;
protected KeyStore truststore;
protected PublicKey realmKey;
protected String scope;
public String getResourceName() {
return resourceName;
@ -78,4 +79,12 @@ public class ResourceMetadata {
public void setRealmKey(PublicKey realmKey) {
this.realmKey = realmKey;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}

View file

@ -13,7 +13,7 @@ import org.codehaus.jackson.annotate.JsonPropertyOrder;
"resource", "credentials",
"use-resource-role-mappings",
"enable-cors", "cors-max-age", "cors-allowed-methods",
"expose-token", "bearer-only",
"expose-token", "bearer-only", "scope",
"connection-pool-size",
"allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password",
"client-keystore", "client-keystore-password", "client-key-password"

View file

@ -2,6 +2,7 @@ package org.keycloak.representations.adapters.config;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.annotate.JsonPropertyOrder;
import org.keycloak.representations.SkeletonKeyScope;
import java.util.HashMap;
import java.util.Map;
@ -16,7 +17,7 @@ import java.util.Map;
"resource", "credentials",
"use-resource-role-mappings",
"enable-cors", "cors-max-age", "cors-allowed-methods",
"expose-token", "bearer-only"})
"expose-token", "bearer-only", "scope"})
public class BaseAdapterConfig extends BaseRealmConfig {
@JsonProperty("resource")
protected String resource;
@ -36,6 +37,9 @@ public class BaseAdapterConfig extends BaseRealmConfig {
protected boolean bearerOnly;
@JsonProperty("credentials")
protected Map<String, String> credentials = new HashMap<String, String>();
@JsonProperty("scope")
protected SkeletonKeyScope scope;
public boolean isUseResourceRoleMappings() {
return useResourceRoleMappings;
@ -108,4 +112,12 @@ public class BaseAdapterConfig extends BaseRealmConfig {
public void setCredentials(Map<String, String> credentials) {
this.credentials = credentials;
}
public SkeletonKeyScope getScope() {
return scope;
}
public void setScope(SkeletonKeyScope scope) {
this.scope = scope;
}
}

View file

@ -5,5 +5,8 @@
"ssl-not-required" : true,
"credentials" : {
"password" : "password"
},
"scope": {
"realm": [ "user" ]
}
}

View file

@ -2,7 +2,10 @@ package org.keycloak.adapters.config;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.keycloak.representations.SkeletonKeyScope;
import org.keycloak.util.Base64Url;
import org.keycloak.util.EnvUtil;
import org.keycloak.util.JsonSerialization;
import org.keycloak.util.PemUtils;
import org.keycloak.adapters.ResourceMetadata;
import org.keycloak.representations.adapters.config.AdapterConfig;
@ -64,6 +67,11 @@ public class AdapterConfigLoader {
resourceMetadata.setClientKeyPassword(clientKeyPassword);
resourceMetadata.setTruststore(this.truststore);
if (adapterConfig.getScope() != null) {
String scope = encodeScope(adapterConfig.getScope());
resourceMetadata.setScope(scope);
}
}
public AdapterConfig getAdapterConfig() {
@ -119,4 +127,13 @@ public class AdapterConfigLoader {
}
}
}
protected String encodeScope(SkeletonKeyScope scope) {
try {
byte[] scopeBytes = JsonSerialization.writeValueAsBytes(scope);
return Base64Url.encode(scopeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View file

@ -30,5 +30,9 @@ public abstract class OAuthClientConfigLoader extends RealmConfigurationLoader {
oauthClient.setAuthUrl(adapterConfig.getAuthUrl());
oauthClient.setCodeUrl(adapterConfig.getCodeUrl());
oauthClient.setTruststore(truststore);
if (adapterConfig.getScope() != null) {
String scope = encodeScope(adapterConfig.getScope());
oauthClient.setScope(scope);
}
}
}

View file

@ -138,12 +138,15 @@ public class ServletOAuthLogin {
if (port != 443) secureUrl.port(port);
url = secureUrl.build().toString();
}
return realmInfo.getAuthUrl().clone()
KeycloakUriBuilder uriBuilder = realmInfo.getAuthUrl().clone()
.queryParam("client_id", realmInfo.getMetadata().getResourceName())
.queryParam("redirect_uri", url)
.queryParam("state", state)
.queryParam("login", "true")
.build().toString();
.queryParam("login", "true");
if (realmInfo.getMetadata().getScope() != null) {
uriBuilder.queryParam("scope", realmInfo.getMetadata().getScope());
}
return uriBuilder.build().toString();
}
protected static final AtomicLong counter = new AtomicLong();

View file

@ -18,6 +18,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.net.URL;
/**
* Helper code to obtain oauth access tokens via browser redirects
@ -87,11 +88,15 @@ public class JaxrsOAuthClient extends AbstractOAuthClient {
state += "#" + path;
}
URI url = UriBuilder.fromUri(authUrl)
UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
.queryParam("client_id", clientId)
.queryParam("redirect_uri", redirectUri)
.queryParam("state", state)
.build();
.queryParam("state", state);
if (scope != null) {
uriBuilder.queryParam("scope", scope);
}
URI url = uriBuilder.build();
NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure, true);
logger.debug("NewCookie: " + cookie.toString());
logger.debug("Oauth Redirect to: " + url);

View file

@ -84,11 +84,15 @@ public class ServletOAuthClient extends AbstractOAuthClient {
public void redirect(String redirectUri, HttpServletRequest request, HttpServletResponse response) throws IOException {
String state = getStateCode();
URI url = KeycloakUriBuilder.fromUri(authUrl)
KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(authUrl)
.queryParam("client_id", clientId)
.queryParam("redirect_uri", redirectUri)
.queryParam("state", state)
.build();
.queryParam("state", state);
if (scope != null) {
uriBuilder.queryParam("scope", scope);
}
URI url = uriBuilder.build();
String stateCookiePath = this.stateCookiePath;
if (stateCookiePath == null) stateCookiePath = request.getContextPath();
if (stateCookiePath.equals("")) stateCookiePath = "/";