commit
1be8136347
33 changed files with 551 additions and 236 deletions
|
@ -15,8 +15,7 @@ public class RealmConfiguration {
|
||||||
protected ResteasyClient client;
|
protected ResteasyClient client;
|
||||||
protected UriBuilder authUrl;
|
protected UriBuilder authUrl;
|
||||||
protected ResteasyWebTarget codeUrl;
|
protected ResteasyWebTarget codeUrl;
|
||||||
protected String clientId;
|
protected Form resourceCredentials = new Form();
|
||||||
protected Form credentials = new Form();
|
|
||||||
protected boolean sslRequired = true;
|
protected boolean sslRequired = true;
|
||||||
protected String stateCookieName = "OAuth_Token_Request_State";
|
protected String stateCookieName = "OAuth_Token_Request_State";
|
||||||
|
|
||||||
|
@ -44,16 +43,8 @@ public class RealmConfiguration {
|
||||||
this.authUrl = authUrl;
|
this.authUrl = authUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientId() {
|
public Form getResourceCredentials() {
|
||||||
return clientId;
|
return resourceCredentials;
|
||||||
}
|
|
||||||
|
|
||||||
public void setClientId(String clientId) {
|
|
||||||
this.clientId = clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Form getCredentials() {
|
|
||||||
return credentials;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResteasyWebTarget getCodeUrl() {
|
public ResteasyWebTarget getCodeUrl() {
|
||||||
|
|
|
@ -8,8 +8,8 @@ import java.security.PublicKey;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class ResourceMetadata {
|
public class ResourceMetadata {
|
||||||
protected String resourceName;
|
|
||||||
protected String realm;
|
protected String realm;
|
||||||
|
protected String resourceName;
|
||||||
protected KeyStore clientKeystore;
|
protected KeyStore clientKeystore;
|
||||||
protected String clientKeyPassword;
|
protected String clientKeyPassword;
|
||||||
protected KeyStore truststore;
|
protected KeyStore truststore;
|
||||||
|
|
15
core/src/main/java/org/keycloak/TokenIdGenerator.java
Executable file
15
core/src/main/java/org/keycloak/TokenIdGenerator.java
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
package org.keycloak;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class TokenIdGenerator {
|
||||||
|
private static final AtomicLong counter = new AtomicLong();
|
||||||
|
public static String generateId() {
|
||||||
|
return UUID.randomUUID().toString() + "-" + System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class CredentialRepresentation {
|
||||||
|
protected String type;
|
||||||
|
protected String value;
|
||||||
|
protected boolean hashed;
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHashed() {
|
||||||
|
return hashed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashed(boolean hashed) {
|
||||||
|
this.hashed = hashed;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,10 @@ import java.util.Set;
|
||||||
public class ResourceRepresentation {
|
public class ResourceRepresentation {
|
||||||
protected String self; // link
|
protected String self; // link
|
||||||
protected String name;
|
protected String name;
|
||||||
|
protected String adminUrl;
|
||||||
protected boolean surrogateAuthRequired;
|
protected boolean surrogateAuthRequired;
|
||||||
|
protected boolean useRealmMappings;
|
||||||
|
protected List<CredentialRepresentation> credentials;
|
||||||
protected Set<String> roles;
|
protected Set<String> roles;
|
||||||
protected List<RoleMappingRepresentation> roleMappings;
|
protected List<RoleMappingRepresentation> roleMappings;
|
||||||
protected List<ScopeMappingRepresentation> scopeMappings;
|
protected List<ScopeMappingRepresentation> scopeMappings;
|
||||||
|
@ -79,5 +82,37 @@ public class ResourceRepresentation {
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAdminUrl() {
|
||||||
|
return adminUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAdminUrl(String adminUrl) {
|
||||||
|
this.adminUrl = adminUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CredentialRepresentation> getCredentials() {
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCredentials(List<CredentialRepresentation> credentials) {
|
||||||
|
this.credentials = credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceRepresentation credential(String type, String value, boolean hashed) {
|
||||||
|
if (this.credentials == null) credentials = new ArrayList<CredentialRepresentation>();
|
||||||
|
CredentialRepresentation cred = new CredentialRepresentation();
|
||||||
|
cred.setType(type);
|
||||||
|
cred.setValue(value);
|
||||||
|
cred.setHashed(hashed);
|
||||||
|
credentials.add(cred);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUseRealmMappings() {
|
||||||
|
return useRealmMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUseRealmMappings(boolean useRealmMappings) {
|
||||||
|
this.useRealmMappings = useRealmMappings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,41 +10,12 @@ import java.util.Map;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class UserRepresentation {
|
public class UserRepresentation {
|
||||||
public static class Credential {
|
|
||||||
protected String type;
|
|
||||||
protected String value;
|
|
||||||
protected boolean hashed;
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setType(String type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHashed() {
|
|
||||||
return hashed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHashed(boolean hashed) {
|
|
||||||
this.hashed = hashed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String self; // link
|
protected String self; // link
|
||||||
protected String username;
|
protected String username;
|
||||||
protected boolean enabled;
|
protected boolean enabled;
|
||||||
protected Map<String, String> attributes;
|
protected Map<String, String> attributes;
|
||||||
protected List<Credential> credentials;
|
protected List<CredentialRepresentation> credentials;
|
||||||
|
|
||||||
public String getSelf() {
|
public String getSelf() {
|
||||||
return self;
|
return self;
|
||||||
|
@ -70,23 +41,23 @@ public class UserRepresentation {
|
||||||
this.attributes = attributes;
|
this.attributes = attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Credential> getCredentials() {
|
|
||||||
return credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCredentials(List<Credential> credentials) {
|
|
||||||
this.credentials = credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserRepresentation attribute(String name, String value) {
|
public UserRepresentation attribute(String name, String value) {
|
||||||
if (this.attributes == null) attributes = new HashMap<String, String>();
|
if (this.attributes == null) attributes = new HashMap<String, String>();
|
||||||
attributes.put(name, value);
|
attributes.put(name, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<CredentialRepresentation> getCredentials() {
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCredentials(List<CredentialRepresentation> credentials) {
|
||||||
|
this.credentials = credentials;
|
||||||
|
}
|
||||||
|
|
||||||
public UserRepresentation credential(String type, String value, boolean hashed) {
|
public UserRepresentation credential(String type, String value, boolean hashed) {
|
||||||
if (this.credentials == null) credentials = new ArrayList<Credential>();
|
if (this.credentials == null) credentials = new ArrayList<CredentialRepresentation>();
|
||||||
Credential cred = new Credential();
|
CredentialRepresentation cred = new CredentialRepresentation();
|
||||||
cred.setType(type);
|
cred.setType(type);
|
||||||
cred.setValue(value);
|
cred.setValue(value);
|
||||||
cred.setHashed(hashed);
|
cred.setHashed(hashed);
|
||||||
|
|
66
core/src/main/java/org/keycloak/representations/idm/admin/AdminAction.java
Executable file
66
core/src/main/java/org/keycloak/representations/idm/admin/AdminAction.java
Executable file
|
@ -0,0 +1,66 @@
|
||||||
|
package org.keycloak.representations.idm.admin;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||||
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Posted to managed client from admin server.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AdminAction {
|
||||||
|
protected String id;
|
||||||
|
protected long expiration;
|
||||||
|
protected String resource;
|
||||||
|
protected String action;
|
||||||
|
|
||||||
|
public AdminAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminAction(String id, long expiration, String resource, String action) {
|
||||||
|
this.id = id;
|
||||||
|
this.expiration = expiration;
|
||||||
|
this.resource = resource;
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAction(String action) {
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean isExpired()
|
||||||
|
{
|
||||||
|
long time = System.currentTimeMillis() / 1000;
|
||||||
|
return time > expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getExpiration() {
|
||||||
|
return expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiration(long expiration) {
|
||||||
|
this.expiration = expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResource() {
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResource(String resource) {
|
||||||
|
this.resource = resource;
|
||||||
|
}
|
||||||
|
}
|
26
core/src/main/java/org/keycloak/representations/idm/admin/LogoutAction.java
Executable file
26
core/src/main/java/org/keycloak/representations/idm/admin/LogoutAction.java
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
package org.keycloak.representations.idm.admin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class LogoutAction extends AdminAction {
|
||||||
|
public static final String LOGOUT_ACTION = "logout";
|
||||||
|
protected String user;
|
||||||
|
|
||||||
|
public LogoutAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public LogoutAction(String id, long expiration, String resource, String user) {
|
||||||
|
super(id, expiration, resource, LOGOUT_ACTION);
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(String user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"realm" : "demo",
|
"realm" : "demo",
|
||||||
|
"resource" : "customer-portal",
|
||||||
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||||
"auth-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/login",
|
"auth-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/login",
|
||||||
"code-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/access/codes",
|
"code-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/access/codes",
|
||||||
"ssl-not-required" : true,
|
"ssl-not-required" : true,
|
||||||
"client-id" : "customer-portal",
|
"credentials" : {
|
||||||
"client-credentials" : {
|
|
||||||
"password" : "password"
|
"password" : "password"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
examples/as7-eap-demo/customer-app/src/main/webapp/customers/view.jsp
Normal file → Executable file
8
examples/as7-eap-demo/customer-app/src/main/webapp/customers/view.jsp
Normal file → Executable file
|
@ -1,11 +1,15 @@
|
||||||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1"
|
||||||
pageEncoding="ISO-8859-1"%>
|
pageEncoding="ISO-8859-1"%>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Customer View Page</title>
|
<title>Customer View Page</title>
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="#E3F6CE">
|
<body bgcolor="#E3F6CE">
|
||||||
<p>Goto: <a href="https://localhost:8443/product-portal">products</a> | <a href="https://localhost:8443/auth-server/j_oauth_logout">logout</a></p>
|
<%
|
||||||
|
String logoutUri = UriBuilder.fromUri("http://localhost:8080/auth-server/rest/realms/demo/tokens/logout")
|
||||||
|
.queryParam("redirect_uri", "http://localhost:8080/customer-portal").build().toString();
|
||||||
|
%>
|
||||||
|
<p>Goto: <a href="http://localhost:8080/product-portal">products</a> | <a href="<%=logoutUri%>">logout</a></p>
|
||||||
User <b><%=request.getUserPrincipal().getName()%></b> made this request.
|
User <b><%=request.getUserPrincipal().getName()%></b> made this request.
|
||||||
<h2>Customer Listing</h2>
|
<h2>Customer Listing</h2>
|
||||||
<%
|
<%
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"realm" : "demo",
|
"realm" : "demo",
|
||||||
|
"resource" : "database-service",
|
||||||
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"
|
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"realm" : "demo",
|
"realm" : "demo",
|
||||||
|
"resource" : "product-portal",
|
||||||
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||||
"auth-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/login",
|
"auth-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/login",
|
||||||
"code-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/access/codes",
|
"code-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/access/codes",
|
||||||
"ssl-not-required" : true,
|
"ssl-not-required" : true,
|
||||||
"client-id" : "product-portal",
|
"credentials" : {
|
||||||
"client-credentials" : {
|
|
||||||
"password" : "password"
|
"password" : "password"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
examples/as7-eap-demo/product-app/src/main/webapp/products/view.jsp
Normal file → Executable file
9
examples/as7-eap-demo/product-app/src/main/webapp/products/view.jsp
Normal file → Executable file
|
@ -1,11 +1,16 @@
|
||||||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1"
|
||||||
pageEncoding="ISO-8859-1"%>
|
pageEncoding="ISO-8859-1"%>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Product View Page</title>
|
<title>Product View Page</title>
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="#F5F6CE">
|
<body bgcolor="#F5F6CE">
|
||||||
<p>Goto: <a href="https://localhost:8443/customer-portal">customers</a> | <a href="https://localhost:8443/auth-server/j_oauth_logout">logout</a></p>
|
<%
|
||||||
|
String logoutUri = UriBuilder.fromUri("http://localhost:8080/auth-server/rest/realms/demo/tokens/logout")
|
||||||
|
.queryParam("redirect_uri", "http://localhost:8080/product-portal").build().toString();
|
||||||
|
%>
|
||||||
|
|
||||||
|
<p>Goto: <a href="http://localhost:8080/customer-portal">customers</a> | <a href="<%=logoutUri%>">logout</a></p>
|
||||||
User <b><%=request.getUserPrincipal().getName()%></b> made this request.
|
User <b><%=request.getUserPrincipal().getName()%></b> made this request.
|
||||||
<h2>Product Listing</h2>
|
<h2>Product Listing</h2>
|
||||||
<%
|
<%
|
||||||
|
|
|
@ -25,22 +25,6 @@
|
||||||
{ "type" : "Password",
|
{ "type" : "Password",
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"username" : "customer-portal",
|
|
||||||
"enabled" : true,
|
|
||||||
"credentials" : [
|
|
||||||
{ "type" : "Password",
|
|
||||||
"value" : "password" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"username" : "product-portal",
|
|
||||||
"enabled" : true,
|
|
||||||
"credentials" : [
|
|
||||||
{ "type" : "Password",
|
|
||||||
"value" : "password" }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"roleMappings" : [
|
"roleMappings" : [
|
||||||
|
@ -49,14 +33,24 @@
|
||||||
"roles" : ["user"]
|
"roles" : ["user"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"scopeMappings" : [
|
"resources" : [
|
||||||
{
|
{
|
||||||
"username" : "customer-portal",
|
"name" : "customer-portal",
|
||||||
"roles" : ["*"]
|
"adminUrl" : "http://localhost:8080/customer-portal/j_admin_request",
|
||||||
|
"useRealmMappings" : true,
|
||||||
|
"credentials" : [
|
||||||
|
{ "type" : "Password",
|
||||||
|
"value" : "password" }
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"username" : "product-portal",
|
"name" : "product-portal",
|
||||||
"roles" : ["*"]
|
"adminUrl" : "http://localhost:8080/product-portal/j_admin_request",
|
||||||
|
"useRealmMappings" : true,
|
||||||
|
"credentials" : [
|
||||||
|
{ "type" : "Password",
|
||||||
|
"value" : "password" }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -63,7 +63,7 @@ public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements
|
||||||
@Override
|
@Override
|
||||||
protected boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
|
protected boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
|
||||||
try {
|
try {
|
||||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, !remoteSkeletonKeyConfig.isCancelPropagation(), true);
|
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, !remoteSkeletonKeyConfig.isCancelPropagation(), true, remoteSkeletonKeyConfig.isUseResourceRoleMappings());
|
||||||
if (bearer.login(request, response)) {
|
if (bearer.login(request, response)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,11 +30,13 @@ public class CatalinaBearerTokenAuthenticator {
|
||||||
protected SkeletonKeyToken token;
|
protected SkeletonKeyToken token;
|
||||||
private Principal principal;
|
private Principal principal;
|
||||||
protected boolean propagateToken;
|
protected boolean propagateToken;
|
||||||
|
protected boolean useResourceRoleMappings;
|
||||||
|
|
||||||
public CatalinaBearerTokenAuthenticator(ResourceMetadata resourceMetadata, boolean propagateToken, boolean challenge) {
|
public CatalinaBearerTokenAuthenticator(ResourceMetadata resourceMetadata, boolean propagateToken, boolean challenge, boolean useResourceRoleMappings) {
|
||||||
this.resourceMetadata = resourceMetadata;
|
this.resourceMetadata = resourceMetadata;
|
||||||
this.challenge = challenge;
|
this.challenge = challenge;
|
||||||
this.propagateToken = propagateToken;
|
this.propagateToken = propagateToken;
|
||||||
|
this.useResourceRoleMappings = useResourceRoleMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceMetadata getResourceMetadata() {
|
public ResourceMetadata getResourceMetadata() {
|
||||||
|
@ -77,8 +80,8 @@ public class CatalinaBearerTokenAuthenticator {
|
||||||
challengeResponse(response, "invalid_token", e.getMessage());
|
challengeResponse(response, "invalid_token", e.getMessage());
|
||||||
}
|
}
|
||||||
boolean verifyCaller = false;
|
boolean verifyCaller = false;
|
||||||
Set<String> roles = null;
|
Set<String> roles = new HashSet<String>();
|
||||||
if (resourceMetadata.getResourceName() != null) {
|
if (useResourceRoleMappings) {
|
||||||
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
|
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
|
||||||
if (access != null) roles = access.getRoles();
|
if (access != null) roles = access.getRoles();
|
||||||
verifyCaller = token.isVerifyCaller(resourceMetadata.getResourceName());
|
verifyCaller = token.isVerifyCaller(resourceMetadata.getResourceName());
|
||||||
|
|
|
@ -527,8 +527,8 @@ public class OAuthAuthenticationServerValve extends FormAuthenticator implements
|
||||||
html.append("<br>");
|
html.append("<br>");
|
||||||
|
|
||||||
writer = new StringWriter();
|
writer = new StringWriter();
|
||||||
rep.getClientCredentials().put("password", "REQUIRED");
|
rep.getCredentials().put("password", "REQUIRED");
|
||||||
rep.setClientId("REQUIRED");
|
//rep.setClientId("REQUIRED");
|
||||||
rep.setTruststore("REQUIRED");
|
rep.setTruststore("REQUIRED");
|
||||||
rep.setTruststorePassword("REQUIRED");
|
rep.setTruststorePassword("REQUIRED");
|
||||||
mapper.writeValue(writer, rep);
|
mapper.writeValue(writer, rep);
|
||||||
|
@ -561,7 +561,7 @@ public class OAuthAuthenticationServerValve extends FormAuthenticator implements
|
||||||
|
|
||||||
public boolean bearer(Request request, HttpServletResponse response, boolean propagate) throws IOException {
|
public boolean bearer(Request request, HttpServletResponse response, boolean propagate) throws IOException {
|
||||||
if (request.getHeader("Authorization") != null) {
|
if (request.getHeader("Authorization") != null) {
|
||||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, true, false);
|
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, true, false, false);
|
||||||
try {
|
try {
|
||||||
if (bearer.login(request, response)) {
|
if (bearer.login(request, response)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -14,8 +14,9 @@ import org.apache.catalina.deploy.LoginConfig;
|
||||||
import org.apache.catalina.realm.GenericPrincipal;
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
import org.jboss.resteasy.jose.jws.JWSInput;
|
||||||
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
|
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
||||||
|
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
import org.keycloak.RealmConfiguration;
|
import org.keycloak.RealmConfiguration;
|
||||||
import org.keycloak.ResourceMetadata;
|
import org.keycloak.ResourceMetadata;
|
||||||
|
@ -24,12 +25,14 @@ import org.keycloak.SkeletonKeySession;
|
||||||
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
|
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
|
||||||
import org.keycloak.adapters.as7.config.ManagedResourceConfigLoader;
|
import org.keycloak.adapters.as7.config.ManagedResourceConfigLoader;
|
||||||
import org.keycloak.representations.SkeletonKeyToken;
|
import org.keycloak.representations.SkeletonKeyToken;
|
||||||
|
import org.keycloak.representations.idm.admin.LogoutAction;
|
||||||
|
|
||||||
import javax.security.auth.login.LoginException;
|
import javax.security.auth.login.LoginException;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -67,10 +70,6 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
||||||
managedResourceConfigLoader.init(true);
|
managedResourceConfigLoader.init(true);
|
||||||
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
|
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
|
||||||
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
|
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
|
||||||
String client_id = remoteSkeletonKeyConfig.getClientId();
|
|
||||||
if (client_id == null) {
|
|
||||||
throw new IllegalArgumentException("Must set client-id to use with auth server");
|
|
||||||
}
|
|
||||||
realmConfiguration = new RealmConfiguration();
|
realmConfiguration = new RealmConfiguration();
|
||||||
String authUrl = remoteSkeletonKeyConfig.getAuthUrl();
|
String authUrl = remoteSkeletonKeyConfig.getAuthUrl();
|
||||||
if (authUrl == null) {
|
if (authUrl == null) {
|
||||||
|
@ -81,17 +80,16 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
||||||
throw new RuntimeException("You mut specify code-url");
|
throw new RuntimeException("You mut specify code-url");
|
||||||
}
|
}
|
||||||
realmConfiguration.setMetadata(resourceMetadata);
|
realmConfiguration.setMetadata(resourceMetadata);
|
||||||
realmConfiguration.setClientId(client_id);
|
|
||||||
realmConfiguration.setSslRequired(!remoteSkeletonKeyConfig.isSslNotRequired());
|
realmConfiguration.setSslRequired(!remoteSkeletonKeyConfig.isSslNotRequired());
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : managedResourceConfigLoader.getRemoteSkeletonKeyConfig().getClientCredentials().entrySet()) {
|
for (Map.Entry<String, String> entry : managedResourceConfigLoader.getRemoteSkeletonKeyConfig().getCredentials().entrySet()) {
|
||||||
realmConfiguration.getCredentials().param(entry.getKey(), entry.getValue());
|
realmConfiguration.getResourceCredentials().param(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
ResteasyClient client = managedResourceConfigLoader.getClient();
|
ResteasyClient client = managedResourceConfigLoader.getClient();
|
||||||
|
|
||||||
realmConfiguration.setClient(client);
|
realmConfiguration.setClient(client);
|
||||||
realmConfiguration.setAuthUrl(UriBuilder.fromUri(authUrl).queryParam("client_id", client_id));
|
realmConfiguration.setAuthUrl(UriBuilder.fromUri(authUrl).queryParam("client_id", resourceMetadata.getResourceName()));
|
||||||
realmConfiguration.setCodeUrl(client.target(tokenUrl));
|
realmConfiguration.setCodeUrl(client.target(tokenUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +97,8 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
||||||
public void invoke(Request request, Response response) throws IOException, ServletException {
|
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||||
try {
|
try {
|
||||||
String requestURI = request.getDecodedRequestURI();
|
String requestURI = request.getDecodedRequestURI();
|
||||||
if (requestURI.endsWith("j_oauth_remote_logout")) {
|
if (requestURI.endsWith("j_admin_request")) {
|
||||||
remoteLogout(request, response);
|
adminRequest(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
super.invoke(request, response);
|
super.invoke(request, response);
|
||||||
|
@ -135,33 +133,71 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void remoteLogout(Request request, HttpServletResponse response) throws IOException {
|
protected void adminRequest(Request request, HttpServletResponse response) throws IOException {
|
||||||
|
String token = request.getParameter("token");
|
||||||
|
if (token == null) {
|
||||||
|
log.warn("admin request failed, no token");
|
||||||
|
response.sendError(403, "no token");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JWSInput input = new JWSInput(token);
|
||||||
|
boolean verified = false;
|
||||||
|
try {
|
||||||
|
verified = RSAProvider.verify(input, resourceMetadata.getRealmKey());
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
if (!verified) {
|
||||||
|
log.warn("admin request failed, unable to verify token");
|
||||||
|
response.sendError(403, "verification failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String action = request.getParameter("action");
|
||||||
|
if (LogoutAction.LOGOUT_ACTION.equals(action)) {
|
||||||
|
remoteLogout(input, response);
|
||||||
|
} else {
|
||||||
|
log.warn("admin request failed, unknown action");
|
||||||
|
response.sendError(403, "Unknown action");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void remoteLogout(JWSInput token, HttpServletResponse response) throws IOException {
|
||||||
try {
|
try {
|
||||||
log.debug("->> remoteLogout: ");
|
log.debug("->> remoteLogout: ");
|
||||||
if (!bearer(true, request, response)) {
|
LogoutAction action = JsonSerialization.fromBytes(LogoutAction.class, token.getContent());
|
||||||
log.debug("remoteLogout: bearer auth failed");
|
if (action.isExpired()) {
|
||||||
|
log.warn("admin request failed, expired token");
|
||||||
|
response.sendError(400, "Expired token");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GenericPrincipal gp = (GenericPrincipal) request.getPrincipal();
|
if (!LogoutAction.LOGOUT_ACTION.equals(action.getAction())) {
|
||||||
if (!gp.hasRole(remoteSkeletonKeyConfig.getAdminRole())) {
|
log.warn("Action doesn't match");
|
||||||
log.debug("remoteLogout: role failure");
|
response.sendError(400, "Action does not match");
|
||||||
response.sendError(403);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String user = request.getParameter("user");
|
if (!resourceMetadata.getResourceName().equals(action.getResource())) {
|
||||||
|
log.warn("Resource name does not match");
|
||||||
|
response.sendError(400, "Resource name does not match");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
String user = action.getUser();
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
|
log.info("logout of session for: " + user);
|
||||||
userSessionManagement.logout(user);
|
userSessionManagement.logout(user);
|
||||||
} else {
|
} else {
|
||||||
|
log.info("logout of all sessions");
|
||||||
userSessionManagement.logoutAll();
|
userSessionManagement.logoutAll();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("failed to logout", e);
|
log.warn("failed to logout", e);
|
||||||
|
response.sendError(500, "Failed to logout");
|
||||||
}
|
}
|
||||||
response.setStatus(204);
|
response.setStatus(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean bearer(boolean challenge, Request request, HttpServletResponse response) throws LoginException, IOException {
|
protected boolean bearer(boolean challenge, Request request, HttpServletResponse response) throws LoginException, IOException {
|
||||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(realmConfiguration.getMetadata(), !remoteSkeletonKeyConfig.isCancelPropagation(), challenge);
|
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(realmConfiguration.getMetadata(), !remoteSkeletonKeyConfig.isCancelPropagation(), challenge, remoteSkeletonKeyConfig.isUseResourceRoleMappings());
|
||||||
if (bearer.login(request, response)) {
|
if (bearer.login(request, response)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -207,13 +243,13 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
||||||
if (!oauth.resolveCode(code)) return;
|
if (!oauth.resolveCode(code)) return;
|
||||||
|
|
||||||
SkeletonKeyToken token = oauth.getToken();
|
SkeletonKeyToken token = oauth.getToken();
|
||||||
Set<String> roles = null;
|
Set<String> roles = new HashSet<String>();
|
||||||
if (resourceMetadata.getResourceName() != null) {
|
if (remoteSkeletonKeyConfig.isUseResourceRoleMappings()) {
|
||||||
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
|
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
|
||||||
if (access != null) roles = access.getRoles();
|
if (access != null) roles.addAll(access.getRoles());
|
||||||
} else {
|
} else {
|
||||||
SkeletonKeyToken.Access access = token.getRealmAccess();
|
SkeletonKeyToken.Access access = token.getRealmAccess();
|
||||||
if (access != null) roles = access.getRoles();
|
if (access != null) roles.addAll(access.getRoles());
|
||||||
}
|
}
|
||||||
SkeletonKeyPrincipal skp = new SkeletonKeyPrincipal(token.getPrincipal(), null);
|
SkeletonKeyPrincipal skp = new SkeletonKeyPrincipal(token.getPrincipal(), null);
|
||||||
GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(context.getRealm(), skp, roles);
|
GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(context.getRealm(), skp, roles);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.keycloak.adapters.as7;
|
package org.keycloak.adapters.as7;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.util.BasicAuthHelper;
|
|
||||||
import org.keycloak.RSATokenVerifier;
|
import org.keycloak.RSATokenVerifier;
|
||||||
import org.keycloak.RealmConfiguration;
|
import org.keycloak.RealmConfiguration;
|
||||||
import org.keycloak.VerificationException;
|
import org.keycloak.VerificationException;
|
||||||
|
@ -14,7 +13,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.ws.rs.client.Entity;
|
import javax.ws.rs.client.Entity;
|
||||||
import javax.ws.rs.core.Form;
|
import javax.ws.rs.core.Form;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -144,7 +142,7 @@ public class ServletOAuthLogin {
|
||||||
url = secureUrl.build().toString();
|
url = secureUrl.build().toString();
|
||||||
}
|
}
|
||||||
return realmInfo.getAuthUrl().clone()
|
return realmInfo.getAuthUrl().clone()
|
||||||
.queryParam("client_id", realmInfo.getClientId())
|
.queryParam("client_id", realmInfo.getMetadata().getResourceName())
|
||||||
.queryParam("redirect_uri", url)
|
.queryParam("redirect_uri", url)
|
||||||
.queryParam("state", state)
|
.queryParam("state", state)
|
||||||
.queryParam("login", "true")
|
.queryParam("login", "true")
|
||||||
|
@ -223,8 +221,8 @@ public class ServletOAuthLogin {
|
||||||
|
|
||||||
if (!checkStateCookie()) return false;
|
if (!checkStateCookie()) return false;
|
||||||
|
|
||||||
String client_id = realmInfo.getClientId();
|
String client_id = realmInfo.getMetadata().getResourceName();
|
||||||
String password = realmInfo.getCredentials().asMap().getFirst("password");
|
String password = realmInfo.getResourceCredentials().asMap().getFirst("password");
|
||||||
//String authHeader = BasicAuthHelper.createHeader(client_id, password);
|
//String authHeader = BasicAuthHelper.createHeader(client_id, password);
|
||||||
String redirectUri = stripOauthParametersFromRedirect();
|
String redirectUri = stripOauthParametersFromRedirect();
|
||||||
Form form = new Form();
|
Form form = new Form();
|
||||||
|
|
|
@ -26,6 +26,8 @@ public class ManagedResourceConfig {
|
||||||
protected String authUrl;
|
protected String authUrl;
|
||||||
@JsonProperty("code-url")
|
@JsonProperty("code-url")
|
||||||
protected String codeUrl;
|
protected String codeUrl;
|
||||||
|
@JsonProperty("use-resource-role-mappings")
|
||||||
|
protected boolean useResourceRoleMappings;
|
||||||
|
|
||||||
@JsonProperty("ssl-not-required")
|
@JsonProperty("ssl-not-required")
|
||||||
protected boolean sslNotRequired;
|
protected boolean sslNotRequired;
|
||||||
|
@ -37,21 +39,27 @@ public class ManagedResourceConfig {
|
||||||
protected String truststore;
|
protected String truststore;
|
||||||
@JsonProperty("truststore-password")
|
@JsonProperty("truststore-password")
|
||||||
protected String truststorePassword;
|
protected String truststorePassword;
|
||||||
@JsonProperty("client-id")
|
|
||||||
protected String clientId;
|
|
||||||
@JsonProperty("client-keystore")
|
@JsonProperty("client-keystore")
|
||||||
protected String clientKeystore;
|
protected String clientKeystore;
|
||||||
@JsonProperty("client-keystore-password")
|
@JsonProperty("client-keystore-password")
|
||||||
protected String clientKeystorePassword;
|
protected String clientKeystorePassword;
|
||||||
@JsonProperty("client-key-password")
|
@JsonProperty("client-key-password")
|
||||||
protected String clientKeyPassword;
|
protected String clientKeyPassword;
|
||||||
@JsonProperty("client-credentials")
|
@JsonProperty("credentials")
|
||||||
protected Map<String, String> clientCredentials = new HashMap<String, String>();
|
protected Map<String, String> credentials = new HashMap<String, String>();
|
||||||
@JsonProperty("connection-pool-size")
|
@JsonProperty("connection-pool-size")
|
||||||
protected int connectionPoolSize;
|
protected int connectionPoolSize;
|
||||||
@JsonProperty("cancel-propagation")
|
@JsonProperty("cancel-propagation")
|
||||||
protected boolean cancelPropagation;
|
protected boolean cancelPropagation;
|
||||||
|
|
||||||
|
public boolean isUseResourceRoleMappings() {
|
||||||
|
return useResourceRoleMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
|
||||||
|
this.useResourceRoleMappings = useResourceRoleMappings;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSslNotRequired() {
|
public boolean isSslNotRequired() {
|
||||||
return sslNotRequired;
|
return sslNotRequired;
|
||||||
}
|
}
|
||||||
|
@ -140,16 +148,8 @@ public class ManagedResourceConfig {
|
||||||
this.truststorePassword = truststorePassword;
|
this.truststorePassword = truststorePassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientId() {
|
public Map<String, String> getCredentials() {
|
||||||
return clientId;
|
return credentials;
|
||||||
}
|
|
||||||
|
|
||||||
public void setClientId(String clientId) {
|
|
||||||
this.clientId = clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getClientCredentials() {
|
|
||||||
return clientCredentials;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientKeystore() {
|
public String getClientKeystore() {
|
||||||
|
|
|
@ -103,8 +103,9 @@ public class ManagedResourceConfigLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
String realm = remoteSkeletonKeyConfig.getRealm();
|
String realm = remoteSkeletonKeyConfig.getRealm();
|
||||||
String resource = remoteSkeletonKeyConfig.getResource();
|
|
||||||
if (realm == null) throw new RuntimeException("Must set 'realm' in config");
|
if (realm == null) throw new RuntimeException("Must set 'realm' in config");
|
||||||
|
String resource = remoteSkeletonKeyConfig.getResource();
|
||||||
|
if (resource == null) throw new RuntimeException("Must set 'resource' in config");
|
||||||
|
|
||||||
String realmKeyPem = remoteSkeletonKeyConfig.getRealmKey();
|
String realmKeyPem = remoteSkeletonKeyConfig.getRealmKey();
|
||||||
if (realmKeyPem == null) {
|
if (realmKeyPem == null) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.keycloak.representations.SkeletonKeyToken;
|
||||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.RequiredCredentialModel;
|
import org.keycloak.services.models.RequiredCredentialModel;
|
||||||
|
import org.keycloak.services.resources.RealmsResource;
|
||||||
import org.picketlink.idm.credential.Credentials;
|
import org.picketlink.idm.credential.Credentials;
|
||||||
import org.picketlink.idm.credential.Password;
|
import org.picketlink.idm.credential.Password;
|
||||||
import org.picketlink.idm.credential.TOTPCredentials;
|
import org.picketlink.idm.credential.TOTPCredentials;
|
||||||
|
@ -20,6 +21,8 @@ import javax.ws.rs.core.Cookie;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.NewCookie;
|
import javax.ws.rs.core.NewCookie;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import java.net.URI;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -45,14 +48,19 @@ public class AuthenticationManager {
|
||||||
return realm.isRealmAdmin(user);
|
return realm.isRealmAdmin(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void expireIdentityCookie(Cookie cookie) {
|
public void expireIdentityCookie(RealmModel realm, UriInfo uriInfo) {
|
||||||
|
URI uri = RealmsResource.realmBaseUrl(uriInfo).build(realm.getId());
|
||||||
HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
|
HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
|
||||||
if (response == null) return;
|
if (response == null) {
|
||||||
NewCookie expireIt = new NewCookie(cookie.getName(), "", cookie.getPath(), null, "Expiring cookie", 0, false);
|
logger.info("can't expire identity cookie, no HttpResponse");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.info("Expiring identity cookie");
|
||||||
|
NewCookie expireIt = new NewCookie(TokenManager.KEYCLOAK_IDENTITY_COOKIE, "", uri.getPath(), null, "Expiring cookie", 0, false);
|
||||||
response.addNewCookie(expireIt);
|
response.addNewCookie(expireIt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public User authenticateIdentityCookie(RealmModel realm, HttpHeaders headers) {
|
public User authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
||||||
Cookie cookie = headers.getCookies().get(TokenManager.KEYCLOAK_IDENTITY_COOKIE);
|
Cookie cookie = headers.getCookies().get(TokenManager.KEYCLOAK_IDENTITY_COOKIE);
|
||||||
if (cookie == null) return null;
|
if (cookie == null) return null;
|
||||||
|
|
||||||
|
@ -61,19 +69,19 @@ public class AuthenticationManager {
|
||||||
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getId());
|
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getId());
|
||||||
if (!token.isActive()) {
|
if (!token.isActive()) {
|
||||||
logger.info("identity cookie expired");
|
logger.info("identity cookie expired");
|
||||||
expireIdentityCookie(cookie);
|
expireIdentityCookie(realm, uriInfo);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
User user = realm.getIdm().getUser(token.getPrincipal());
|
User user = realm.getIdm().getUser(token.getPrincipal());
|
||||||
if (user == null || !user.isEnabled()) {
|
if (user == null || !user.isEnabled()) {
|
||||||
logger.info("Unknown user in identity cookie");
|
logger.info("Unknown user in identity cookie");
|
||||||
expireIdentityCookie(cookie);
|
expireIdentityCookie(realm, uriInfo);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
logger.info("Failed to verify identity cookie", e);
|
logger.info("Failed to verify identity cookie", e);
|
||||||
expireIdentityCookie(cookie);
|
expireIdentityCookie(realm, uriInfo);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
package org.keycloak.services.managers;
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.ResourceRepresentation;
|
import org.keycloak.representations.idm.ResourceRepresentation;
|
||||||
import org.keycloak.representations.idm.RoleMappingRepresentation;
|
import org.keycloak.representations.idm.RoleMappingRepresentation;
|
||||||
import org.keycloak.representations.idm.ScopeMappingRepresentation;
|
import org.keycloak.representations.idm.ScopeMappingRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.RequiredCredentialModel;
|
import org.keycloak.services.models.RequiredCredentialModel;
|
||||||
import org.keycloak.services.models.ResourceModel;
|
import org.keycloak.services.models.ResourceModel;
|
||||||
import org.keycloak.services.models.UserCredentialModel;
|
import org.keycloak.services.models.UserCredentialModel;
|
||||||
import org.keycloak.services.resources.RegistrationService;
|
|
||||||
import org.picketlink.idm.IdentityManager;
|
import org.picketlink.idm.IdentityManager;
|
||||||
import org.picketlink.idm.IdentitySession;
|
import org.picketlink.idm.IdentitySession;
|
||||||
import org.picketlink.idm.model.Attribute;
|
import org.picketlink.idm.model.Attribute;
|
||||||
|
@ -22,7 +21,6 @@ import org.picketlink.idm.model.SimpleRole;
|
||||||
import org.picketlink.idm.model.SimpleUser;
|
import org.picketlink.idm.model.SimpleUser;
|
||||||
import org.picketlink.idm.model.User;
|
import org.picketlink.idm.model.User;
|
||||||
|
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
|
||||||
import javax.ws.rs.WebApplicationException;
|
import javax.ws.rs.WebApplicationException;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
@ -73,6 +71,7 @@ public class RealmManager {
|
||||||
SimpleAgent agent = new SimpleAgent(RealmModel.REALM_AGENT_ID);
|
SimpleAgent agent = new SimpleAgent(RealmModel.REALM_AGENT_ID);
|
||||||
idm.add(agent);
|
idm.add(agent);
|
||||||
RealmModel realm = new RealmModel(newRealm, identitySession);
|
RealmModel realm = new RealmModel(newRealm, identitySession);
|
||||||
|
idm.add(new SimpleRole("*"));
|
||||||
return realm;
|
return realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +134,7 @@ public class RealmManager {
|
||||||
}
|
}
|
||||||
newRealm.getIdm().add(user);
|
newRealm.getIdm().add(user);
|
||||||
if (userRep.getCredentials() != null) {
|
if (userRep.getCredentials() != null) {
|
||||||
for (UserRepresentation.Credential cred : userRep.getCredentials()) {
|
for (CredentialRepresentation cred : userRep.getCredentials()) {
|
||||||
UserCredentialModel credential = new UserCredentialModel();
|
UserCredentialModel credential = new UserCredentialModel();
|
||||||
credential.setType(cred.getType());
|
credential.setType(cred.getType());
|
||||||
credential.setValue(cred.getValue());
|
credential.setValue(cred.getValue());
|
||||||
|
@ -145,25 +144,25 @@ public class RealmManager {
|
||||||
userMap.put(user.getLoginName(), user);
|
userMap.put(user.getLoginName(), user);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Role> roles = new HashMap<String, Role>();
|
|
||||||
|
|
||||||
if (rep.getRoles() != null) {
|
if (rep.getRoles() != null) {
|
||||||
for (String roleString : rep.getRoles()) {
|
for (String roleString : rep.getRoles()) {
|
||||||
SimpleRole role = new SimpleRole(roleString.trim());
|
SimpleRole role = new SimpleRole(roleString.trim());
|
||||||
newRealm.getIdm().add(role);
|
newRealm.getIdm().add(role);
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rep.getResources() != null) {
|
||||||
|
createResources(rep, newRealm, userMap);
|
||||||
|
}
|
||||||
|
|
||||||
if (rep.getRoleMappings() != null) {
|
if (rep.getRoleMappings() != null) {
|
||||||
for (RoleMappingRepresentation mapping : rep.getRoleMappings()) {
|
for (RoleMappingRepresentation mapping : rep.getRoleMappings()) {
|
||||||
User user = userMap.get(mapping.getUsername());
|
User user = userMap.get(mapping.getUsername());
|
||||||
for (String roleString : mapping.getRoles()) {
|
for (String roleString : mapping.getRoles()) {
|
||||||
Role role = roles.get(roleString.trim());
|
Role role = newRealm.getIdm().getRole(roleString.trim());
|
||||||
if (role == null) {
|
if (role == null) {
|
||||||
role = new SimpleRole(roleString.trim());
|
role = new SimpleRole(roleString.trim());
|
||||||
newRealm.getIdm().add(role);
|
newRealm.getIdm().add(role);
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
}
|
||||||
newRealm.getIdm().grantRole(user, role);
|
newRealm.getIdm().grantRole(user, role);
|
||||||
}
|
}
|
||||||
|
@ -173,11 +172,10 @@ public class RealmManager {
|
||||||
if (rep.getScopeMappings() != null) {
|
if (rep.getScopeMappings() != null) {
|
||||||
for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
|
for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
|
||||||
for (String roleString : scope.getRoles()) {
|
for (String roleString : scope.getRoles()) {
|
||||||
Role role = roles.get(roleString.trim());
|
Role role = newRealm.getIdm().getRole(roleString.trim());
|
||||||
if (role == null) {
|
if (role == null) {
|
||||||
role = new SimpleRole(roleString.trim());
|
role = new SimpleRole(roleString.trim());
|
||||||
newRealm.getIdm().add(role);
|
newRealm.getIdm().add(role);
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
}
|
||||||
User user = userMap.get(scope.getUsername());
|
User user = userMap.get(scope.getUsername());
|
||||||
newRealm.addScope(user, role.getName());
|
newRealm.addScope(user, role.getName());
|
||||||
|
@ -185,43 +183,43 @@ public class RealmManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!roles.containsKey("*")) {
|
|
||||||
SimpleRole wildcard = new SimpleRole("*");
|
|
||||||
newRealm.getIdm().add(wildcard);
|
|
||||||
roles.put("*", wildcard);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rep.getResources() != null) {
|
|
||||||
createResources(rep, newRealm, userMap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createResources(RealmRepresentation rep, RealmModel realm, Map<String, User> userMap) {
|
protected void createResources(RealmRepresentation rep, RealmModel realm, Map<String, User> userMap) {
|
||||||
for (ResourceRepresentation resourceRep : rep.getResources()) {
|
for (ResourceRepresentation resourceRep : rep.getResources()) {
|
||||||
ResourceModel resource = realm.addResource(resourceRep.getName());
|
ResourceModel resource = realm.addResource(resourceRep.getName());
|
||||||
|
resource.setManagementUrl(resourceRep.getAdminUrl());
|
||||||
resource.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
|
resource.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
|
||||||
resource.updateResource();
|
resource.updateResource();
|
||||||
Map<String, Role> roles = new HashMap<String, Role>();
|
|
||||||
|
User resourceUser = resource.getResourceUser();
|
||||||
|
if (resourceRep.getCredentials() != null) {
|
||||||
|
for (CredentialRepresentation cred : resourceRep.getCredentials()) {
|
||||||
|
UserCredentialModel credential = new UserCredentialModel();
|
||||||
|
credential.setType(cred.getType());
|
||||||
|
credential.setValue(cred.getValue());
|
||||||
|
realm.updateCredential(resourceUser, credential);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
userMap.put(resourceUser.getLoginName(), resourceUser);
|
||||||
|
|
||||||
|
|
||||||
if (resourceRep.getRoles() != null) {
|
if (resourceRep.getRoles() != null) {
|
||||||
for (String roleString : resourceRep.getRoles()) {
|
for (String roleString : resourceRep.getRoles()) {
|
||||||
SimpleRole role = new SimpleRole(roleString.trim());
|
SimpleRole role = new SimpleRole(roleString.trim());
|
||||||
resource.getIdm().add(role);
|
resource.getIdm().add(role);
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (resourceRep.getRoleMappings() != null) {
|
if (resourceRep.getRoleMappings() != null) {
|
||||||
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
|
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
|
||||||
User user = userMap.get(mapping.getUsername());
|
User user = userMap.get(mapping.getUsername());
|
||||||
for (String roleString : mapping.getRoles()) {
|
for (String roleString : mapping.getRoles()) {
|
||||||
Role role = roles.get(roleString.trim());
|
Role role = resource.getIdm().getRole(roleString.trim());
|
||||||
if (role == null) {
|
if (role == null) {
|
||||||
role = new SimpleRole(roleString.trim());
|
role = new SimpleRole(roleString.trim());
|
||||||
resource.getIdm().add(role);
|
resource.getIdm().add(role);
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
}
|
||||||
Role role1 = resource.getIdm().getRole(role.getName());
|
realm.getIdm().grantRole(user, role);
|
||||||
realm.getIdm().grantRole(user, role1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,22 +227,16 @@ public class RealmManager {
|
||||||
for (ScopeMappingRepresentation mapping : resourceRep.getScopeMappings()) {
|
for (ScopeMappingRepresentation mapping : resourceRep.getScopeMappings()) {
|
||||||
User user = userMap.get(mapping.getUsername());
|
User user = userMap.get(mapping.getUsername());
|
||||||
for (String roleString : mapping.getRoles()) {
|
for (String roleString : mapping.getRoles()) {
|
||||||
Role role = roles.get(roleString.trim());
|
Role role = resource.getIdm().getRole(roleString.trim());
|
||||||
if (role == null) {
|
if (role == null) {
|
||||||
role = new SimpleRole(roleString.trim());
|
role = new SimpleRole(roleString.trim());
|
||||||
resource.getIdm().add(role);
|
resource.getIdm().add(role);
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
}
|
||||||
resource.addScope(user, role.getName());
|
resource.addScope(user, role.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!roles.containsKey("*")) {
|
if (resourceRep.isUseRealmMappings()) realm.addScope(resource.getResourceUser(), "*");
|
||||||
SimpleRole wildcard = new SimpleRole("*");
|
|
||||||
resource.getIdm().add(wildcard);
|
|
||||||
roles.put("*", wildcard);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +258,7 @@ public class RealmManager {
|
||||||
boolean hasBrowserCredentials = true;
|
boolean hasBrowserCredentials = true;
|
||||||
for (RequiredCredentialRepresentation credential : rep.getRequiredCredentials()) {
|
for (RequiredCredentialRepresentation credential : rep.getRequiredCredentials()) {
|
||||||
boolean hasCredential = false;
|
boolean hasCredential = false;
|
||||||
for (UserRepresentation.Credential cred : userRep.getCredentials()) {
|
for (CredentialRepresentation cred : userRep.getCredentials()) {
|
||||||
if (cred.getType().equals(credential.getType())) {
|
if (cred.getType().equals(credential.getType())) {
|
||||||
hasCredential = true;
|
hasCredential = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||||
|
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||||
|
import org.keycloak.TokenIdGenerator;
|
||||||
|
import org.keycloak.representations.idm.admin.LogoutAction;
|
||||||
|
import org.keycloak.services.models.RealmModel;
|
||||||
|
import org.keycloak.services.models.ResourceModel;
|
||||||
|
|
||||||
|
import javax.ws.rs.client.Entity;
|
||||||
|
import javax.ws.rs.core.Form;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ResourceAdminManager {
|
||||||
|
|
||||||
|
public void logoutAll(RealmModel realm) {
|
||||||
|
singleLogOut(realm, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void singleLogOut(RealmModel realm, String user) {
|
||||||
|
ResteasyClient client = new ResteasyClientBuilder()
|
||||||
|
.disableTrustManager() // todo fix this, should have a trust manager or a good default
|
||||||
|
.build();
|
||||||
|
|
||||||
|
List<ResourceModel> resources = realm.getResources();
|
||||||
|
for (ResourceModel resource : resources) {
|
||||||
|
logoutResource(realm, resource, user, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean logoutResource(RealmModel realm, ResourceModel resource, String user, ResteasyClient client) {
|
||||||
|
LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), System.currentTimeMillis() / 1000 + 30, resource.getName(), user);
|
||||||
|
String token = new TokenManager().encodeToken(realm, adminAction);
|
||||||
|
Form form = new Form();
|
||||||
|
form.param("token", token);
|
||||||
|
Response response = client.target(resource.getManagementUrl()).queryParam("action", "logout").request().post(Entity.form(form));
|
||||||
|
boolean success = response.getStatus() == 204;
|
||||||
|
response.close();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,15 +3,17 @@ package org.keycloak.services.managers;
|
||||||
import org.jboss.resteasy.jose.Base64Url;
|
import org.jboss.resteasy.jose.Base64Url;
|
||||||
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
||||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||||
|
import org.jboss.resteasy.spi.HttpResponse;
|
||||||
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
import org.keycloak.representations.SkeletonKeyScope;
|
import org.keycloak.representations.SkeletonKeyScope;
|
||||||
import org.keycloak.representations.SkeletonKeyToken;
|
import org.keycloak.representations.SkeletonKeyToken;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.ResourceModel;
|
import org.keycloak.services.models.ResourceModel;
|
||||||
import org.keycloak.services.resources.RealmsResource;
|
import org.keycloak.services.resources.RealmsResource;
|
||||||
import org.keycloak.services.resources.TokenService;
|
|
||||||
import org.picketlink.idm.model.User;
|
import org.picketlink.idm.model.User;
|
||||||
|
|
||||||
import javax.ws.rs.ForbiddenException;
|
import javax.ws.rs.ForbiddenException;
|
||||||
|
import javax.ws.rs.core.Cookie;
|
||||||
import javax.ws.rs.core.NewCookie;
|
import javax.ws.rs.core.NewCookie;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
@ -38,6 +40,7 @@ public class TokenManager {
|
||||||
accessCodeMap.clear();
|
accessCodeMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public AccessCodeEntry pullAccessCode(String key) {
|
public AccessCodeEntry pullAccessCode(String key) {
|
||||||
return accessCodeMap.remove(key);
|
return accessCodeMap.remove(key);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +58,7 @@ public class TokenManager {
|
||||||
{
|
{
|
||||||
SkeletonKeyToken token = null;
|
SkeletonKeyToken token = null;
|
||||||
if (scopeParam != null) token = createScopedToken(scopeParam, realm, client, user);
|
if (scopeParam != null) token = createScopedToken(scopeParam, realm, client, user);
|
||||||
else token = createLoginToken(realm, client, user);
|
else token = createUnscopedToken(realm, client, user);
|
||||||
|
|
||||||
AccessCodeEntry code = new AccessCodeEntry();
|
AccessCodeEntry code = new AccessCodeEntry();
|
||||||
code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
|
code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
|
||||||
|
@ -72,15 +75,7 @@ public class TokenManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkeletonKeyToken createScopedToken(SkeletonKeyScope scope, RealmModel realm, User client, User user) {
|
public SkeletonKeyToken createScopedToken(SkeletonKeyScope scope, RealmModel realm, User client, User user) {
|
||||||
SkeletonKeyToken token = new SkeletonKeyToken();
|
SkeletonKeyToken token = initToken(realm, client, user);
|
||||||
token.id(RealmManager.generateId());
|
|
||||||
token.principal(user.getLoginName());
|
|
||||||
token.audience(realm.getName());
|
|
||||||
token.issuedNow();
|
|
||||||
token.issuedFor(client.getLoginName());
|
|
||||||
if (realm.getTokenLifespan() > 0) {
|
|
||||||
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
|
|
||||||
}
|
|
||||||
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
|
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
|
||||||
|
|
||||||
for (String res : scope.keySet()) {
|
for (String res : scope.keySet()) {
|
||||||
|
@ -102,23 +97,53 @@ public class TokenManager {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected SkeletonKeyToken initToken(RealmModel realm, User client, User user) {
|
||||||
|
SkeletonKeyToken token = new SkeletonKeyToken();
|
||||||
|
token.id(RealmManager.generateId());
|
||||||
|
token.principal(user.getLoginName());
|
||||||
|
token.audience(realm.getName());
|
||||||
|
token.issuedNow();
|
||||||
|
token.issuedFor(client.getLoginName());
|
||||||
|
if (realm.getTokenLifespan() > 0) {
|
||||||
|
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
public SkeletonKeyToken createScopedToken(String scopeParam, RealmModel realm, User client, User user) {
|
public SkeletonKeyToken createScopedToken(String scopeParam, RealmModel realm, User client, User user) {
|
||||||
SkeletonKeyScope scope = decodeScope(scopeParam);
|
SkeletonKeyScope scope = decodeScope(scopeParam);
|
||||||
return createScopedToken(scope, realm, client, user);
|
return createScopedToken(scope, realm, client, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkeletonKeyToken createLoginToken(RealmModel realm, User client, User user) {
|
public SkeletonKeyToken createUnscopedToken(RealmModel realm, User client, User user) {
|
||||||
Set<String> mapping = realm.getScopes(client);
|
|
||||||
if (!mapping.contains("*")) {
|
SkeletonKeyToken token = initToken(realm, client, user);
|
||||||
throw new ForbiddenException(Response.status(403).entity("<h1>Security Alert</h1><p>Known client not authorized to request a user login.</p>").type("text/html").build());
|
|
||||||
|
Set<String> realmMapping = realm.getRoleMappings(user);
|
||||||
|
|
||||||
|
if (realmMapping != null && realmMapping.size() > 0) {
|
||||||
|
Set<String> scope = realm.getScope(client);
|
||||||
|
SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
|
||||||
|
for (String role : realmMapping) {
|
||||||
|
if (scope.contains("*") || scope.contains(role)) access.addRole(role);
|
||||||
|
}
|
||||||
|
token.setRealmAccess(access);
|
||||||
|
}
|
||||||
|
List<ResourceModel> resources = realm.getResources();
|
||||||
|
for (ResourceModel resource : resources) {
|
||||||
|
Set<String> scope = resource.getScope(client);
|
||||||
|
Set<String> mapping = resource.getRoleMappings(user);
|
||||||
|
if (mapping.size() == 0 || scope.size() == 0) continue;
|
||||||
|
SkeletonKeyToken.Access access = token.addAccess(resource.getName())
|
||||||
|
.verifyCaller(resource.isSurrogateAuthRequired());
|
||||||
|
for (String role : mapping) {
|
||||||
|
if (scope.contains("*") || scope.contains(role)) access.addRole(role);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SkeletonKeyToken token = createAccessToken(realm, user);
|
|
||||||
token.issuedFor(client.getLoginName());
|
|
||||||
return token;
|
return token;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String encodeScope(SkeletonKeyScope scope) {
|
public String encodeScope(SkeletonKeyScope scope) {
|
||||||
String token = null;
|
String token = null;
|
||||||
try {
|
try {
|
||||||
|
@ -187,7 +212,7 @@ public class TokenManager {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String encodeToken(RealmModel realm, SkeletonKeyToken token) {
|
public String encodeToken(RealmModel realm, Object token) {
|
||||||
byte[] tokenBytes = null;
|
byte[] tokenBytes = null;
|
||||||
try {
|
try {
|
||||||
tokenBytes = JsonSerialization.toByteArray(token, false);
|
tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||||
|
|
|
@ -18,6 +18,8 @@ import org.picketlink.idm.model.Attribute;
|
||||||
import org.picketlink.idm.model.Grant;
|
import org.picketlink.idm.model.Grant;
|
||||||
import org.picketlink.idm.model.Realm;
|
import org.picketlink.idm.model.Realm;
|
||||||
import org.picketlink.idm.model.Role;
|
import org.picketlink.idm.model.Role;
|
||||||
|
import org.picketlink.idm.model.SimpleRole;
|
||||||
|
import org.picketlink.idm.model.SimpleUser;
|
||||||
import org.picketlink.idm.model.Tier;
|
import org.picketlink.idm.model.Tier;
|
||||||
import org.picketlink.idm.model.User;
|
import org.picketlink.idm.model.User;
|
||||||
import org.picketlink.idm.query.IdentityQuery;
|
import org.picketlink.idm.query.IdentityQuery;
|
||||||
|
@ -293,8 +295,15 @@ public class RealmModel {
|
||||||
relationship.setResourceName(name);
|
relationship.setResourceName(name);
|
||||||
relationship.setRealmAgent(realmAgent);
|
relationship.setRealmAgent(realmAgent);
|
||||||
relationship.setResourceId(newTier.getId());
|
relationship.setResourceId(newTier.getId());
|
||||||
|
relationship.setManagementUrl(""); // Picketlink doesn't like null attribute values
|
||||||
|
User resourceUser = new SimpleUser(name);
|
||||||
|
idm.add(resourceUser);
|
||||||
|
relationship.setResourceUser(resourceUser);
|
||||||
idm.add(relationship);
|
idm.add(relationship);
|
||||||
return new ResourceModel(newTier, relationship, this, identitySession);
|
ResourceModel resource = new ResourceModel(newTier, relationship, this, identitySession);
|
||||||
|
resource.getIdm().add(new SimpleRole("*"));
|
||||||
|
resource.addScope(resourceUser, "*");
|
||||||
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getRoleMappings(User user) {
|
public Set<String> getRoleMappings(User user) {
|
||||||
|
@ -320,7 +329,7 @@ public class RealmModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Set<String> getScopes(Agent agent) {
|
public Set<String> getScope(Agent agent) {
|
||||||
RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class);
|
RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class);
|
||||||
query.setParameter(ScopeRelationship.CLIENT, agent);
|
query.setParameter(ScopeRelationship.CLIENT, agent);
|
||||||
List<ScopeRelationship> scope = query.getResultList();
|
List<ScopeRelationship> scope = query.getResultList();
|
||||||
|
|
|
@ -41,6 +41,10 @@ public class ResourceModel {
|
||||||
getIdm().update(agent);
|
getIdm().update(agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public User getResourceUser() {
|
||||||
|
return agent.getResourceUser();
|
||||||
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return tier.getId();
|
return tier.getId();
|
||||||
}
|
}
|
||||||
|
@ -69,6 +73,14 @@ public class ResourceModel {
|
||||||
agent.setSurrogateAuthRequired(surrogateAuthRequired);
|
agent.setSurrogateAuthRequired(surrogateAuthRequired);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getManagementUrl() {
|
||||||
|
return agent.getManagementUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setManagementUrl(String url) {
|
||||||
|
agent.setManagementUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
public List<Role> getRoles() {
|
public List<Role> getRoles() {
|
||||||
IdentityQuery<Role> query = getIdm().createIdentityQuery(Role.class);
|
IdentityQuery<Role> query = getIdm().createIdentityQuery(Role.class);
|
||||||
query.setParameter(Role.PARTITION, tier);
|
query.setParameter(Role.PARTITION, tier);
|
||||||
|
@ -90,10 +102,14 @@ public class ResourceModel {
|
||||||
IdentityManager idm = getIdm();
|
IdentityManager idm = getIdm();
|
||||||
Role role = idm.getRole(roleName);
|
Role role = idm.getRole(roleName);
|
||||||
if (role == null) throw new RuntimeException("role not found");
|
if (role == null) throw new RuntimeException("role not found");
|
||||||
|
addScope(agent, role);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addScope(Agent agent, Role role) {
|
||||||
ScopeRelationship scope = new ScopeRelationship();
|
ScopeRelationship scope = new ScopeRelationship();
|
||||||
scope.setClient(agent);
|
scope.setClient(agent);
|
||||||
scope.setScope(role);
|
scope.setScope(role);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getScope(Agent agent) {
|
public Set<String> getScope(Agent agent) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.keycloak.services.models.relationships;
|
||||||
import org.picketlink.idm.model.AbstractAttributedType;
|
import org.picketlink.idm.model.AbstractAttributedType;
|
||||||
import org.picketlink.idm.model.Agent;
|
import org.picketlink.idm.model.Agent;
|
||||||
import org.picketlink.idm.model.Relationship;
|
import org.picketlink.idm.model.Relationship;
|
||||||
|
import org.picketlink.idm.model.User;
|
||||||
import org.picketlink.idm.model.annotation.AttributeProperty;
|
import org.picketlink.idm.model.annotation.AttributeProperty;
|
||||||
import org.picketlink.idm.model.annotation.IdentityProperty;
|
import org.picketlink.idm.model.annotation.IdentityProperty;
|
||||||
import org.picketlink.idm.query.RelationshipQueryParameter;
|
import org.picketlink.idm.query.RelationshipQueryParameter;
|
||||||
|
@ -23,8 +24,10 @@ public class ResourceRelationship extends AbstractAttributedType implements Rela
|
||||||
};
|
};
|
||||||
|
|
||||||
protected Agent realmAgent;
|
protected Agent realmAgent;
|
||||||
|
protected User resourceUser;
|
||||||
protected String resourceId;
|
protected String resourceId;
|
||||||
protected String resourceName;
|
protected String resourceName;
|
||||||
|
protected String managementUrl = ""; // Picketlink doesn't like null attribute values
|
||||||
protected boolean surrogateAuthRequired;
|
protected boolean surrogateAuthRequired;
|
||||||
protected boolean enabled;
|
protected boolean enabled;
|
||||||
|
|
||||||
|
@ -37,6 +40,15 @@ public class ResourceRelationship extends AbstractAttributedType implements Rela
|
||||||
this.realmAgent = realmAgent;
|
this.realmAgent = realmAgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IdentityProperty
|
||||||
|
public User getResourceUser() {
|
||||||
|
return resourceUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResourceUser(User resourceUser) {
|
||||||
|
this.resourceUser = resourceUser;
|
||||||
|
}
|
||||||
|
|
||||||
@AttributeProperty
|
@AttributeProperty
|
||||||
public String getResourceId() {
|
public String getResourceId() {
|
||||||
return resourceId;
|
return resourceId;
|
||||||
|
@ -72,4 +84,15 @@ public class ResourceRelationship extends AbstractAttributedType implements Rela
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AttributeProperty
|
||||||
|
public String getManagementUrl()
|
||||||
|
{
|
||||||
|
return managementUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setManagementUrl(String managementUrl) {
|
||||||
|
if (managementUrl == null) managementUrl = ""; // Picketlink doesn't like NULL attribute values.
|
||||||
|
this.managementUrl = managementUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,9 +52,9 @@ public class RealmSubResource {
|
||||||
StringBuffer html = new StringBuffer();
|
StringBuffer html = new StringBuffer();
|
||||||
|
|
||||||
String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString();
|
String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString();
|
||||||
String codeUri = TokenService.accessCodeRequest(uriInfo).build(realm.getId()).toString();
|
String codeUri = TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getId()).toString();
|
||||||
String grantUrl = TokenService.grantRequest(uriInfo).build(realm.getId()).toString();
|
String grantUrl = TokenService.grantAccessTokenUrl(uriInfo).build(realm.getId()).toString();
|
||||||
String idGrantUrl = TokenService.identityGrantRequest(uriInfo).build(realm.getId()).toString();
|
String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).build(realm.getId()).toString();
|
||||||
|
|
||||||
html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>");
|
html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>");
|
||||||
html.append("<p>auth: ").append(authUri).append("</p>");
|
html.append("<p>auth: ").append(authUri).append("</p>");
|
||||||
|
@ -76,9 +76,9 @@ public class RealmSubResource {
|
||||||
rep.setAdminRole(ADMIN_ROLE);
|
rep.setAdminRole(ADMIN_ROLE);
|
||||||
|
|
||||||
rep.setAuthorizationUrl(TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString());
|
rep.setAuthorizationUrl(TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString());
|
||||||
rep.setCodeUrl(TokenService.accessCodeRequest(uriInfo).build(realm.getId()).toString());
|
rep.setCodeUrl(TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getId()).toString());
|
||||||
rep.setGrantUrl(TokenService.grantRequest(uriInfo).build(realm.getId()).toString());
|
rep.setGrantUrl(TokenService.grantAccessTokenUrl(uriInfo).build(realm.getId()).toString());
|
||||||
String idGrantUrl = TokenService.identityGrantRequest(uriInfo).build(realm.getId()).toString();
|
String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).build(realm.getId()).toString();
|
||||||
rep.setIdentityGrantUrl(idGrantUrl);
|
rep.setIdentityGrantUrl(idGrantUrl);
|
||||||
return rep;
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.resteasy.logging.Logger;
|
import org.jboss.resteasy.logging.Logger;
|
||||||
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
|
@ -12,10 +13,8 @@ import org.picketlink.idm.model.User;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.ForbiddenException;
|
import javax.ws.rs.ForbiddenException;
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
@ -57,7 +56,7 @@ public class RegistrationService {
|
||||||
|
|
||||||
user = new SimpleUser(newUser.getUsername());
|
user = new SimpleUser(newUser.getUsername());
|
||||||
defaultRealm.getIdm().add(user);
|
defaultRealm.getIdm().add(user);
|
||||||
for (UserRepresentation.Credential cred : newUser.getCredentials()) {
|
for (CredentialRepresentation cred : newUser.getCredentials()) {
|
||||||
UserCredentialModel credModel = new UserCredentialModel();
|
UserCredentialModel credModel = new UserCredentialModel();
|
||||||
credModel.setType(cred.getType());
|
credModel.setType(cred.getType());
|
||||||
credModel.setValue(cred.getValue());
|
credModel.setValue(cred.getValue());
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.keycloak.representations.SkeletonKeyToken;
|
||||||
import org.keycloak.services.JspRequestParameters;
|
import org.keycloak.services.JspRequestParameters;
|
||||||
import org.keycloak.services.managers.AccessCodeEntry;
|
import org.keycloak.services.managers.AccessCodeEntry;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
|
import org.keycloak.services.managers.ResourceAdminManager;
|
||||||
import org.keycloak.services.managers.TokenManager;
|
import org.keycloak.services.managers.TokenManager;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.RequiredCredentialModel;
|
import org.keycloak.services.models.RequiredCredentialModel;
|
||||||
|
@ -31,7 +32,6 @@ import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.NewCookie;
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.SecurityContext;
|
import javax.ws.rs.core.SecurityContext;
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
@ -51,7 +51,6 @@ public class TokenService {
|
||||||
|
|
||||||
|
|
||||||
protected static final Logger logger = Logger.getLogger(TokenService.class);
|
protected static final Logger logger = Logger.getLogger(TokenService.class);
|
||||||
//protected Map<String, AccessCodeEntry> accessCodeMap;
|
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
protected UriInfo uriInfo;
|
protected UriInfo uriInfo;
|
||||||
|
@ -73,39 +72,40 @@ public class TokenService {
|
||||||
protected RealmModel realm;
|
protected RealmModel realm;
|
||||||
protected TokenManager tokenManager;
|
protected TokenManager tokenManager;
|
||||||
protected AuthenticationManager authManager = new AuthenticationManager();
|
protected AuthenticationManager authManager = new AuthenticationManager();
|
||||||
|
private ResourceAdminManager resourceAdminManager = new ResourceAdminManager();
|
||||||
|
|
||||||
public TokenService(RealmModel realm, TokenManager tokenManager) {
|
public TokenService(RealmModel realm, TokenManager tokenManager) {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.tokenManager = tokenManager;
|
this.tokenManager = tokenManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UriBuilder tokenServiceBase(UriInfo uriInfo) {
|
public static UriBuilder tokenServiceBaseUrl(UriInfo uriInfo) {
|
||||||
UriBuilder base = uriInfo.getBaseUriBuilder()
|
UriBuilder base = uriInfo.getBaseUriBuilder()
|
||||||
.path(RealmsResource.class).path(RealmsResource.class, "getTokenService");
|
.path(RealmsResource.class).path(RealmsResource.class, "getTokenService");
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UriBuilder accessCodeRequest(UriInfo uriInfo) {
|
public static UriBuilder accessCodeToTokenUrl(UriInfo uriInfo) {
|
||||||
return tokenServiceBase(uriInfo).path(TokenService.class, "accessRequest");
|
return tokenServiceBaseUrl(uriInfo).path(TokenService.class, "accessCodeToToken");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UriBuilder grantRequest(UriInfo uriInfo) {
|
public static UriBuilder grantAccessTokenUrl(UriInfo uriInfo) {
|
||||||
return tokenServiceBase(uriInfo).path(TokenService.class, "accessTokenGrant");
|
return tokenServiceBaseUrl(uriInfo).path(TokenService.class, "grantAccessToken");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UriBuilder identityGrantRequest(UriInfo uriInfo) {
|
public static UriBuilder grantIdentityTokenUrl(UriInfo uriInfo) {
|
||||||
return tokenServiceBase(uriInfo).path(TokenService.class, "accessTokenGrant");
|
return tokenServiceBaseUrl(uriInfo).path(TokenService.class, "grantIdentityToken");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UriBuilder loginPageUrl(UriInfo uriInfo) {
|
public static UriBuilder loginPageUrl(UriInfo uriInfo) {
|
||||||
return tokenServiceBase(uriInfo).path(TokenService.class, "loginRequest");
|
return tokenServiceBaseUrl(uriInfo).path(TokenService.class, "loginPage");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UriBuilder logainActionUrl(UriInfo uriInfo) {
|
public static UriBuilder processLoginUrl(UriInfo uriInfo) {
|
||||||
return tokenServiceBase(uriInfo).path(TokenService.class, "login");
|
return tokenServiceBaseUrl(uriInfo).path(TokenService.class, "processLogin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ public class TokenService {
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response identityTokenGrant(MultivaluedMap<String, String> form) {
|
public Response grantIdentityToken(MultivaluedMap<String, String> form) {
|
||||||
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||||
if (username == null) {
|
if (username == null) {
|
||||||
throw new NotAuthorizedException("No user");
|
throw new NotAuthorizedException("No user");
|
||||||
|
@ -142,7 +142,7 @@ public class TokenService {
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response accessTokenGrant(MultivaluedMap<String, String> form) {
|
public Response grantAccessToken(MultivaluedMap<String, String> form) {
|
||||||
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||||
if (username == null) {
|
if (username == null) {
|
||||||
throw new NotAuthorizedException("No user");
|
throw new NotAuthorizedException("No user");
|
||||||
|
@ -169,7 +169,7 @@ public class TokenService {
|
||||||
@Path("auth/request/login")
|
@Path("auth/request/login")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public Response login(MultivaluedMap<String, String> formData) {
|
public Response processLogin(MultivaluedMap<String, String> formData) {
|
||||||
String clientId = formData.getFirst("client_id");
|
String clientId = formData.getFirst("client_id");
|
||||||
String scopeParam = formData.getFirst("scope");
|
String scopeParam = formData.getFirst("scope");
|
||||||
String state = formData.getFirst("state");
|
String state = formData.getFirst("state");
|
||||||
|
@ -226,7 +226,7 @@ public class TokenService {
|
||||||
@Path("access/codes")
|
@Path("access/codes")
|
||||||
@POST
|
@POST
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public Response accessRequest(MultivaluedMap<String, String> formData) {
|
public Response accessCodeToToken(MultivaluedMap<String, String> formData) {
|
||||||
logger.info("accessRequest <---");
|
logger.info("accessRequest <---");
|
||||||
if (!realm.isEnabled()) {
|
if (!realm.isEnabled()) {
|
||||||
throw new NotAuthorizedException("Realm not enabled");
|
throw new NotAuthorizedException("Realm not enabled");
|
||||||
|
@ -356,7 +356,7 @@ public class TokenService {
|
||||||
String scopeParam,
|
String scopeParam,
|
||||||
String state) {
|
String state) {
|
||||||
request.setAttribute(RealmModel.class.getName(), realm);
|
request.setAttribute(RealmModel.class.getName(), realm);
|
||||||
request.setAttribute("KEYCLOAK_LOGIN_ACTION", logainActionUrl(uriInfo).build(realm.getId()));
|
request.setAttribute("KEYCLOAK_LOGIN_ACTION", processLoginUrl(uriInfo).build(realm.getId()));
|
||||||
|
|
||||||
// RESTEASY eats the form data, so we send via an attribute
|
// RESTEASY eats the form data, so we send via an attribute
|
||||||
request.setAttribute("redirect_uri", redirect);
|
request.setAttribute("redirect_uri", redirect);
|
||||||
|
@ -369,11 +369,11 @@ public class TokenService {
|
||||||
|
|
||||||
@Path("login")
|
@Path("login")
|
||||||
@GET
|
@GET
|
||||||
public Response loginRequest(@QueryParam("response_type") String responseType,
|
public Response loginPage(@QueryParam("response_type") String responseType,
|
||||||
@QueryParam("redirect_uri") String redirect,
|
@QueryParam("redirect_uri") String redirect,
|
||||||
@QueryParam("client_id") String clientId,
|
@QueryParam("client_id") String clientId,
|
||||||
@QueryParam("scope") String scopeParam,
|
@QueryParam("scope") String scopeParam,
|
||||||
@QueryParam("state") String state) {
|
@QueryParam("state") String state) {
|
||||||
if (!realm.isEnabled()) {
|
if (!realm.isEnabled()) {
|
||||||
securityFailureForward("Realm not enabled");
|
securityFailureForward("Realm not enabled");
|
||||||
return null;
|
return null;
|
||||||
|
@ -390,7 +390,7 @@ public class TokenService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
User user = authManager.authenticateIdentityCookie(realm, headers);
|
User user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
return redirectAccessCode(scopeParam, state, redirect, client, user);
|
return redirectAccessCode(scopeParam, state, redirect, client, user);
|
||||||
}
|
}
|
||||||
|
@ -400,6 +400,21 @@ public class TokenService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Path("logout")
|
||||||
|
@GET
|
||||||
|
public Response logout(@QueryParam("redirect_uri") String redirectUri) {
|
||||||
|
// todo do we care if anybody can trigger this?
|
||||||
|
|
||||||
|
User user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
|
if (user != null) {
|
||||||
|
logger.info("Logging out: " + user.getLoginName());
|
||||||
|
authManager.expireIdentityCookie(realm, uriInfo);
|
||||||
|
resourceAdminManager.singleLogOut(realm, user.getLoginName());
|
||||||
|
}
|
||||||
|
// todo manage legal redirects
|
||||||
|
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
|
||||||
|
}
|
||||||
|
|
||||||
private Response loginForm(String validationError, String redirect, String clientId, String scopeParam, String state, RealmModel realm, User client) {
|
private Response loginForm(String validationError, String redirect, String clientId, String scopeParam, String state, RealmModel realm, User client) {
|
||||||
StringBuffer html = new StringBuffer();
|
StringBuffer html = new StringBuffer();
|
||||||
if (scopeParam != null) {
|
if (scopeParam != null) {
|
||||||
|
@ -431,7 +446,7 @@ public class TokenService {
|
||||||
}
|
}
|
||||||
html.append("</table><p>To Authorize, please login below</p>");
|
html.append("</table><p>To Authorize, please login below</p>");
|
||||||
} else {
|
} else {
|
||||||
Set<String> scopeMapping = realm.getScopes(client);
|
Set<String> scopeMapping = realm.getScope(client);
|
||||||
if (scopeMapping.contains("*")) {
|
if (scopeMapping.contains("*")) {
|
||||||
html.append("<h1>Login For ").append(realm.getName()).append(" Realm</h1>");
|
html.append("<h1>Login For ").append(realm.getName()).append(" Realm</h1>");
|
||||||
if (validationError != null) {
|
if (validationError != null) {
|
||||||
|
@ -485,7 +500,7 @@ public class TokenService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UriBuilder formActionUri = logainActionUrl(uriInfo);
|
UriBuilder formActionUri = processLoginUrl(uriInfo);
|
||||||
String action = formActionUri.build(realm.getId()).toString();
|
String action = formActionUri.build(realm.getId()).toString();
|
||||||
html.append("<form action=\"").append(action).append("\" method=\"POST\">");
|
html.append("<form action=\"").append(action).append("\" method=\"POST\">");
|
||||||
html.append("Username: <input type=\"text\" name=\"username\" size=\"20\"><br>");
|
html.append("Username: <input type=\"text\" name=\"username\" size=\"20\"><br>");
|
||||||
|
|
|
@ -166,7 +166,7 @@ public class AdapterTest {
|
||||||
idm.add(new SimpleRole("admin"));
|
idm.add(new SimpleRole("admin"));
|
||||||
idm.add(new SimpleRole("user"));
|
idm.add(new SimpleRole("user"));
|
||||||
List<Role> roles = realmModel.getRoles();
|
List<Role> roles = realmModel.getRoles();
|
||||||
Assert.assertEquals(2, roles.size());
|
Assert.assertEquals(3, roles.size());
|
||||||
SimpleUser user = new SimpleUser("bburke");
|
SimpleUser user = new SimpleUser("bburke");
|
||||||
idm.add(user);
|
idm.add(user);
|
||||||
Role role = idm.getRole("user");
|
Role role = idm.getRole("user");
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class ImportTest {
|
||||||
|
|
||||||
User user = realm.getIdm().getUser("loginclient");
|
User user = realm.getIdm().getUser("loginclient");
|
||||||
Assert.assertNotNull(user);
|
Assert.assertNotNull(user);
|
||||||
Set<String> scopes = realm.getScopes(user);
|
Set<String> scopes = realm.getScope(user);
|
||||||
System.out.println("Scopes size: " + scopes.size());
|
System.out.println("Scopes size: " + scopes.size());
|
||||||
Assert.assertTrue(scopes.contains("*"));
|
Assert.assertTrue(scopes.contains("*"));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue