KEYCLOAK-3882 Split server-spi into server-spi and server-spi-private

This commit is contained in:
Stian Thorgersen committed 2016-11-10 13:28:42 +01:00
1 parent 52a4509ada
commit 7e33f4a7d1
399 files changed
+551 -272

No files matched your search

@@ -1,48 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak;
/**
* Non-recoverable error thrown during server startup
*
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ServerStartupError extends Error {
private final boolean fillStackTrace;
public ServerStartupError(String message) {
super(message);
fillStackTrace = true;
}
public ServerStartupError(String message, boolean fillStackTrace) {
super(message);
this.fillStackTrace = fillStackTrace;
}
@Override
public synchronized Throwable fillInStackTrace() {
if (fillStackTrace) {
return super.fillInStackTrace();
} else {
return this;
}
}
}
@@ -1,192 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.common.ClientConnection;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.services.managers.BruteForceProtector;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface AbstractAuthenticationFlowContext {
/**
* Current event builder being used
*
* @return
*/
EventBuilder getEvent();
/**
* Create a refresh new EventBuilder to use within this context
*
* @return
*/
EventBuilder newEvent();
/**
* The current execution in the flow
*
* @return
*/
AuthenticationExecutionModel getExecution();
/**
* Current realm
*
* @return
*/
RealmModel getRealm();
/**
* Information about the IP address from the connecting HTTP client.
*
* @return
*/
ClientConnection getConnection();
/**
* UriInfo of the current request
*
* @return
*/
UriInfo getUriInfo();
/**
* Current session
*
* @return
*/
KeycloakSession getSession();
HttpRequest getHttpRequest();
BruteForceProtector getProtector();
/**
* Get any configuration associated with the current execution
*
* @return
*/
AuthenticatorConfigModel getAuthenticatorConfig();
/**
* This could be an error message forwarded from another authenticator that is restarting or continuing the flo. For example
* the brokering API sends this when the broker failed authentication
* and we want to continue authentication locally. forwardedErrorMessage can then be displayed by
* whatever form is challenging.
*/
FormMessage getForwardedErrorMessage();
/**
* This could be an success message forwarded from another authenticator that is restarting or continuing the flow. For example
* a reset password sends an email, then resets the flow with a success message. forwardedSuccessMessage can then be displayed by
* whatever form is challenging.
*/
FormMessage getForwardedSuccessMessage();
/**
* Generates access code and updates clientsession timestamp
* Access codes must be included in form action callbacks as a query parameter.
*
* @return
*/
String generateAccessCode();
AuthenticationExecutionModel.Requirement getCategoryRequirementFromCurrentFlow(String authenticatorCategory);
/**
* Mark the current execution as successful. The flow will then continue
*
*/
void success();
/**
* Aborts the current flow
*
* @param error
*/
void failure(AuthenticationFlowError error);
/**
* Aborts the current flow.
*
* @param error
* @param response Response that will be sent back to HTTP client
*/
void failure(AuthenticationFlowError error, Response response);
/**
* Sends a challenge response back to the HTTP client. If the current execution requirement is optional, this response will not be
* sent. If the current execution requirement is alternative, then this challenge will be sent if no other alternative
* execution was successful.
*
* @param challenge
*/
void challenge(Response challenge);
/**
* Sends the challenge back to the HTTP client irregardless of the current executionr equirement
*
* @param challenge
*/
void forceChallenge(Response challenge);
/**
* Same behavior as challenge(), but the error count in brute force attack detection will be incremented.
* For example, if a user enters in a bad password, the user is directed to try again, but Keycloak will keep track
* of how many failures have happened.
*
* @param error
* @param challenge
*/
void failureChallenge(AuthenticationFlowError error, Response challenge);
/**
* There was no failure or challenge. The authenticator was attempted, but not fulfilled. If the current execution
* requirement is alternative or optional, then this status is ignored by the flow.
*
*/
void attempted();
/**
* Get the current status of the current execution.
*
* @return may return null if not set yet.
*/
FlowStatus getStatus();
/**
* Get the error condition of a failed execution.
*
* @return may return null if there was no error
*/
AuthenticationFlowError getError();
}
@@ -1,33 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import javax.ws.rs.core.Response;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface AuthenticationFlow {
String BASIC_FLOW = "basic-flow";
String FORM_FLOW = "form-flow";
String CLIENT_FLOW = "client-flow";
Response processAction(String actionExecution);
Response processFlow();
}
@@ -1,133 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.FormMessage;
import java.net.URI;
/**
* This interface encapsulates information about an execution in an AuthenticationFlow. It is also used to set
* the status of the execution being performed.
*
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface AuthenticationFlowContext extends AbstractAuthenticationFlowContext {
/**
* Current user attached to this flow. It can return null if no user has been identified yet
*
* @return
*/
UserModel getUser();
/**
* Attach a specific user to this flow.
*
* @param user
*/
void setUser(UserModel user);
/**
* Clear the user from the flow.
*/
void clearUser();
void attachUserSession(UserSessionModel userSession);
/**
* ClientSessionModel attached to this flow
*
* @return
*/
ClientSessionModel getClientSession();
/**
* Create a Freemarker form builder that presets the user, action URI, and a generated access code
*
* @return
*/
LoginFormsProvider form();
/**
* Get the action URL for the required action.
*
* @param code client session access code
* @return
*/
URI getActionUrl(String code);
/**
* Get the action URL for the required action. This auto-generates the access code.
*
* @return
*/
URI getActionUrl();
/**
* End the flow and redirect browser based on protocol specific respones. This should only be executed
* in browser-based flows.
*
*/
void cancelLogin();
/**
* Reset the current flow to the beginning and restarts it.
*
*/
void resetFlow();
/**
* Fork the current flow. The client session will be cloned and set to point at the realm's browser login flow. The Response will be the result
* of this fork. The previous flow will still be set at the current execution. This is used by reset password when it sends an email.
* It sends an email linking to the current flow and redirects the browser to a new browser login flow.
*
*
*
* @return
*/
void fork();
/**
* Fork the current flow. The client session will be cloned and set to point at the realm's browser login flow. The Response will be the result
* of this fork. The previous flow will still be set at the current execution. This is used by reset password when it sends an email.
* It sends an email linking to the current flow and redirects the browser to a new browser login flow.
*
* This method will set up a success message that will be displayed in the first page of the new flow
*
* @param message Corresponds to raw text or a message property defined in a message bundle
*/
void forkWithSuccessMessage(FormMessage message);
/**
* Fork the current flow. The client session will be cloned and set to point at the realm's browser login flow. The Response will be the result
* of this fork. The previous flow will still be set at the current execution. This is used by reset password when it sends an email.
* It sends an email linking to the current flow and redirects the browser to a new browser login flow.
*
* This method will set up an error message that will be displayed in the first page of the new flow
*
* @param message Corresponds to raw text or a message property defined in a message bundle
*/
void forkWithErrorMessage(FormMessage message);
}
@@ -1,47 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
/**
* Set of error codes that can be thrown by an Authenticator, FormAuthenticator, or FormAction
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public enum AuthenticationFlowError {
EXPIRED_CODE,
INVALID_CLIENT_SESSION,
INVALID_USER,
INVALID_CREDENTIALS,
CREDENTIAL_SETUP_REQUIRED,
USER_DISABLED,
USER_CONFLICT,
USER_TEMPORARILY_DISABLED,
INTERNAL_ERROR,
UNKNOWN_USER,
FORK_FLOW,
UNKNOWN_CLIENT,
CLIENT_NOT_FOUND,
CLIENT_DISABLED,
CLIENT_CREDENTIALS_SETUP_REQUIRED,
INVALID_CLIENT_CREDENTIALS,
IDENTITY_PROVIDER_NOT_FOUND,
IDENTITY_PROVIDER_DISABLED,
IDENTITY_PROVIDER_ERROR
}
@@ -1,56 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
/**
* Throw this exception from an Authenticator, FormAuthenticator, or FormAction if you want to completely abort the flow.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AuthenticationFlowException extends RuntimeException {
private AuthenticationFlowError error;
public AuthenticationFlowException(AuthenticationFlowError error) {
this.error = error;
}
public AuthenticationFlowException(String message, AuthenticationFlowError error) {
super(message);
this.error = error;
}
public AuthenticationFlowException(String message, Throwable cause, AuthenticationFlowError error) {
super(message, cause);
this.error = error;
}
public AuthenticationFlowException(Throwable cause, AuthenticationFlowError error) {
super(cause);
this.error = error;
}
public AuthenticationFlowException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, AuthenticationFlowError error) {
super(message, cause, enableSuppression, writableStackTrace);
this.error = error;
}
public AuthenticationFlowError getError() {
return error;
}
}
@@ -1,88 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.Provider;
/**
* This interface is for users that want to add custom authenticators to an authentication flow.
* You must implement this interface as well as an AuthenticatorFactory.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface Authenticator extends Provider {
/**
* Initial call for the authenticator. This method should check the current HTTP request to determine if the request
* satifies the Authenticator's requirements. If it doesn't, it should send back a challenge response by calling
* the AuthenticationFlowContext.challenge(Response). If this challenge is a authentication, the action URL
* of the form must point to
*
* /realms/{realm}/login-actions/authenticate?code={session-code}&execution={executionId}
*
* or
*
* /realms/{realm}/login-actions/registration?code={session-code}&execution={executionId}
*
* {session-code} pertains to the code generated from AuthenticationFlowContext.generateAccessCode(). The {executionId}
* pertains to the AuthenticationExecutionModel.getId() value obtained from AuthenticationFlowContext.getExecution().
*
* The action URL will invoke the action() method described below.
*
* @param context
*/
void authenticate(AuthenticationFlowContext context);
/**
* Called from a form action invocation.
*
* @param context
*/
void action(AuthenticationFlowContext context);
/**
* Does this authenticator require that the user has already been identified? That AuthenticatorContext.getUser() is not null?
*
* @return
*/
boolean requiresUser();
/**
* Is this authenticator configured for this user.
*
* @param session
* @param realm
* @param user
* @return
*/
boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user);
/**
* Set actions to configure authenticator
*
*/
void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user);
}
@@ -1,33 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.ProviderFactory;
/**
* Factory for creating Authenticator instances. This is a singleton and created when Keycloak boots.
*
* You must specify a file
* META-INF/services/org.keycloak.authentication.AuthenticatorFactory in the jar that this class is contained in
* This file must have the fully qualified class name of all your AuthenticatorFactory classes
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface AuthenticatorFactory extends ProviderFactory<Authenticator>, ConfigurableAuthenticatorFactory {
}
@@ -1,49 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class AuthenticatorSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "authenticator";
}
@Override
public Class<? extends Provider> getProviderClass() {
return Authenticator.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return AuthenticatorFactory.class;
}
}
@@ -1,56 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.models.ClientModel;
import java.util.Map;
/**
* Encapsulates information about the execution in ClientAuthenticationFlow
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ClientAuthenticationFlowContext extends AbstractAuthenticationFlowContext {
/**
* Current client attached to this flow. It can return null if no client has been identified yet
*
* @return
*/
ClientModel getClient();
/**
* Attach a specific client to this flow.
*
* @param client
*/
void setClient(ClientModel client);
/**
* Return the map where the authenticators can put some additional state related to authenticated client and the context how was
* client authenticated (ie. attributes from client certificate etc). Map is writable, so you can add/remove items from it as needed.
*
* After successful authentication will be those state data put into UserSession notes. This allows you to configure
* UserSessionNote protocol mapper for your client, which will allow to map those state data into the access token available in the application
*
* @return
*/
Map<String, String> getClientAuthAttributes();
}
@@ -1,45 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.Provider;
/**
* This interface is for users that want to add custom client authenticators to an authentication flow.
* You must implement this interface as well as a ClientAuthenticatorFactory.
*
* This interface is for verifying client credentials from request. On the adapter side, you must also implement org.keycloak.adapters.authentication.ClientCredentialsProvider , which is supposed
* to add the client credentials to the request, which will ClientAuthenticator verify on server side
*
* @see org.keycloak.authentication.authenticators.client.ClientIdAndSecretAuthenticator
* @see org.keycloak.authentication.authenticators.client.JWTClientAuthenticator
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ClientAuthenticator extends Provider {
/**
* Initial call for the authenticator. This method should check the current HTTP request to determine if the request
* satisfies the ClientAuthenticator's requirements. If it doesn't, it should send back a challenge response by calling
* the ClientAuthenticationFlowContext.challenge(Response).
*
* @param context
*/
void authenticateClient(ClientAuthenticationFlowContext context);
}
@@ -1,72 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.models.ClientModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderFactory;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Factory for creating ClientAuthenticator instances. This is a singleton and created when Keycloak boots.
*
* You must specify a file
* META-INF/services/org.keycloak.authentication.ClientAuthenticatorFactory in the jar that this class is contained in
* This file must have the fully qualified class name of all your ClientAuthenticatorFactory classes
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ClientAuthenticatorFactory extends ProviderFactory<ClientAuthenticator>, ConfigurableAuthenticatorFactory {
ClientAuthenticator create();
/**
* Is this authenticator configurable globally?
*
* @return
*/
@Override
boolean isConfigurable();
/**
* List of config properties for this client implementation. Those will be shown in admin console in clients credentials tab and can be configured per client.
* Applicable only if "isConfigurablePerClient" is true
*
* @return
*/
List<ProviderConfigProperty> getConfigPropertiesPerClient();
/**
* Get configuration, which needs to be used for adapter ( keycloak.json ) of particular client. Some implementations
* may return just template and user needs to edit the values according to his environment (For example fill the location of keystore file)
*
* @return
*/
Map<String, Object> getAdapterConfiguration(ClientModel client);
/**
* Get authentication methods for the specified protocol
*
* @param loginProtocol corresponds to {@link org.keycloak.protocol.LoginProtocolFactory#getId}
* @return name of supported client authenticator methods in the protocol specific "language"
*/
Set<String> getProtocolAuthenticatorMethods(String loginProtocol);
}
@@ -1,48 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ClientAuthenticatorSpi implements Spi {
@Override
public boolean isInternal() {
return false;
}
@Override
public String getName() {
return "client-authenticator";
}
@Override
public Class<? extends Provider> getProviderClass() {
return ClientAuthenticator.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return ClientAuthenticatorFactory.class;
}
}
@@ -1,65 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.provider.ConfiguredProvider;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ConfigurableAuthenticatorFactory extends ConfiguredProvider {
/**
* Friendly name for the authenticator
*
* @return
*/
String getDisplayType();
/**
* General authenticator type, i.e. totp, password, cert.
*
* @return null if not a referencable category
*/
String getReferenceCategory();
/**
* Is this authenticator configurable?
*
* @return
*/
boolean isConfigurable();
/**
* What requirement settings are allowed.
*
* @return
*/
AuthenticationExecutionModel.Requirement[] getRequirementChoices();
/**
*
* Does this authenticator have required actions that can set if the user does not have
* this authenticator set up?
*
*
* @return
*/
boolean isUserSetupAllowed();
}
@@ -1,77 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
/**
* Status of an execution/authenticator in a Authentication Flow
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public enum FlowStatus {
/**
* Successful execution
*/
SUCCESS,
/**
* Execution offered a challenge. Optional executions will ignore this challenge. Alternative executions may
* ignore the challenge depending on the status of other executions in the flow.
*
*/
CHALLENGE,
/**
* Irregardless of the execution's requirement, this challenge will be sent to the user.
*
*/
FORCE_CHALLENGE,
/**
* Flow will be aborted and a Response provided by the execution will be sent.
*
*/
FAILURE_CHALLENGE,
/**
* Flow will be aborted.
*
*/
FAILED,
/**
* This is not an error condition. Execution was attempted, but the authenticator is unable to process the request. An example of this is if
* a Kerberos authenticator did not see a negotiate header. There was no error, but the execution was attempted.
*
*/
ATTEMPTED,
/**
* This flow is being forked. The current client session is being cloned, reset, and redirected to browser login.
*
*/
FORK,
/**
* This flow was reset to the beginning. An example is hitting cancel on the OTP page which will bring you back to the
* username password page.
*
*/
FLOW_RESET
}
@@ -1,46 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.models.utils.FormMessage;
/**
* Thrown internally when authenticator wants to fork the current flow.
*
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ForkFlowException extends AuthenticationFlowException {
protected FormMessage successMessage;
protected FormMessage errorMessage;
public FormMessage getSuccessMessage() {
return successMessage;
}
public FormMessage getErrorMessage() {
return errorMessage;
}
public ForkFlowException(FormMessage successMessage, FormMessage errorMessage) {
super(AuthenticationFlowError.FORK_FLOW);
this.successMessage = successMessage;
this.errorMessage = errorMessage;
}
}
@@ -1,82 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.Provider;
/**
* Fine grain processing of a form. Allows you to split up the processing of a form into smaller parts so that you can
* enable/disable them from the admin console. For example, Recaptcha is a FormAction. This allows you as the admin
* to turn Recaptcha on/off even though it is on the same form/page as other registration validation.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface FormAction extends Provider {
/**
* When a FormAuthenticator is rendering the challenge page, even FormAction.buildPage() method will be called
* This gives the FormAction the opportunity to add additional attributes to the form to be displayed.
*
* @param context
* @param form
*/
void buildPage(FormContext context, LoginFormsProvider form);
/**
* This is the first phase of form processing. Each FormAction.validate() method is called. This gives the
* FormAction a chance to validate and challenge if user input is invalid.
*
* @param context
*/
void validate(ValidationContext context);
/**
* Called after all validate() calls of all FormAction providers are successful.
*
* @param context
*/
void success(FormContext context);
/**
* Does this FormAction require that a user be set? For registration, this method will always return false.
*
* @return
*/
boolean requiresUser();
/**
* Is this FormAction configured for the current user?
*
* @param session
* @param realm
* @param user
* @return
*/
boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user);
/**
* Set actions to configure authenticator
*
*/
void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user);
}
@@ -1,33 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.ProviderFactory;
/**
* Factory for instantiating FormAction objects. This is a singleton and created when Keycloak boots.
*
* You must specify a file
* META-INF/services/org.keycloak.authentication.FormActionFactory in the jar that this class is contained in
* This file must have the fully qualified class name of all your FormActionFactory classes
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface FormActionFactory extends ProviderFactory<FormAction>, ConfigurableAuthenticatorFactory {
}
@@ -1,49 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class FormActionSpi implements Spi {
@Override
public boolean isInternal() {
return false;
}
@Override
public String getName() {
return "form-action";
}
@Override
public Class<? extends Provider> getProviderClass() {
return FormAction.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return FormActionFactory.class;
}
}
@@ -1,44 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.provider.Provider;
import javax.ws.rs.core.Response;
/**
* This class is responsible for rendering a form. The way it works is that each FormAction that is a child of this
* FormAuthenticator, will have its buildPage() method call first, then the FormAuthenticator.render() method will be invoked.
*
* This gives each FormAction a chance to add information to the form in an independent manner.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface FormAuthenticator extends Provider {
/**
* Called to render the FormAuthenticator's challenge page. If null is returned, then success is assumed and the
* next authenticator in the flow will be invoked.
*
* @param context
* @param form
* @return
*/
Response render(FormContext context, LoginFormsProvider form);
}
@@ -1,33 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.ProviderFactory;
/**
* Factory for instantiating FormAuthenticators. This is a singleton and created when Keycloak boots.
*
* You must specify a file
* META-INF/services/org.keycloak.authentication.FormAuthenticatorFactory in the jar that this class is contained in
* This file must have the fully qualified class name of all your FormAuthenticatorFactory classes
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface FormAuthenticatorFactory extends ProviderFactory<FormAuthenticator>, ConfigurableAuthenticatorFactory {
}
@@ -1,49 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class FormAuthenticatorSpi implements Spi {
@Override
public boolean isInternal() {
return false;
}
@Override
public String getName() {
return "form-authenticator";
}
@Override
public Class<? extends Provider> getProviderClass() {
return FormAuthenticator.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return FormAuthenticatorFactory.class;
}
}
@@ -1,117 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.common.ClientConnection;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import javax.ws.rs.core.UriInfo;
/**
* Interface that encapsulates the current state of the current form being executed
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface FormContext {
/**
* Current event builder being used
*
* @return
*/
EventBuilder getEvent();
/**
* Create a refresh new EventBuilder to use within this context
*
* @return
*/
EventBuilder newEvent();
/**
* The current execution in the flow
*
* @return
*/
AuthenticationExecutionModel getExecution();
/**
* Current user attached to this flow. It can return null if no uesr has been identified yet
*
* @return
*/
UserModel getUser();
/**
* Attach a specific user to this flow.
*
* @param user
*/
void setUser(UserModel user);
/**
* Current realm
*
* @return
*/
RealmModel getRealm();
/**
* ClientSessionModel attached to this flow
*
* @return
*/
ClientSessionModel getClientSession();
/**
* Information about the IP address from the connecting HTTP client.
*
* @return
*/
ClientConnection getConnection();
/**
* UriInfo of the current request
*
* @return
*/
UriInfo getUriInfo();
/**
* Current session
*
* @return
*/
KeycloakSession getSession();
HttpRequest getHttpRequest();
/**
* Get any configuration associated with the current execution
*
* @return
*/
AuthenticatorConfigModel getAuthenticatorConfig();
}
@@ -1,135 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.common.ClientConnection;
import org.keycloak.events.EventBuilder;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
/**
* Interface that encapsulates current information about the current requred action
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface RequiredActionContext {
public static enum Status {
CHALLENGE,
SUCCESS,
IGNORE,
FAILURE
}
/**
* Get the action URL for the required action.
*
* @param code client sessino access code
* @return
*/
URI getActionUrl(String code);
/**
* Get the action URL for the required action. This auto-generates the access code.
*
* @return
*/
URI getActionUrl();
/**
* Create a Freemarker form builder that presets the user, action URI, and a generated access code
*
* @return
*/
LoginFormsProvider form();
/**
* If challenge has been sent this returns the JAX-RS Response
*
* @return
*/
Response getChallenge();
/**
* Current event builder being used
*
* @return
*/
EventBuilder getEvent();
/**
* Current user
*
* @return
*/
UserModel getUser();
RealmModel getRealm();
ClientSessionModel getClientSession();
UserSessionModel getUserSession();
ClientConnection getConnection();
UriInfo getUriInfo();
KeycloakSession getSession();
HttpRequest getHttpRequest();
/**
* Generates access code and updates clientsession timestamp
* Access codes must be included in form action callbacks as a query parameter.
*
* @return
*/
String generateCode();
Status getStatus();
/**
* Send a challenge Response back to user
*
* @param response
*/
void challenge(Response response);
/**
* Abort the authentication with an error
*
*/
void failure();
/**
* Mark this required action as successful. The required action will be removed from the UserModel
*
*/
void success();
/**
* Ignore this required action and go onto the next, or complete the flow.
*
*/
void ignore();
}
@@ -1,38 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.ProviderFactory;
/**
* You must specify a file
* META-INF/services/org.keycloak.authentication.RequiredActionFactory in the jar that this class is contained in
* This file must have the fully qualified class name of all your RequiredActionFactory classes
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface RequiredActionFactory extends ProviderFactory<RequiredActionProvider> {
/**
* Display text used in admin console to reference this required action
*
* @return
*/
String getDisplayText();
}
@@ -1,54 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.Provider;
/**
* RequiredAction provider. Required actions are one-time actions that a user must perform before they are logged in.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface RequiredActionProvider extends Provider {
/**
* Called every time a uesr authenticates. This checks to see if this required action should be triggered.
* The implementation of this method is responsible for setting the required action on the UserModel.
*
* For example, the UpdatePassword required actions checks the password policies to see if the password has expired.
*
* @param context
*/
void evaluateTriggers(RequiredActionContext context);
/**
* If the user has a required action set, this method will be the initial call to obtain what to display to the
* user's browser. Return null if no action should be done.
*
* @param context
* @return
*/
void requiredActionChallenge(RequiredActionContext context);
/**
* Called when a required action has form input you want to process.
*
* @param context
*/
void processAction(RequiredActionContext context);
}
@@ -1,49 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class RequiredActionSpi implements Spi {
@Override
public boolean isInternal() {
return false;
}
@Override
public String getName() {
return "required-action";
}
@Override
public Class<? extends Provider> getProviderClass() {
return RequiredActionProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return RequiredActionFactory.class;
}
}
@@ -1,48 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.models.utils.FormMessage;
import javax.ws.rs.core.MultivaluedMap;
import java.util.List;
/**
* Interface that encapsulates the current validation that is being performed. Calling success() or validationError()
* sets the status of this current validation.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ValidationContext extends FormContext {
/**
* Mark this validation as having a validation error
*
* @param formData form data you want to display when the form is refreshed
* @param errors error messages to display on the form
*/
void validationError(MultivaluedMap<String, String> formData, List<FormMessage> errors);
void error(String error);
/**
* Mark this validation as sucessful
*
*/
void success();
}
@@ -1,144 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization;
import org.keycloak.authorization.permission.evaluator.Evaluators;
import org.keycloak.authorization.policy.evaluation.DefaultPolicyEvaluator;
import org.keycloak.authorization.policy.provider.PolicyProvider;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
/**
* <p>The main contract here is the creation of {@link org.keycloak.authorization.permission.evaluator.PermissionEvaluator} instances. Usually
* an application has a single {@link AuthorizationProvider} instance and threads servicing client requests obtain {@link org.keycloak.authorization.core.permission.evaluator.PermissionEvaluator}
* from the {@link #evaluators()} method.
*
* <p>The internal state of a {@link AuthorizationProvider} is immutable. This internal state includes all of the metadata
* used during the evaluation of policies.
*
* <p>Once created, {@link org.keycloak.authorization.permission.evaluator.PermissionEvaluator} instances can be obtained from the {@link #evaluators()} method:
*
* <pre>
* List<ResourcePermission> permissionsToEvaluate = getPermissions(); // the permissions to evaluate
* EvaluationContext evaluationContext = createEvaluationContext(); // the context with runtime environment information
* PermissionEvaluator evaluator = authorization.evaluators().from(permissionsToEvaluate, context);
*
* evaluator.evaluate(new Decision() {
*
* public void onDecision(Evaluation evaluation) {
* // do something on grant
* }
*
* });
* </pre>
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public final class AuthorizationProvider implements Provider {
private final DefaultPolicyEvaluator policyEvaluator;
private final Executor scheduller;
private final StoreFactory storeFactory;
private final List<PolicyProviderFactory> policyProviderFactories;
private final KeycloakSession keycloakSession;
private final RealmModel realm;
public AuthorizationProvider(KeycloakSession session, RealmModel realm, StoreFactory storeFactory, Executor scheduller) {
this.keycloakSession = session;
this.realm = realm;
this.storeFactory = storeFactory;
this.scheduller = scheduller;
this.policyProviderFactories = configurePolicyProviderFactories(session);
this.policyEvaluator = new DefaultPolicyEvaluator(this, this.policyProviderFactories);
}
public AuthorizationProvider(KeycloakSession session, RealmModel realm, StoreFactory storeFactory) {
this(session, realm, storeFactory, Runnable::run);
}
/**
* Returns a {@link Evaluators} instance from where {@link org.keycloak.authorization.policy.evaluation.PolicyEvaluator} instances
* can be obtained.
*
* @return a {@link Evaluators} instance
*/
public Evaluators evaluators() {
return new Evaluators(this.policyProviderFactories, this.policyEvaluator, this.scheduller);
}
/**
* Returns a {@link StoreFactory}.
*
* @return the {@link StoreFactory}
*/
public StoreFactory getStoreFactory() {
return this.storeFactory;
}
/**
* Returns the registered {@link PolicyProviderFactory}.
*
* @return a {@link List} containing all registered {@link PolicyProviderFactory}
*/
public List<PolicyProviderFactory> getProviderFactories() {
return this.policyProviderFactories;
}
/**
* Returns a {@link PolicyProviderFactory} given a <code>type</code>.
*
* @param type the type of the policy provider
* @param <F> the expected type of the provider
* @return a {@link PolicyProviderFactory} with the given <code>type</code>
*/
public <F extends PolicyProviderFactory> F getProviderFactory(String type) {
return (F) getProviderFactories().stream().filter(policyProviderFactory -> policyProviderFactory.getId().equals(type)).findFirst().orElse(null);
}
public KeycloakSession getKeycloakSession() {
return this.keycloakSession;
}
public RealmModel getRealm() {
return realm;
}
private List<PolicyProviderFactory> configurePolicyProviderFactories(KeycloakSession session) {
List<ProviderFactory> providerFactories = session.getKeycloakSessionFactory().getProviderFactories(PolicyProvider.class);
if (providerFactories.isEmpty()) {
throw new RuntimeException("Could not find any policy provider.");
}
return providerFactories.stream().map(providerFactory -> (PolicyProviderFactory) providerFactory).collect(Collectors.toList());
}
@Override
public void close() {
}
}
@@ -1,31 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface AuthorizationProviderFactory extends ProviderFactory<AuthorizationProvider> {
AuthorizationProvider create(KeycloakSession session, RealmModel realm);
}
@@ -1,48 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class AuthorizationSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "authorization";
}
@Override
public Class<? extends Provider> getProviderClass() {
return AuthorizationProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return AuthorizationProviderFactory.class;
}
}
@@ -1,41 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization;
import org.keycloak.authorization.policy.evaluation.Evaluation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface Decision<D extends Evaluation> {
enum Effect {
PERMIT,
DENY
}
void onDecision(D evaluation);
default void onError(Throwable cause) {
throw new RuntimeException("Not implemented.", cause);
}
default void onComplete() {
}
}
@@ -1,142 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.attribute;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
/**
* <p>Holds attributes, their values and provides utlity methods to manage them.
*
* <p>In the future, it may be useful to provide different implementations for this interface in order to plug or integrate with different
* Policy Information Point (PIP).</p>
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface Attributes {
static Attributes from(Map<String, Collection<String>> attributes) {
return () -> attributes;
}
/**
* Converts to a {@link Map}.
*
* @return
*/
Map<String, Collection<String>> toMap();
/**
* Checks if there is an attribute with the given <code>name</code>.
*
* @param name the attribute name
* @return true if any attribute with <code>name</code> exist. Otherwise, returns false.
*/
default boolean exists(String name) {
return toMap().containsKey(name);
}
/**
* Checks if there is an attribute with the given <code>name</code> and <code>value</code>.
*
* @param name the attribute name
* @param value the attribute value
* @return true if any attribute with <code>name</code> and <code>value</code> exist. Otherwise, returns false.
*/
default boolean containsValue(String name, String value) {
Collection<String> values = toMap().get(name);
return values != null && values.stream().anyMatch(value::equals);
}
/**
* Returns a {@link Entry} from where values can be obtained and parsed accordingly.
*
* @param name the attribute name
* @return an {@link Entry} holding the values for an attribute
*/
default Entry getValue(String name) {
Collection<String> value = toMap().get(name);
if (value != null) {
return new Entry(name, value);
}
return null;
}
/**
* Holds an attribute and its values, providing useful methods for obtaining and formatting values. Specially useful
* for writing rule-based policies.
*/
class Entry {
private final String[] values;
private final String name;
public Entry(String name, Collection<String> values) {
this.name = name;
this.values = values.toArray(new String[values.size()]);
}
private String getName() {
return this.name;
}
public int size() {
return values.length;
}
public String asString(int idx) {
if (idx >= values.length) {
throw new IllegalArgumentException("Invalid index [" + idx + "]. Values are [" + values + "].");
}
return values[idx];
}
public int asInt(int idx) {
return Integer.parseInt(asString(idx));
}
public Date asDate(int idx, String pattern) {
try {
return new SimpleDateFormat(pattern).parse(asString(idx));
} catch (ParseException e) {
throw new RuntimeException("Error parsing date.", e);
}
}
public InetAddress asInetAddress(int idx) {
try {
return InetAddress.getByName(asString(idx));
} catch (UnknownHostException e) {
throw new RuntimeException("Error parsing address.", e);
}
}
public long asLong(int idx) {
return Long.parseLong(asString(idx));
}
}
}
@@ -1,24 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Provides classes related with the representation of attributes and their manipulation.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
package org.keycloak.authorization.attribute;
@@ -1,97 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.identity;
import org.keycloak.authorization.attribute.Attributes;
/**
* <p>Represents a security identity, which can be a person or non-person entity that was previously authenticated.
*
* <p>An {@link Identity} plays an important role during the evaluation of policies as they represent the entity to which one or more permissions
* should be granted or not, providing additional information and attributes that can be relevant to the different
* access control methods involved during the evaluation of policies.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface Identity {
/**
* Returns the unique identifier of this identity.
*
* @return the unique identifier of this identity
*/
String getId();
/**
* Returns the attributes or claims associated with this identity.
*
* @return the attributes or claims associated with this identity
*/
Attributes getAttributes();
/**
* Indicates if this identity is granted with a role (realm or client) with the given <code>roleName</code>.
*
* @param roleName the name of the role
*
* @return true if the identity has the given role. Otherwise, it returns false.
*/
default boolean hasRole(String roleName) {
return hasRealmRole(roleName) || hasClientRole(roleName);
}
/**
* Indicates if this identity is granted with a realm role with the given <code>roleName</code>.
*
* @param roleName the name of the role
*
* @return true if the identity has the given role. Otherwise, it returns false.
*/
default boolean hasRealmRole(String roleName) {
return getAttributes().containsValue("kc.realm.roles", roleName);
}
/**
* Indicates if this identity is granted with a client role with the given <code>roleName</code>.
*
* @param clientId the client id
* @param roleName the name of the role
*
* @return true if the identity has the given role. Otherwise, it returns false.
*/
default boolean hasClientRole(String clientId, String roleName) {
return getAttributes().containsValue("kc.client." + clientId + ".roles", roleName);
}
/**
* Indicates if this identity is granted with a client role with the given <code>roleName</code>.
*
* @param roleName the name of the role
*
* @return true if the identity has the given role. Otherwise, it returns false.
*/
default boolean hasClientRole(String roleName) {
return getAttributes().toMap().entrySet().stream().filter(entry -> {
String key = entry.getKey();
if (key.startsWith("kc.client") && key.endsWith(".roles")) {
return getAttributes().containsValue(key, roleName);
}
return false;
}).findFirst().isPresent();
}
}
@@ -1,24 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Provides classes related with the representation and management of identities.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
package org.keycloak.authorization.identity;
@@ -1,158 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.model;
import org.keycloak.representations.idm.authorization.DecisionStrategy;
import org.keycloak.representations.idm.authorization.Logic;
import java.util.Map;
import java.util.Set;
/**
* Represents an authorization policy and all the configuration associated with it.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface Policy {
/**
* Returns the unique identifier for this instance.
*
* @return the unique identifier for this instance
*/
String getId();
/**
* Returns the type of this policy.
*
* @return the type of this policy
*/
String getType();
/**
* Returns the {@link DecisionStrategy} for this policy.
*
* @return the decision strategy defined for this policy
*/
DecisionStrategy getDecisionStrategy();
/**
* Sets the {DecisionStrategy} for this policy.
*
* @return the decision strategy for this policy
*/
void setDecisionStrategy(DecisionStrategy decisionStrategy);
/**
* Returns the {@link Logic} for this policy.
*
* @return the decision strategy defined for this policy
*/
Logic getLogic();
/**
* Sets the {Logic} for this policy.
*
* @return the decision strategy for this policy
*/
void setLogic(Logic logic);
/**
* Returns a {@link Map} holding string-based key/value pairs representing any additional configuration for this policy.
*
* @return a map with any additional configuration defined for this policy.
*/
Map<String, String> getConfig();
/**
* Sets a {@link Map} with string-based key/value pairs representing any additional configuration for this policy.
*
* @return a map with any additional configuration for this policy.
*/
void setConfig(Map<String, String> config);
/**
* Returns the name of this policy.
*
* @return the name of this policy
*/
String getName();
/**
* Sets an unique name to this policy.
*
* @param name an unique name
*/
void setName(String name);
/**
* Returns the description of this policy.
*
* @return a description or null of there is no description
*/
String getDescription();
/**
* Sets the description for this policy.
*
* @param description a description
*/
void setDescription(String description);
/**
* Returns the {@link ResourceServer} where this policy belongs to.
*
* @return a resource server
*/
<R extends ResourceServer> R getResourceServer();
/**
* Returns the {@link Policy} instances associated with this policy and used to evaluate authorization decisions when
* this policy applies.
*
* @return the associated policies or an empty set if no policy is associated with this policy
*/
<P extends Policy> Set<P> getAssociatedPolicies();
/**
* Returns the {@link Resource} instances where this policy applies.
*
* @return a set with all resource instances where this policy applies. Or an empty set if there is no resource associated with this policy
*/
<R extends Resource> Set<R> getResources();
/**
* Returns the {@link Scope} instances where this policy applies.
*
* @return a set with all scope instances where this policy applies. Or an empty set if there is no scope associated with this policy
*/
<S extends Scope> Set<S> getScopes();
void addScope(Scope scope);
void removeScope(Scope scope);
void addAssociatedPolicy(Policy associatedPolicy);
void removeAssociatedPolicy(Policy associatedPolicy);
void addResource(Resource resource);
void removeResource(Resource resource);
}
@@ -1,116 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.model;
import java.util.List;
import java.util.Set;
/**
* Represents a resource, which is usually protected by a set of policies within a resource server.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface Resource {
/**
* Returns the unique identifier for this instance.
*
* @return the unique identifier for this instance
*/
String getId();
/**
* Returns the resource's name.
*
* @return the name of this resource
*/
String getName();
/**
* Sets a name for this resource. The name must be unique.
*
* @param name the name of this resource
*/
void setName(String name);
/**
* Returns a {@link java.net.URI} that uniquely identify this resource.
*
* @return an {@link java.net.URI} for this resource or null if not defined.
*/
String getUri();
/**
* Sets a {@link java.net.URI} that uniquely identify this resource.
*
* @param uri an {@link java.net.URI} for this resource
*/
void setUri(String uri);
/**
* Returns a string representing the type of this resource.
*
* @return the type of this resource or null if not defined
*/
String getType();
/**
* Sets a string representing the type of this resource.
*
* @return the type of this resource or null if not defined
*/
void setType(String type);
/**
* Returns a {@link List} containing all the {@link Scope} associated with this resource.
*
* @return a list with all scopes associated with this resource
*/
<S extends Scope> List<S> getScopes();
/**
* Returns an icon {@link java.net.URI} for this resource.
*
* @return a uri for an icon
*/
String getIconUri();
/**
* Sets an icon {@link java.net.URI} for this resource.
*
* @return a uri for an icon
*/
void setIconUri(String iconUri);
/**
* Returns the {@link ResourceServer} to where this resource belongs to.
*
* @return the resource server associated with this resource
*/
<R extends ResourceServer> R getResourceServer();
/**
* Returns the resource's owner, which is usually an identifier that uniquely identifies the resource's owner.
*
* @return the owner of this resource
*/
String getOwner();
void updateScopes(Set<Scope> scopes);
}
@@ -1,73 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.model;
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
/**
* Represents a resource server, whose resources are managed and protected. A resource server is basically an existing
* client application in Keycloak that will also act as a resource server.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface ResourceServer {
/**
* Returns the unique identifier for this instance.
*
* @return the unique identifier for this instance
*/
String getId();
/**
* Returns the identifier of the client application (which already exists in Keycloak) that is also acting as a resource
* server.
*
* @return the identifier of the client application associated with this instance.
*/
String getClientId();
/**
* Indicates if the resource server is allowed to manage its own resources remotely using the Protection API.
*
* {@code true} if the resource server is allowed to managed them remotely
*/
boolean isAllowRemoteResourceManagement();
/**
* Indicates if the resource server is allowed to manage its own resources remotely using the Protection API.
*
* @param allowRemoteResourceManagement {@code true} if the resource server is allowed to managed them remotely
*/
void setAllowRemoteResourceManagement(boolean allowRemoteResourceManagement);
/**
* Returns the {@code PolicyEnforcementMode} configured for this instance.
*
* @return the {@code PolicyEnforcementMode} configured for this instance.
*/
PolicyEnforcementMode getPolicyEnforcementMode();
/**
* Defines a {@code PolicyEnforcementMode} for this instance.
*
* @param enforcementMode one of the available options in {@code PolicyEnforcementMode}
*/
void setPolicyEnforcementMode(PolicyEnforcementMode enforcementMode);
}
@@ -1,70 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.model;
/**
* Represents a scope, which is usually associated with one or more resources in order to define the actions that can be performed
* or a specific access context.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface Scope {
/**
* Returns the unique identifier for this instance.
*
* @return the unique identifier for this instance
*/
String getId();
/**
* Returns the name of this scope.
*
* @return the name of this scope
*/
String getName();
/**
* Sets a name for this scope. The name must be unique.
*
* @param name the name of this scope
*/
void setName(String name);
/**
* Returns an icon {@link java.net.URI} for this scope.
*
* @return a uri for an icon
*/
String getIconUri();
/**
* Sets an icon {@link java.net.URI} for this scope.
*
* @return a uri for an icon
*/
void setIconUri(String iconUri);
/**
* Returns the {@link ResourceServer} instance to where this scope belongs to.
*
* @return
*/
ResourceServer getResourceServer();
}
@@ -1,24 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Provides the domain model and any other type related with it
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
package org.keycloak.authorization.model;
@@ -1,24 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Fine-grained Authorization SPI.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
package org.keycloak.authorization;
@@ -1,71 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.permission;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import java.util.Collections;
import java.util.List;
/**
* Represents a permission for a given resource.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class ResourcePermission {
private final Resource resource;
private final List<Scope> scopes;
private ResourceServer resourceServer;
public ResourcePermission(Resource resource, List<Scope> scopes, ResourceServer resourceServer) {
this.resource = resource;
this.scopes = scopes;
this.resourceServer = resourceServer;
}
/**
* Returns the resource to which this permission applies.
*
* @return the resource to which this permission applies
*/
public Resource getResource() {
return this.resource;
}
/**
* Returns a list of permitted scopes associated with the resource
*
* @return a lit of permitted scopes
*/
public List<Scope> getScopes() {
return Collections.unmodifiableList(this.scopes);
}
/**
* Returns the resource server associated with this permission.
*
* @return the resource server
*/
public ResourceServer getResourceServer() {
return this.resourceServer;
}
}
@@ -1,53 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.permission.evaluator;
import org.keycloak.authorization.permission.ResourcePermission;
import org.keycloak.authorization.policy.evaluation.DefaultPolicyEvaluator;
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import java.util.List;
import java.util.concurrent.Executor;
/**
* A factory for the different {@link PermissionEvaluator} implementations.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public final class Evaluators {
private final List<PolicyProviderFactory> policyProviderFactories;
private final DefaultPolicyEvaluator policyEvaluator;
private final Executor scheduler;
public Evaluators(List<PolicyProviderFactory> policyProviderFactories, DefaultPolicyEvaluator policyEvaluator, Executor scheduler) {
this.policyProviderFactories = policyProviderFactories;
this.policyEvaluator = policyEvaluator;
this.scheduler = scheduler;
}
public PermissionEvaluator from(List<ResourcePermission> permissions, EvaluationContext evaluationContext) {
return schedule(permissions, evaluationContext);
}
public PermissionEvaluator schedule(List<ResourcePermission> permissions, EvaluationContext evaluationContext) {
return new ScheduledPermissionEvaluator(new IterablePermissionEvaluator(permissions.iterator(), evaluationContext, this.policyEvaluator), this.scheduler);
}
}
@@ -1,53 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.permission.evaluator;
import org.keycloak.authorization.Decision;
import org.keycloak.authorization.permission.ResourcePermission;
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
import org.keycloak.authorization.policy.evaluation.PolicyEvaluator;
import java.util.Iterator;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
class IterablePermissionEvaluator implements PermissionEvaluator {
private final Iterator<ResourcePermission> permissions;
private final EvaluationContext executionContext;
private final PolicyEvaluator policyEvaluator;
IterablePermissionEvaluator(Iterator<ResourcePermission> permissions, EvaluationContext executionContext, PolicyEvaluator policyEvaluator) {
this.permissions = permissions;
this.executionContext = executionContext;
this.policyEvaluator = policyEvaluator;
}
@Override
public void evaluate(Decision decision) {
try {
while (this.permissions.hasNext()) {
this.policyEvaluator.evaluate(this.permissions.next(), this.executionContext, decision);
}
decision.onComplete();
} catch (Throwable cause) {
decision.onError(cause);
}
}
}
@@ -1,31 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.permission.evaluator;
import org.keycloak.authorization.Decision;
/**
* An {@link PermissionEvaluator} represents a source of {@link org.keycloak.authorization.permission.ResourcePermission}, responsible for emitting these permissions
* to a consumer in order to evaluate the authorization policies based on a {@link org.keycloak.authorization.policy.evaluation.EvaluationContext}.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface PermissionEvaluator {
void evaluate(Decision decision);
}
@@ -1,43 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.permission.evaluator;
import org.keycloak.authorization.Decision;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
* @see PermissionEvaluator
*/
class ScheduledPermissionEvaluator implements PermissionEvaluator {
private final PermissionEvaluator publisher;
private final Executor scheduler;
ScheduledPermissionEvaluator(PermissionEvaluator publisher, Executor scheduler) {
this.publisher = publisher;
this.scheduler = scheduler;
}
@Override
public void evaluate(Decision decision) {
CompletableFuture.runAsync(() -> publisher.evaluate(decision), scheduler);
}
}
@@ -1,103 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.evaluation;
import org.keycloak.authorization.Decision;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.permission.ResourcePermission;
import org.keycloak.representations.idm.authorization.DecisionStrategy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public abstract class DecisionResultCollector implements Decision<DefaultEvaluation> {
private Map<ResourcePermission, Result> results = new HashMap();
@Override
public void onDecision(DefaultEvaluation evaluation) {
if (evaluation.getParentPolicy() != null) {
results.computeIfAbsent(evaluation.getPermission(), Result::new).policy(evaluation.getParentPolicy()).policy(evaluation.getPolicy()).setStatus(evaluation.getEffect());
} else {
results.computeIfAbsent(evaluation.getPermission(), Result::new).setStatus(evaluation.getEffect());
}
}
@Override
public void onComplete() {
for (Result result : results.values()) {
for (Result.PolicyResult policyResult : result.getResults()) {
if (isGranted(policyResult)) {
policyResult.setStatus(Effect.PERMIT);
} else {
policyResult.setStatus(Effect.DENY);
}
}
if (result.getResults().stream()
.filter(policyResult -> Effect.DENY.equals(policyResult.getStatus())).count() > 0) {
result.setStatus(Effect.DENY);
} else {
result.setStatus(Effect.PERMIT);
}
}
onComplete(results.values().stream().collect(Collectors.toList()));
}
protected abstract void onComplete(List<Result> results);
private boolean isGranted(Result.PolicyResult policyResult) {
List<Result.PolicyResult> values = policyResult.getAssociatedPolicies();
int grantCount = 0;
int denyCount = policyResult.getPolicy().getAssociatedPolicies().size();
for (Result.PolicyResult decision : values) {
if (decision.getStatus().equals(Effect.PERMIT)) {
grantCount++;
denyCount--;
}
}
Policy policy = policyResult.getPolicy();
DecisionStrategy decisionStrategy = policy.getDecisionStrategy();
if (decisionStrategy == null) {
decisionStrategy = DecisionStrategy.UNANIMOUS;
}
if (DecisionStrategy.AFFIRMATIVE.equals(decisionStrategy) && grantCount > 0) {
return true;
} else if (DecisionStrategy.UNANIMOUS.equals(decisionStrategy) && denyCount == 0) {
return true;
} else if (DecisionStrategy.CONSENSUS.equals(decisionStrategy)) {
if (grantCount > denyCount) {
return true;
}
}
return false;
}
}
@@ -1,105 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.evaluation;
import org.keycloak.authorization.Decision;
import org.keycloak.authorization.Decision.Effect;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.permission.ResourcePermission;
import org.keycloak.representations.idm.authorization.Logic;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class DefaultEvaluation implements Evaluation {
private final ResourcePermission permission;
private final EvaluationContext executionContext;
private final Decision decision;
private final Policy policy;
private final Policy parentPolicy;
private Effect effect;
public DefaultEvaluation(ResourcePermission permission, EvaluationContext executionContext, Policy parentPolicy, Policy policy, Decision decision) {
this.permission = permission;
this.executionContext = executionContext;
this.parentPolicy = parentPolicy;
this.policy = policy;
this.decision = decision;
}
/**
* Returns the {@link ResourcePermission} to be evaluated.
*
* @return the permission to be evaluated
*/
public ResourcePermission getPermission() {
return this.permission;
}
/**
* Returns the {@link org.keycloak.authorization.permission.evaluator.PermissionEvaluator}. Which provides access to the whole evaluation runtime context.
*
* @return the evaluation context
*/
public EvaluationContext getContext() {
return this.executionContext;
}
/**
* Grants all the requested permissions to the caller.
*/
public void grant() {
if (policy != null && Logic.NEGATIVE.equals(policy.getLogic())) {
this.effect = Effect.DENY;
} else {
this.effect = Effect.PERMIT;
}
this.decision.onDecision(this);
}
public void deny() {
if (policy != null && Logic.NEGATIVE.equals(policy.getLogic())) {
this.effect = Effect.PERMIT;
} else {
this.effect = Effect.DENY;
}
this.decision.onDecision(this);
}
public Policy getPolicy() {
return this.policy;
}
public Policy getParentPolicy() {
return this.parentPolicy;
}
public Effect getEffect() {
return effect;
}
void denyIfNoEffect() {
if (this.effect == null) {
deny();
}
}
}
@@ -1,189 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.evaluation;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.Decision;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import org.keycloak.authorization.permission.ResourcePermission;
import org.keycloak.authorization.policy.provider.PolicyProvider;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.authorization.store.PolicyStore;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class DefaultPolicyEvaluator implements PolicyEvaluator {
private final AuthorizationProvider authorization;
private Map<String, PolicyProviderFactory> policyProviders = new HashMap<>();
public DefaultPolicyEvaluator(AuthorizationProvider authorization, List<PolicyProviderFactory> policyProviderFactories) {
this.authorization = authorization;
for (PolicyProviderFactory providerFactory : policyProviderFactories) {
this.policyProviders.put(providerFactory.getId(), providerFactory);
}
}
@Override
public void evaluate(ResourcePermission permission, EvaluationContext executionContext, Decision decision) {
ResourceServer resourceServer = permission.getResourceServer();
if (PolicyEnforcementMode.DISABLED.equals(resourceServer.getPolicyEnforcementMode())) {
createEvaluation(permission, executionContext, decision, null, null).grant();
return;
}
StoreFactory storeFactory = this.authorization.getStoreFactory();
PolicyStore policyStore = storeFactory.getPolicyStore();
AtomicInteger policiesCount = new AtomicInteger(0);
Consumer<Policy> consumer = createDecisionConsumer(permission, executionContext, decision, policiesCount);
Resource resource = permission.getResource();
if (resource != null) {
List<? extends Policy> resourcePolicies = policyStore.findByResource(resource.getId());
if (!resourcePolicies.isEmpty()) {
resourcePolicies.forEach(consumer);
}
if (resource.getType() != null) {
policyStore.findByResourceType(resource.getType(), resourceServer.getId()).forEach(consumer);
}
if (permission.getScopes().isEmpty() && !resource.getScopes().isEmpty()) {
policyStore.findByScopeIds(resource.getScopes().stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId()).forEach(consumer);
}
}
if (!permission.getScopes().isEmpty()) {
policyStore.findByScopeIds(permission.getScopes().stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId()).forEach(consumer);
}
if (PolicyEnforcementMode.PERMISSIVE.equals(resourceServer.getPolicyEnforcementMode()) && policiesCount.get() == 0) {
createEvaluation(permission, executionContext, decision, null, null).grant();
}
}
private Consumer<Policy> createDecisionConsumer(ResourcePermission permission, EvaluationContext executionContext, Decision decision, AtomicInteger policiesCount) {
return (parentPolicy) -> {
if (hasRequestedScopes(permission, parentPolicy)) {
for (Policy associatedPolicy : parentPolicy.getAssociatedPolicies()) {
PolicyProviderFactory providerFactory = policyProviders.get(associatedPolicy.getType());
if (providerFactory == null) {
throw new RuntimeException("Could not find a policy provider for policy type [" + associatedPolicy.getType() + "].");
}
PolicyProvider policyProvider = providerFactory.create(associatedPolicy, this.authorization);
if (policyProvider == null) {
throw new RuntimeException("Unknown parentPolicy provider for type [" + associatedPolicy.getType() + "].");
}
DefaultEvaluation evaluation = createEvaluation(permission, executionContext, decision, parentPolicy, associatedPolicy);
policyProvider.evaluate(evaluation);
evaluation.denyIfNoEffect();
policiesCount.incrementAndGet();
}
}
};
}
private DefaultEvaluation createEvaluation(ResourcePermission permission, EvaluationContext executionContext, Decision decision, Policy parentPolicy, Policy associatedPolicy) {
return new DefaultEvaluation(permission, executionContext, parentPolicy, associatedPolicy, decision);
}
private boolean hasRequestedScopes(final ResourcePermission permission, final Policy policy) {
if (permission.getScopes().isEmpty()) {
return true;
}
Resource resourcePermission = permission.getResource();
Set<Resource> policyResources = policy.getResources();
if (resourcePermission != null && !policyResources.isEmpty()) {
if (!policyResources.stream().filter(resource -> resource.getId().equals(resourcePermission.getId())).findFirst().isPresent()) {
return false;
}
}
Set<Scope> scopes = new HashSet<>(policy.getScopes());
if (scopes.isEmpty()) {
Set<Resource> resources = new HashSet<>();
resources.addAll(policyResources);
for (Resource resource : resources) {
scopes.addAll(resource.getScopes());
}
if (!resources.isEmpty() && scopes.isEmpty()) {
return false;
}
if (scopes.isEmpty()) {
Resource resource = permission.getResource();
String type = resource.getType();
if (type != null) {
List<Resource> resourcesByType = authorization.getStoreFactory().getResourceStore().findByType(type);
for (Resource resourceType : resourcesByType) {
if (resourceType.getOwner().equals(resource.getResourceServer().getClientId())) {
resources.add(resourceType);
}
}
}
}
for (Resource resource : resources) {
scopes.addAll(resource.getScopes());
}
}
for (Scope givenScope : scopes) {
for (Scope scope : permission.getScopes()) {
if (givenScope.getId().equals(scope.getId())) {
return true;
}
}
}
return false;
}
}
@@ -1,54 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.evaluation;
import org.keycloak.authorization.permission.ResourcePermission;
/**
* <p>An {@link Evaluation} is mainly used by {@link org.keycloak.authorization.policy.provider.PolicyProvider} in order to evaluate a single
* and specific {@link ResourcePermission} against the configured policies.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface Evaluation {
/**
* Returns the {@link ResourcePermission} to be evaluated.
*
* @return the permission to be evaluated
*/
ResourcePermission getPermission();
/**
* Returns the {@link EvaluationContext}. Which provides access to the whole evaluation runtime context.
*
* @return the evaluation context
*/
EvaluationContext getContext();
/**
* Grants the requested permission to the caller.
*/
void grant();
/**
* Denies the requested permission.
*/
void deny();
}
@@ -1,45 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.evaluation;
import org.keycloak.authorization.attribute.Attributes;
import org.keycloak.authorization.identity.Identity;
/**
* This interface serves as a bridge between the policy evaluation runtime and the environment in which it is running. When evaluating
* policies, this interface can be used to query information from the execution environment/context and enrich decisions.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface EvaluationContext {
/**
* Returns the {@link Identity} that represents an entity (person or non-person) to which the permissions must be granted, or not.
*
* @return the identity to which the permissions must be granted, or not
*/
Identity getIdentity();
/**
* Returns all attributes within the current execution and runtime environment.
*
* @return the attributes within the current execution and runtime environment
*/
Attributes getAttributes();
}
@@ -1,38 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.evaluation;
import org.keycloak.authorization.Decision;
import org.keycloak.authorization.permission.ResourcePermission;
/**
* <p>A {@link PolicyEvaluator} evaluates authorization policies based on a given {@link ResourcePermission}, sending
* the results to a {@link Decision} point through the methods defined in that interface.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface PolicyEvaluator {
/**
* Starts the evaluation of the configured authorization policies.
*
* @param decision a {@link Decision} point to where notifications events will be delivered during the evaluation
*/
void evaluate(ResourcePermission permission, EvaluationContext executionContext, Decision decision);
}
@@ -1,120 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.evaluation;
import org.keycloak.authorization.Decision.Effect;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.permission.ResourcePermission;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class Result {
private final ResourcePermission permission;
private List<PolicyResult> results = new ArrayList<>();
private Effect status;
public Result(ResourcePermission permission) {
this.permission = permission;
}
public ResourcePermission getPermission() {
return permission;
}
public List<PolicyResult> getResults() {
return results;
}
public PolicyResult policy(Policy policy) {
for (PolicyResult result : this.results) {
if (result.getPolicy().equals(policy)) {
return result;
}
}
PolicyResult policyResult = new PolicyResult(policy);
this.results.add(policyResult);
return policyResult;
}
public void setStatus(final Effect status) {
this.status = status;
}
public Effect getEffect() {
return status;
}
public static class PolicyResult {
private final Policy policy;
private List<PolicyResult> associatedPolicies = new ArrayList<>();
private Effect status;
public PolicyResult(Policy policy) {
this.policy = policy;
}
public PolicyResult status(Effect status) {
this.status = status;
return this;
}
public PolicyResult policy(Policy policy) {
return getPolicy(policy, this.associatedPolicies);
}
private PolicyResult getPolicy(Policy policy, List<PolicyResult> results) {
for (PolicyResult result : results) {
if (result.getPolicy().equals(policy)) {
return result;
}
}
PolicyResult policyResult = new PolicyResult(policy);
results.add(policyResult);
return policyResult;
}
public Policy getPolicy() {
return policy;
}
public List<PolicyResult> getAssociatedPolicies() {
return associatedPolicies;
}
public Effect getStatus() {
return status;
}
public void setStatus(final Effect status) {
this.status = status;
}
}
}
@@ -1,24 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Provides classes related with the evaluation of policies.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
package org.keycloak.authorization.policy.evaluation;
@@ -1,29 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.provider;
import org.keycloak.authorization.policy.evaluation.Evaluation;
import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface PolicyProvider extends Provider {
void evaluate(Evaluation evaluation);
}
@@ -1,33 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.provider;
import org.keycloak.authorization.model.Policy;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface PolicyProviderAdminService {
void onCreate(Policy policy);
void onUpdate(Policy policy);
void onRemove(Policy policy);
}
@@ -1,38 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.provider;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface PolicyProviderFactory extends ProviderFactory<PolicyProvider> {
String getName();
String getGroup();
PolicyProvider create(Policy policy, AuthorizationProvider authorization);
PolicyProviderAdminService getAdminResource(ResourceServer resourceServer);
}
@@ -1,48 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.policy.provider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class PolicySpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "policy";
}
@Override
public Class<? extends Provider> getProviderClass() {
return PolicyProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return PolicyProviderFactory.class;
}
}
@@ -1,24 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Provides classes and a SPI to plug different policy providers.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
package org.keycloak.authorization.policy.provider;
@@ -1,64 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store;
import org.keycloak.authorization.store.syncronization.ClientApplicationSynchronizer;
import org.keycloak.authorization.store.syncronization.RealmSynchronizer;
import org.keycloak.authorization.store.syncronization.Synchronizer;
import org.keycloak.authorization.store.syncronization.UserSynchronizer;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel.ClientRemovedEvent;
import org.keycloak.models.RealmModel.RealmRemovedEvent;
import org.keycloak.models.UserModel.UserRemovedEvent;
import org.keycloak.provider.ProviderEvent;
import org.keycloak.provider.ProviderFactory;
import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface AuthorizationStoreFactory extends ProviderFactory<StoreFactory> {
@Override
default void postInit(KeycloakSessionFactory factory) {
registerSynchronizationListeners(factory);
}
default void registerSynchronizationListeners(KeycloakSessionFactory factory) {
Map<Class<? extends ProviderEvent>, Synchronizer> synchronizers = new HashMap<>();
synchronizers.put(ClientRemovedEvent.class, new ClientApplicationSynchronizer());
synchronizers.put(RealmRemovedEvent.class, new RealmSynchronizer());
synchronizers.put(UserRemovedEvent.class, new UserSynchronizer());
factory.register(event -> {
try {
synchronizers.forEach((eventType, synchronizer) -> {
if (eventType.isInstance(event)) {
synchronizer.synchronize(event, factory);
}
});
} catch (Exception e) {
throw new RuntimeException("Error synchronizing authorization data.", e);
}
});
}
}
@@ -1,127 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer;
import java.util.List;
import java.util.Map;
/**
* A {@link PolicyStore} is responsible to manage the persistence of {@link Policy} instances.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface PolicyStore {
/**
* Creates a new {@link Policy} instance. The new instance is not necessarily persisted though, which may require
* a call to the {#save} method to actually make it persistent.
*
* @param name the name of the policy
* @param type the type of the policy
* @param resourceServer the resource server to which this policy belongs
* @return a new instance of {@link Policy}
*/
Policy create(String name, String type, ResourceServer resourceServer);
/**
* Deletes a policy from the underlying persistence mechanism.
*
* @param id the id of the policy to delete
*/
void delete(String id);
/**
* Returns a {@link Policy} with the given <code>id</code>
*
* @param id the identifier of the policy
* @return a policy with the given identifier.
*/
Policy findById(String id);
/**
* Returns a {@link Policy} with the given <code>name</code>
*
* @param name the name of the policy
* @param resourceServerId the resource server id
* @return a policy with the given name.
*/
Policy findByName(String name, String resourceServerId);
/**
* Returns a list of {@link Policy} associated with a {@link ResourceServer} with the given <code>resourceServerId</code>.
*
* @param resourceServerId the identifier of a resource server
* @return a list of policies that belong to the given resource server
*/
List<Policy> findByResourceServer(String resourceServerId);
/**
* Returns a list of {@link Policy} associated with a {@link ResourceServer} with the given <code>resourceServerId</code>.
*
* @param attributes a map holding the attributes that will be used as a filter
* @param resourceServerId the identifier of a resource server
* @return a list of policies that belong to the given resource server
*/
List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult);
/**
* Returns a list of {@link Policy} associated with a {@link org.keycloak.authorization.core.model.Resource} with the given <code>resourceId</code>.
*
* @param resourceId the identifier of a resource
* @return a list of policies associated with the given resource
*/
List<Policy> findByResource(String resourceId);
/**
* Returns a list of {@link Policy} associated with a {@link org.keycloak.authorization.core.model.Resource} with the given <code>type</code>.
*
* @param resourceType the type of a resource
* @param resourceServerId the resource server id
* @return a list of policies associated with the given resource type
*/
List<Policy> findByResourceType(String resourceType, String resourceServerId);
/**
* Returns a list of {@link Policy} associated with a {@link org.keycloak.authorization.core.model.Scope} with the given <code>scopeIds</code>.
*
* @param scopeIds the id of the scopes
* @param resourceServerId the resource server id
* @return a list of policies associated with the given scopes
*/
List<Policy> findByScopeIds(List<String> scopeIds, String resourceServerId);
/**
* Returns a list of {@link Policy} with the given <code>type</code>.
*
* @param type the type of the policy
* @return a list of policies with the given type
*/
List<Policy> findByType(String type);
/**
* Returns a list of {@link Policy} that depends on another policy with the given <code>id</code>.
*
* @param id the id of the policy to query its dependents
* @return a list of policies that depends on the a policy with the given identifier
*/
List<Policy> findDependentPolicies(String id);
}
@@ -1,63 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store;
import org.keycloak.authorization.model.ResourceServer;
/**
* A {@link ResourceServerStore} is responsible to manage the persistence of {@link ResourceServer} instances.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface ResourceServerStore {
/**
* <p>Creates a {@link ResourceServer} instance backed by this persistent storage implementation.
*
* @param clientId the client id acting as a resource server
*
* @return an instance backed by the underlying storage implementation
*/
ResourceServer create(String clientId);
/**
* Removes a {@link ResourceServer} instance, with the given {@code id} from the persistent storage.
*
* @param id the identifier of an existing resource server instance
*/
void delete(String id);
/**
* Returns a {@link ResourceServer} instance based on its identifier.
*
* @param id the identifier of an existing resource server instance
*
* @return the resource server instance with the given identifier or null if no instance was found
*/
ResourceServer findById(String id);
/**
* Returns a {@link ResourceServer} instance based on the identifier of a client application.
*
* @param id the identifier of an existing client application
*
* @return the resource server instance, with the given client id or null if no instance was found
*/
ResourceServer findByClient(String id);
}
@@ -1,107 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import java.util.List;
import java.util.Map;
/**
* A {@link ResourceStore} is responsible to manage the persistence of {@link Resource} instances.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface ResourceStore {
/**
* <p>Creates a {@link Resource} instance backed by this persistent storage implementation.
*
* @param name the name of this resource. It must be unique.
* @param resourceServer the resource server to where the given resource belongs to
* @param owner the owner of this resource or null if the resource server is the owner
* @return an instance backed by the underlying storage implementation
*/
Resource create(String name, ResourceServer resourceServer, String owner);
/**
* Removes a {@link Resource} instance, with the given {@code id} from the persistent storage.
*
* @param id the identifier of an existing resource instance
*/
void delete(String id);
/**
* Returns a {@link Resource} instance based on its identifier.
*
* @param id the identifier of an existing resource instance
* @return the resource instance with the given identifier or null if no instance was found
*/
Resource findById(String id);
/**
* Finds all {@link Resource} instances with the given {@code ownerId}.
*
* @param ownerId the identifier of the owner
* @return a list with all resource instances owned by the given owner
*/
List<Resource> findByOwner(String ownerId);
/**
* Finds all {@link Resource} instances associated with a given resource server.
*
* @param resourceServerId the identifier of the resource server
* @return a list with all resources associated with the given resource server
*/
List<Resource> findByResourceServer(String resourceServerId);
/**
* Finds all {@link Resource} instances associated with a given resource server.
*
* @param attributes a map holding the attributes that will be used as a filter
* @param resourceServerId the identifier of the resource server
* @return a list with all resources associated with the given resource server
*/
List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult);
/**
* Finds all {@link Resource} associated with a given scope.
*
* @param id one or more scope identifiers
* @return a list of resources associated with the given scope(s)
*/
List<Resource> findByScope(String... id);
/**
* Find a {@link Resource} by its name.
*
* @param name the name of the resource
* @param resourceServerId the identifier of the resource server
* @return a resource with the given name
*/
Resource findByName(String name, String resourceServerId);
/**
* Finds all {@link Resource} with the given type.
*
* @param type the type of the resource
* @return a list of resources with the given type
*/
List<Resource> findByType(String type);
}
@@ -1,89 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import java.util.List;
import java.util.Map;
/**
* A {@link ScopeStore} is responsible to manage the persistence of {@link Scope} instances.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface ScopeStore {
/**
* Creates a new {@link Scope} instance. The new instance is not necessarily persisted though, which may require
* a call to the {#save} method to actually make it persistent.
*
* @param name the name of the scope
* @param resourceServer the resource server to which this scope belongs
*
* @return a new instance of {@link Scope}
*/
Scope create(String name, ResourceServer resourceServer);
/**
* Deletes a scope from the underlying persistence mechanism.
*
* @param id the id of the scope to delete
*/
void delete(String id);
/**
* Returns a {@link Scope} with the given <code>id</code>
*
* @param id the identifier of the scope
*
* @return a scope with the given identifier.
*/
Scope findById(String id);
/**
* Returns a {@link Scope} with the given <code>name</code>
*
* @param name the name of the scope
*
* @param resourceServerId
* @return a scope with the given name.
*/
Scope findByName(String name, String resourceServerId);
/**
* Returns a list of {@link Scope} associated with a {@link ResourceServer} with the given <code>resourceServerId</code>.
*
* @param resourceServerId the identifier of a resource server
*
* @return a list of scopes that belong to the given resource server
*/
List<Scope> findByResourceServer(String id);
/**
* Returns a list of {@link Scope} associated with a {@link ResourceServer} with the given <code>resourceServerId</code>.
*
* @param attributes a map holding the attributes that will be used as a filter
* @param resourceServerId the identifier of a resource server
*
* @return a list of scopes that belong to the given resource server
*/
List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult);
}
@@ -1,61 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store;
import org.keycloak.provider.Provider;
/**
* <p>A factory for the different types of storages that manage the persistence of the domain model types.
*
* <p>Implementations of this interface are usually related with the creation of those storage types accordingly with a
* specific persistence mechanism such as relational and NoSQL databases, filesystem, etc.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface StoreFactory extends Provider {
/**
* Returns a {@link ResourceStore}.
*
* @return the resource store
*/
ResourceStore getResourceStore();
/**
* Returns a {@link ResourceServerStore}.
*
* @return the resource server store
*/
ResourceServerStore getResourceServerStore();
/**
* Returns a {@link ScopeStore}.
*
* @return the scope store
*/
ScopeStore getScopeStore();
/**
* Returns a {@link PolicyStore}.
*
* @return the policy store
*/
PolicyStore getPolicyStore();
}
@@ -1,48 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class StoreFactorySpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "authorizationPersister";
}
@Override
public Class<? extends Provider> getProviderClass() {
return StoreFactory.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return AuthorizationStoreFactory.class;
}
}
@@ -1,24 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Provides classes and a SPI to plug different metadata storage implementations.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
package org.keycloak.authorization.store;
@@ -1,50 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store.syncronization;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.store.ResourceServerStore;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel.ClientRemovedEvent;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class ClientApplicationSynchronizer implements Synchronizer<ClientRemovedEvent> {
@Override
public void synchronize(ClientRemovedEvent event, KeycloakSessionFactory factory) {
ProviderFactory<AuthorizationProvider> providerFactory = factory.getProviderFactory(AuthorizationProvider.class);
AuthorizationProvider authorizationProvider = providerFactory.create(event.getKeycloakSession());
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
ResourceServerStore store = storeFactory.getResourceServerStore();
ResourceServer resourceServer = store.findByClient(event.getClient().getId());
if (resourceServer != null) {
String id = resourceServer.getId();
storeFactory.getResourceStore().findByResourceServer(id).forEach(resource -> storeFactory.getResourceStore().delete(resource.getId()));
storeFactory.getScopeStore().findByResourceServer(id).forEach(scope -> storeFactory.getScopeStore().delete(scope.getId()));
storeFactory.getPolicyStore().findByResourceServer(id).forEach(scope -> storeFactory.getPolicyStore().delete(scope.getId()));
storeFactory.getResourceServerStore().delete(id);
}
}
}
@@ -1,50 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store.syncronization;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel.RealmRemovedEvent;
import org.keycloak.provider.ProviderFactory;
/*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class RealmSynchronizer implements Synchronizer<RealmRemovedEvent> {
@Override
public void synchronize(RealmRemovedEvent event, KeycloakSessionFactory factory) {
ProviderFactory<AuthorizationProvider> providerFactory = factory.getProviderFactory(AuthorizationProvider.class);
AuthorizationProvider authorizationProvider = providerFactory.create(event.getKeycloakSession());
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
event.getRealm().getClients().forEach(clientModel -> {
ResourceServer resourceServer = storeFactory.getResourceServerStore().findByClient(clientModel.getClientId());
if (resourceServer != null) {
String id = resourceServer.getId();
storeFactory.getResourceStore().findByResourceServer(id).forEach(resource -> storeFactory.getResourceStore().delete(resource.getId()));
storeFactory.getScopeStore().findByResourceServer(id).forEach(scope -> storeFactory.getScopeStore().delete(scope.getId()));
storeFactory.getPolicyStore().findByResourceServer(id).forEach(scope -> storeFactory.getPolicyStore().delete(scope.getId()));
storeFactory.getResourceServerStore().delete(id);
}
});
}
}
@@ -1,31 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store.syncronization;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.ProviderEvent;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface Synchronizer<E extends ProviderEvent> {
void synchronize(E event, KeycloakSessionFactory factory);
}
@@ -1,55 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authorization.store.syncronization;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.store.PolicyStore;
import org.keycloak.authorization.store.ResourceStore;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserModel.UserRemovedEvent;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class UserSynchronizer implements Synchronizer<UserRemovedEvent> {
@Override
public void synchronize(UserRemovedEvent event, KeycloakSessionFactory factory) {
ProviderFactory<AuthorizationProvider> providerFactory = factory.getProviderFactory(AuthorizationProvider.class);
AuthorizationProvider authorizationProvider = providerFactory.create(event.getKeycloakSession());
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
UserModel userModel = event.getUser();
ResourceStore resourceStore = storeFactory.getResourceStore();
PolicyStore policyStore = storeFactory.getPolicyStore();
resourceStore.findByOwner(userModel.getId()).forEach(resource -> {
String resourceId = resource.getId();
policyStore.findByResource(resourceId).forEach(policy -> {
if (policy.getResources().size() == 1) {
policyStore.delete(policy.getId());
} else {
policy.removeResource(resource);
}
});
resourceStore.delete(resourceId);
});
}
}
@@ -1,101 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
/**
* @author Pedro Igor
*/
public abstract class AbstractIdentityProvider<C extends IdentityProviderModel> implements IdentityProvider<C> {
protected final KeycloakSession session;
private final C config;
public AbstractIdentityProvider(KeycloakSession session, C config) {
this.session = session;
this.config = config;
}
public C getConfig() {
return this.config;
}
@Override
public Response export(UriInfo uriInfo, RealmModel realm, String format) {
return Response.noContent().build();
}
@Override
public void close() {
// no-op
}
@Override
public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
return null;
}
@Override
public Response performLogin(AuthenticationRequest request) {
return null;
}
@Override
public Response keycloakInitiatedBrowserLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
return null;
}
@Override
public void backchannelLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
}
@Override
public void attachUserSession(UserSessionModel userSession, ClientSessionModel clientSession, BrokeredIdentityContext context) {
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, BrokeredIdentityContext context) {
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context) {
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context) {
}
@Override
public IdentityProviderDataMarshaller getMarshaller() {
return new DefaultDataMarshaller();
}
}
@@ -1,56 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* @author Pedro Igor
*/
public abstract class AbstractIdentityProviderFactory<T extends IdentityProvider> implements IdentityProviderFactory<T> {
@Override
public void close() {
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public T create(KeycloakSession session) {
return null;
}
@Override
public Map<String, String> parseConfig(KeycloakSession session, InputStream inputStream) {
return new HashMap<String, String>();
}
}
@@ -1,60 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class AbstractIdentityProviderMapper implements IdentityProviderMapper {
@Override
public void close() {
}
@Override
public IdentityProviderMapper create(KeycloakSession session) {
return null;
}
@Override
public void init(org.keycloak.Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
}
@@ -1,82 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import javax.ws.rs.core.UriInfo;
/**
* @author Pedro Igor
*/
public class AuthenticationRequest {
private final KeycloakSession session;
private final UriInfo uriInfo;
private final String state;
private final HttpRequest httpRequest;
private final RealmModel realm;
private final String redirectUri;
private final ClientSessionModel clientSession;
public AuthenticationRequest(KeycloakSession session, RealmModel realm, ClientSessionModel clientSession, HttpRequest httpRequest, UriInfo uriInfo, String state, String redirectUri) {
this.session = session;
this.realm = realm;
this.httpRequest = httpRequest;
this.uriInfo = uriInfo;
this.state = state;
this.redirectUri = redirectUri;
this.clientSession = clientSession;
}
public KeycloakSession getSession() {
return session;
}
public UriInfo getUriInfo() {
return this.uriInfo;
}
public String getState() {
return this.state;
}
public HttpRequest getHttpRequest() {
return this.httpRequest;
}
public RealmModel getRealm() {
return this.realm;
}
/**
* <p>Returns the redirect url that must be included in an authentication request in order to process responses from an
* identity provider.</p>
*
* @return
*/
public String getRedirectUri() {
return this.redirectUri;
}
public ClientSessionModel getClientSession() {
return this.clientSession;
}
}
@@ -1,218 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
import org.keycloak.models.IdentityProviderModel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>Represents all identity information obtained from an {@link org.keycloak.broker.provider.IdentityProvider} after a
* successful authentication.</p>
*
* @author Pedro Igor
*/
public class BrokeredIdentityContext {
private String id;
private String username;
private String modelUsername;
private String email;
private String firstName;
private String lastName;
private String brokerSessionId;
private String brokerUserId;
private String code;
private String token;
private IdentityProviderModel idpConfig;
private IdentityProvider idp;
private Map<String, Object> contextData = new HashMap<>();
private ClientSessionModel clientSession;
public BrokeredIdentityContext(String id) {
if (id == null) {
throw new RuntimeException("No identifier provider for identity.");
}
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/**
* Username in remote idp
*
* @return
*/
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
/**
* username to store in UserModel
*
* @return
*/
public String getModelUsername() {
return modelUsername;
}
public void setModelUsername(String modelUsername) {
this.modelUsername = modelUsername;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBrokerSessionId() {
return brokerSessionId;
}
public void setBrokerSessionId(String brokerSessionId) {
this.brokerSessionId = brokerSessionId;
}
public String getBrokerUserId() {
return brokerUserId;
}
public void setBrokerUserId(String brokerUserId) {
this.brokerUserId = brokerUserId;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public IdentityProviderModel getIdpConfig() {
return idpConfig;
}
public void setIdpConfig(IdentityProviderModel idpConfig) {
this.idpConfig = idpConfig;
}
public IdentityProvider getIdp() {
return idp;
}
public void setIdp(IdentityProvider idp) {
this.idp = idp;
}
public Map<String, Object> getContextData() {
return contextData;
}
public void setContextData(Map<String, Object> contextData) {
this.contextData = contextData;
}
// Set the attribute, which will be available on "Update profile" page and in authenticators
public void setUserAttribute(String attributeName, String attributeValue) {
List<String> list = new ArrayList<>();
list.add(attributeValue);
getContextData().put(Constants.USER_ATTRIBUTES_PREFIX + attributeName, list);
}
public String getUserAttribute(String attributeName) {
List<String> userAttribute = (List<String>) getContextData().get(Constants.USER_ATTRIBUTES_PREFIX + attributeName);
if (userAttribute == null || userAttribute.isEmpty()) {
return null;
} else {
return userAttribute.get(0);
}
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public ClientSessionModel getClientSession() {
return clientSession;
}
public void setClientSession(ClientSessionModel clientSession) {
this.clientSession = clientSession;
}
public void setName(String name) {
if (name != null) {
int i = name.lastIndexOf(' ');
if (i != -1) {
firstName = name.substring(0, i);
lastName = name.substring(i + 1);
} else {
firstName = name;
}
}
}
@Override
public String toString() {
return "{" +
"id='" + id + '\'' +
", username='" + username + '\'' +
", email='" + email + '\'' +
'}';
}
}
@@ -1,26 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ConfigConstants {
String ROLE = "role";
}
@@ -1,63 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.common.util.Base64Url;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DefaultDataMarshaller implements IdentityProviderDataMarshaller {
@Override
public String serialize(Object value) {
if (value instanceof String) {
return (String) value;
} else {
try {
byte[] bytes = JsonSerialization.writeValueAsBytes(value);
return Base64Url.encode(bytes);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
@Override
public <T> T deserialize(String serialized, Class<T> clazz) {
try {
if (clazz.equals(String.class)) {
return clazz.cast(serialized);
} else {
byte[] bytes = Base64Url.decode(serialized);
if (List.class.isAssignableFrom(clazz)) {
List list = JsonSerialization.readValue(bytes, List.class);
return clazz.cast(list);
} else {
return JsonSerialization.readValue(bytes, clazz);
}
}
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
@@ -1,31 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
/**
* @author pedroigor
*/
public class IdentityBrokerException extends RuntimeException {
public IdentityBrokerException(String message) {
super(message);
}
public IdentityBrokerException(String message, Throwable t) {
super(message, t);
}
}
@@ -1,110 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.provider.Provider;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
/**
* @author Pedro Igor
*/
public interface IdentityProvider<C extends IdentityProviderModel> extends Provider {
interface AuthenticationCallback {
/**
* This method should be called by provider after the JAXRS callback endpoint has finished authentication
* with the remote IDP
*
* @param context
* @return
*/
Response authenticated(BrokeredIdentityContext context);
Response cancelled(String code);
Response error(String code, String message);
}
void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, BrokeredIdentityContext context);
void attachUserSession(UserSessionModel userSession, ClientSessionModel clientSession, BrokeredIdentityContext context);
void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context);
void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context);
/**
* JAXRS callback endpoint for when the remote IDP wants to callback to keycloak.
*
* @return
*/
Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event);
/**
* <p>Initiates the authentication process by sending an authentication request to an identity provider. This method is called
* only once during the authentication.</p>
*
* @param request The initial authentication request. Contains all the contextual information in order to build an authentication request to the
* identity provider.
* @return
*/
Response performLogin(AuthenticationRequest request);
/**
* <p>Returns a {@link javax.ws.rs.core.Response} containing the token previously stored during the authentication process for a
* specific user.</p>
*
* @param identity
* @return
*/
Response retrieveToken(KeycloakSession session, FederatedIdentityModel identity);
void backchannelLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm);
/**
* Called when a Keycloak application initiates a logout through the browser. This is expected to do a logout
* with the IDP
*
* @param userSession
* @param uriInfo
* @param realm
* @return null if this is not supported by this provider
*/
Response keycloakInitiatedBrowserLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm);
/**
* Export a representation of the IdentityProvider in a specific format. For example, a SAML EntityDescriptor
*
* @return
*/
Response export(UriInfo uriInfo, RealmModel realm, String format);
/**
* Implementation of marshaller to serialize/deserialize attached data to Strings, which can be saved in clientSession
* @return
*/
IdentityProviderDataMarshaller getMarshaller();
}
@@ -1,29 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
/**
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface IdentityProviderDataMarshaller {
String serialize(Object obj);
<T> T deserialize(String serialized, Class<T> clazz);
}
@@ -1,57 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.provider.ProviderFactory;
import java.io.InputStream;
import java.util.Map;
/**
* @author Pedro Igor
*/
public interface IdentityProviderFactory<T extends IdentityProvider> extends ProviderFactory<T> {
/**
* <p>A friendly name for this factory.</p>
*
* @return
*/
String getName();
/**
* <p>Creates an {@link IdentityProvider} based on the configuration contained in
* <code>model</code>.</p>
*
* @param session
* @param model The configuration to be used to create the identity provider.
* @return
*/
T create(KeycloakSession session, IdentityProviderModel model);
/**
* <p>Creates an {@link IdentityProvider} based on the configuration from
* <code>inputStream</code>.</p>
*
* @param session
* @param inputStream The input stream from where configuration will be loaded from..
* @return
*/
Map<String, String> parseConfig(KeycloakSession session, InputStream inputStream);
}
@@ -1,75 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface IdentityProviderMapper extends Provider, ProviderFactory<IdentityProviderMapper>,ConfiguredProvider {
public static final String ANY_PROVIDER = "*";
String[] getCompatibleProviders();
String getDisplayCategory();
String getDisplayType();
/**
* Called to determine what keycloak username and email to use to process the login request from the external IDP.
* It's called before "FirstBrokerLogin" flow, so can be used to map attributes to BrokeredIdentityContext ( BrokeredIdentityContext.setUserAttribute ),
* which will be available on "Review Profile" page and in authenticators during FirstBrokerLogin flow
*
*
* @param session
* @param realm
* @param mapperModel
* @param context
*/
void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
/**
* Called after UserModel is created for first time for this user. Called after "FirstBrokerLogin" flow
*
* @param session
* @param realm
* @param user
* @param mapperModel
* @param context
*/
void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
/**
* Called when this user has logged in before and has already been imported.
*
* @param session
* @param realm
* @param user
* @param mapperModel
* @param context
*/
void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
}
@@ -1,49 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class IdentityProviderMapperSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "identity-provider-mapper";
}
@Override
public Class<? extends Provider> getProviderClass() {
return IdentityProviderMapper.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return IdentityProviderMapper.class;
}
}
@@ -1,49 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author Pedro Igor
*/
public class IdentityProviderSpi implements Spi {
public static final String IDENTITY_PROVIDER_SPI_NAME = "identity_provider";
@Override
public boolean isInternal() {
return false;
}
@Override
public String getName() {
return IDENTITY_PROVIDER_SPI_NAME;
}
@Override
public Class<? extends Provider> getProviderClass() {
return IdentityProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return IdentityProviderFactory.class;
}
}
@@ -1,281 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider.util;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @author Vlastimil Elias (velias at redhat dot com)
*/
public class SimpleHttp {
private String url;
private String method;
private Map<String, String> headers;
private Map<String, String> params;
private SSLSocketFactory sslFactory;
private HostnameVerifier hostnameVerifier;
protected SimpleHttp(String url, String method) {
this.url = url;
this.method = method;
}
public static SimpleHttp doGet(String url) {
return new SimpleHttp(url, "GET");
}
public static SimpleHttp doPost(String url) {
return new SimpleHttp(url, "POST");
}
public SimpleHttp header(String name, String value) {
if (headers == null) {
headers = new HashMap<String, String>();
}
headers.put(name, value);
return this;
}
public SimpleHttp param(String name, String value) {
if (params == null) {
params = new HashMap<String, String>();
}
params.put(name, value);
return this;
}
public SimpleHttp sslFactory(SSLSocketFactory factory) {
sslFactory = factory;
return this;
}
public SimpleHttp hostnameVerifier(HostnameVerifier verifier) {
hostnameVerifier = verifier;
return this;
}
public String asString() throws IOException {
boolean get = method.equals("GET");
boolean post = method.equals("POST");
StringBuilder sb = new StringBuilder();
if (get) {
sb.append(url);
}
if (params != null) {
boolean f = true;
for (Map.Entry<String, String> p : params.entrySet()) {
if (f) {
f = false;
if (get) {
sb.append("?");
}
} else {
sb.append("&");
}
sb.append(URLEncoder.encode(p.getKey(), "UTF-8"));
sb.append("=");
sb.append(URLEncoder.encode(p.getValue(), "UTF-8"));
}
}
if (get) {
url = sb.toString();
}
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
setupTruststoreIfApplicable(connection);
OutputStream os = null;
InputStream is = null;
try {
connection.setRequestMethod(method);
if (headers != null) {
for (Map.Entry<String, String> h : headers.entrySet()) {
connection.setRequestProperty(h.getKey(), h.getValue());
}
}
if (post) {
String data = sb.toString();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", String.valueOf(data.length()));
os = connection.getOutputStream();
os.write(data.getBytes());
} else {
connection.setDoOutput(false);
}
String ce = connection.getHeaderField("Content-Encoding");
is = connection.getInputStream();
if ("gzip".equals(ce)) {
is = new GZIPInputStream(is);
}
return toString(is);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
if (connection != null) {
try {
connection.disconnect();
} catch (Exception e) {
}
}
}
}
public int asStatus() throws IOException {
boolean get = method.equals("GET");
boolean post = method.equals("POST");
StringBuilder sb = new StringBuilder();
if (get) {
sb.append(url);
}
if (params != null) {
boolean f = true;
for (Map.Entry<String, String> p : params.entrySet()) {
if (f) {
f = false;
if (get) {
sb.append("?");
}
} else {
sb.append("&");
}
sb.append(URLEncoder.encode(p.getKey(), "UTF-8"));
sb.append("=");
sb.append(URLEncoder.encode(p.getValue(), "UTF-8"));
}
}
if (get) {
url = sb.toString();
}
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
setupTruststoreIfApplicable(connection);
OutputStream os = null;
InputStream is = null;
try {
connection.setRequestMethod(method);
if (headers != null) {
for (Map.Entry<String, String> h : headers.entrySet()) {
connection.setRequestProperty(h.getKey(), h.getValue());
}
}
if (post) {
String data = sb.toString();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", String.valueOf(data.length()));
os = connection.getOutputStream();
os.write(data.getBytes());
} else {
connection.setDoOutput(false);
}
is = connection.getInputStream();
return connection.getResponseCode();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
if (connection != null) {
try {
connection.disconnect();
} catch (Exception e) {
}
}
}
}
private String toString(InputStream is) throws IOException {
InputStreamReader reader = new InputStreamReader(is);
StringWriter writer = new StringWriter();
char[] buffer = new char[1024 * 4];
for (int n = reader.read(buffer); n != -1; n = reader.read(buffer)) {
writer.write(buffer, 0, n);
}
return writer.toString();
}
private void setupTruststoreIfApplicable(HttpURLConnection connection) {
if (connection instanceof HttpsURLConnection && sslFactory != null) {
HttpsURLConnection con = (HttpsURLConnection) connection;
con.setSSLSocketFactory(sslFactory);
if (hostnameVerifier != null) {
con.setHostnameVerifier(hostnameVerifier);
}
}
}
}
@@ -1,26 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.social;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.models.IdentityProviderModel;
/**
* @author Pedro Igor
*/
public interface SocialIdentityProvider<C extends IdentityProviderModel> extends IdentityProvider<C> {
}
@@ -1,25 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.social;
import org.keycloak.broker.provider.IdentityProviderFactory;
/**
* @author Pedro Igor
*/
public interface SocialIdentityProviderFactory<I extends SocialIdentityProvider> extends IdentityProviderFactory<I> {
}
@@ -1,49 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.social;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author Pedro Igor
*/
public class SocialProviderSpi implements Spi {
public static final String SOCIAL_SPI_NAME = "social";
@Override
public boolean isInternal() {
return false;
}
@Override
public String getName() {
return SOCIAL_SPI_NAME;
}
@Override
public Class<? extends Provider> getProviderClass() {
return SocialIdentityProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return SocialIdentityProviderFactory.class;
}
}
@@ -1,26 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.cluster;
import java.io.Serializable;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ClusterEvent extends Serializable {
}
@@ -1,34 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.cluster;
/**
* Task to be executed on all cluster nodes once it's notified.
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ClusterListener {
/**
* Registered task to be executed on all cluster nodes once it's notified from cache.
*
* @param event value of notification (Object added into the cache)
*/
void run(ClusterEvent event);
}
@@ -1,66 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.cluster;
import org.keycloak.provider.Provider;
import java.util.concurrent.Callable;
/**
* Various utils related to clustering and concurrent tasks on cluster nodes
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ClusterProvider extends Provider {
/**
* Same value for all cluster nodes. It will use startup time of this server in non-cluster environment.
*/
int getClusterStartupTime();
/**
* Execute given task just if it's not already in progress (either on this or any other cluster node).
*
* @param taskKey
* @param taskTimeoutInSeconds timeout for given task. If there is existing task in progress for longer time, it's considered outdated so we will start our task.
* @param task
* @param <T>
* @return result with "executed" flag specifying if execution was executed or ignored.
*/
<T> ExecutionResult<T> executeIfNotExecuted(String taskKey, int taskTimeoutInSeconds, Callable<T> task);
/**
* Register task (listener) under given key. When this key will be put to the cache on any cluster node, the task will be executed
*
* @param taskKey
* @param task
*/
void registerListener(String taskKey, ClusterListener task);
/**
* Notify registered listeners on all cluster nodes
*
* @param taskKey
* @param event
*/
void notify(String taskKey, ClusterEvent event);
}
@@ -1,26 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.cluster;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ClusterProviderFactory extends ProviderFactory<ClusterProvider> {
}
@@ -1,48 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.cluster;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ClusterSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "cluster";
}
@Override
public Class<? extends Provider> getProviderClass() {
return ClusterProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return ClusterProviderFactory.class;
}
}
@@ -1,48 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.cluster;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExecutionResult<T> {
private final boolean executed;
private final T result;
private ExecutionResult(boolean executed, T result) {
this.executed = executed;
this.result = result;
}
public static <T> ExecutionResult<T> executed(T result) {
return new ExecutionResult<>(true, result);
}
public static <T> ExecutionResult<T> notExecuted() {
return new ExecutionResult<>(false, null);
}
public boolean isExecuted() {
return executed;
}
public T getResult() {
return result;
}
}
@@ -1,26 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.connections.httpclient;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface HttpClientFactory extends ProviderFactory<HttpClientProvider> {
}
@@ -1,50 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.connections.httpclient;
import org.apache.http.client.HttpClient;
import org.keycloak.provider.Provider;
import java.io.IOException;
import java.io.InputStream;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface HttpClientProvider extends Provider {
HttpClient getHttpClient();
/**
* Helper method
*
* @param uri
* @param text
* @return http response status
* @throws IOException
*/
public int postText(String uri, String text) throws IOException;
/**
* Helper method
*
* @param uri
* @return response stream, you must close this stream or leaks will happen
* @throws IOException
*/
public InputStream get(String uri) throws IOException;
}
@@ -1,49 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.connections.httpclient;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class HttpClientSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "connectionsHttpClient";
}
@Override
public Class<? extends Provider> getProviderClass() {
return HttpClientProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return HttpClientFactory.class;
}
}
@@ -1,32 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.email;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class EmailException extends Exception {
public EmailException(Throwable cause) {
super(cause);
}
public EmailException(String message, Throwable cause) {
super(message, cause);
}
}
Loaded 100 of 399 files, more files were not shown because too many files have changed in this diff. Show more