KEYCLOAK-828 SPNEGO/Kerberos broker - step 1
This commit is contained in:
parent
d1c4d9795b
commit
0c2795cf7c
12 changed files with 530 additions and 0 deletions
34
broker/kerberos/pom.xml
Normal file
34
broker/kerberos/pom.xml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>keycloak-broker-parent</artifactId>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>keycloak-broker-kerberos</artifactId>
|
||||||
|
<name>Keycloak Broker Kerberos</name>
|
||||||
|
<description/>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-broker-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.logging</groupId>
|
||||||
|
<artifactId>jboss-logging</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.iharder</groupId>
|
||||||
|
<artifactId>base64</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,25 @@
|
||||||
|
package org.keycloak.broker.kerberos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class KerberosConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of HTTP Headers "WWW-Authenticate" or "Authorization" used for SPNEGO/Kerberos
|
||||||
|
**/
|
||||||
|
public static final String NEGOTIATE = "Negotiate";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper parameter for relay state
|
||||||
|
*/
|
||||||
|
public static final String RELAY_STATE_PARAM = "RelayState";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OID of SPNEGO mechanism. See http://www.oid-info.com/get/1.3.6.1.5.5.2
|
||||||
|
*/
|
||||||
|
public static final String SPNEGO_OID = "1.3.6.1.5.5.2";
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
package org.keycloak.broker.kerberos;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.broker.kerberos.impl.KerberosServerSubjectAuthenticator;
|
||||||
|
import org.keycloak.broker.kerberos.impl.SPNEGOAuthenticator;
|
||||||
|
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
||||||
|
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||||
|
import org.keycloak.broker.provider.AuthenticationResponse;
|
||||||
|
import org.keycloak.broker.provider.FederatedIdentity;
|
||||||
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class KerberosIdentityProvider extends AbstractIdentityProvider<KerberosIdentityProviderConfig> {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(KerberosIdentityProvider.class);
|
||||||
|
|
||||||
|
public KerberosIdentityProvider(KerberosIdentityProviderConfig config) {
|
||||||
|
super(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationResponse handleRequest(AuthenticationRequest request) {
|
||||||
|
// TODO: trace
|
||||||
|
logger.info("handleRequest");
|
||||||
|
|
||||||
|
// Just redirect to handleResponse for now
|
||||||
|
URI redirectUri = UriBuilder.fromUri(request.getRedirectUri()).queryParam(KerberosConstants.RELAY_STATE_PARAM, request.getState()).build();
|
||||||
|
Response response = Response.status(302)
|
||||||
|
.location(redirectUri)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return AuthenticationResponse.fromResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRelayState(AuthenticationRequest request) {
|
||||||
|
UriInfo uriInfo = request.getUriInfo();
|
||||||
|
return uriInfo.getQueryParameters().getFirst(KerberosConstants.RELAY_STATE_PARAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationResponse handleResponse(AuthenticationRequest request) {
|
||||||
|
String authHeader = request.getHttpRequest().getHttpHeaders().getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
|
||||||
|
|
||||||
|
// Case when we don't yet have any Negotiate header
|
||||||
|
if (authHeader == null) {
|
||||||
|
return sendNegotiateResponse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] tokens = authHeader.split(" ");
|
||||||
|
if (tokens.length != 2) {
|
||||||
|
logger.warn("Invalid length of tokens: " + tokens.length);
|
||||||
|
return sendNegotiateResponse(null);
|
||||||
|
} else if (!KerberosConstants.NEGOTIATE.equalsIgnoreCase(tokens[0])) {
|
||||||
|
logger.warn("Unknown scheme " + tokens[0]);
|
||||||
|
return sendNegotiateResponse(null);
|
||||||
|
} else {
|
||||||
|
String spnegoToken = tokens[1];
|
||||||
|
SPNEGOAuthenticator spnegoAuthenticator = createSPNEGOAuthenticator(spnegoToken);
|
||||||
|
spnegoAuthenticator.authenticate();
|
||||||
|
|
||||||
|
if (spnegoAuthenticator.isAuthenticated()) {
|
||||||
|
FederatedIdentity federatedIdentity = getFederatedIdentity(spnegoAuthenticator);
|
||||||
|
return AuthenticationResponse.end(federatedIdentity);
|
||||||
|
} else {
|
||||||
|
return sendNegotiateResponse(spnegoAuthenticator.getResponseToken());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SPNEGOAuthenticator createSPNEGOAuthenticator(String spnegoToken) {
|
||||||
|
KerberosServerSubjectAuthenticator kerberosAuth = createKerberosSubjectAuthenticator();
|
||||||
|
return new SPNEGOAuthenticator(kerberosAuth, spnegoToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KerberosServerSubjectAuthenticator createKerberosSubjectAuthenticator() {
|
||||||
|
return new KerberosServerSubjectAuthenticator(getConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send response with header "WWW-Authenticate: Negotiate {negotiateToken}"
|
||||||
|
*
|
||||||
|
* @param negotiateToken token to be send back in response or null if just "WWW-Authenticate: Negotiate" should be sent
|
||||||
|
* @return AuthenticationResponse
|
||||||
|
*/
|
||||||
|
protected AuthenticationResponse sendNegotiateResponse(String negotiateToken) {
|
||||||
|
String negotiateHeader = negotiateToken == null ? KerberosConstants.NEGOTIATE : KerberosConstants.NEGOTIATE + " " + negotiateToken;
|
||||||
|
|
||||||
|
Response response = Response.status(Response.Status.UNAUTHORIZED)
|
||||||
|
.header(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader)
|
||||||
|
.build();
|
||||||
|
return AuthenticationResponse.fromResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected FederatedIdentity getFederatedIdentity(SPNEGOAuthenticator spnegoAuthenticator) {
|
||||||
|
String kerberosUsername = spnegoAuthenticator.getPrincipal();
|
||||||
|
FederatedIdentity user = new FederatedIdentity(kerberosUsername);
|
||||||
|
user.setUsername(kerberosUsername);
|
||||||
|
|
||||||
|
// Just guessing email, but likely can't do anything better...
|
||||||
|
String[] tokens = kerberosUsername.split("@");
|
||||||
|
String email = tokens[0] + "@" + tokens[1].toLowerCase();
|
||||||
|
user.setEmail(email);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response retrieveToken(FederatedIdentityModel identity) {
|
||||||
|
logger.warn("retrieveToken unsupported for Kerberos right now");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.keycloak.broker.kerberos;
|
||||||
|
|
||||||
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class KerberosIdentityProviderConfig extends IdentityProviderModel {
|
||||||
|
|
||||||
|
public KerberosIdentityProviderConfig(IdentityProviderModel identityProviderModel) {
|
||||||
|
super(identityProviderModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServerPrincipal() {
|
||||||
|
return getConfig().get("serverPrincipal");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeyTab() {
|
||||||
|
return getConfig().get("keyTab");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDebug() {
|
||||||
|
return Boolean.valueOf(getConfig().get("debug"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.keycloak.broker.kerberos;
|
||||||
|
|
||||||
|
import org.keycloak.broker.kerberos.KerberosIdentityProvider;
|
||||||
|
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
|
||||||
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class KerberosIdentityProviderFactory extends AbstractIdentityProviderFactory<KerberosIdentityProvider> {
|
||||||
|
|
||||||
|
public static final String PROVIDER_ID = "kerberos";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return PROVIDER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Kerberos";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KerberosIdentityProvider create(IdentityProviderModel model) {
|
||||||
|
return new KerberosIdentityProvider(new KerberosIdentityProviderConfig(model));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package org.keycloak.broker.kerberos.impl;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
import javax.security.auth.login.AppConfigurationEntry;
|
||||||
|
import javax.security.auth.login.Configuration;
|
||||||
|
import javax.security.auth.login.LoginContext;
|
||||||
|
import javax.security.auth.login.LoginException;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.broker.kerberos.KerberosIdentityProviderConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class KerberosServerSubjectAuthenticator {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(KerberosServerSubjectAuthenticator.class);
|
||||||
|
|
||||||
|
private final KerberosIdentityProviderConfig config;
|
||||||
|
private LoginContext loginContext;
|
||||||
|
|
||||||
|
public KerberosServerSubjectAuthenticator(KerberosIdentityProviderConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Subject authenticateServerSubject() throws LoginException {
|
||||||
|
Configuration config = createJaasConfiguration();
|
||||||
|
loginContext = new LoginContext("does-not-matter", null, null, config);
|
||||||
|
loginContext.login();
|
||||||
|
return loginContext.getSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logoutServerSubject() {
|
||||||
|
if (loginContext != null) {
|
||||||
|
try {
|
||||||
|
loginContext.logout();
|
||||||
|
} catch (LoginException le) {
|
||||||
|
logger.error("Failed to logout kerberos server subject: " + config.getServerPrincipal(), le);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Configuration createJaasConfiguration() {
|
||||||
|
return new Configuration() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
|
||||||
|
Map<String, Object> options = new HashMap<String, Object>();
|
||||||
|
options.put("storeKey", "true");
|
||||||
|
options.put("doNotPrompt", "true");
|
||||||
|
options.put("isInitiator", "false");
|
||||||
|
options.put("useKeyTab", "true");
|
||||||
|
|
||||||
|
options.put("keyTab", config.getKeyTab());
|
||||||
|
options.put("principal", config.getServerPrincipal());
|
||||||
|
options.put("debug", String.valueOf(config.getDebug()));
|
||||||
|
AppConfigurationEntry kerberosLMConfiguration = new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
|
||||||
|
return new AppConfigurationEntry[] { kerberosLMConfiguration };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
package org.keycloak.broker.kerberos.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
|
||||||
|
import net.iharder.Base64;
|
||||||
|
import org.ietf.jgss.GSSContext;
|
||||||
|
import org.ietf.jgss.GSSCredential;
|
||||||
|
import org.ietf.jgss.GSSException;
|
||||||
|
import org.ietf.jgss.GSSManager;
|
||||||
|
import org.ietf.jgss.Oid;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.broker.kerberos.KerberosConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class SPNEGOAuthenticator {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(SPNEGOAuthenticator.class);
|
||||||
|
|
||||||
|
private static final GSSManager GSS_MANAGER = GSSManager.getInstance();
|
||||||
|
|
||||||
|
private final KerberosServerSubjectAuthenticator kerberosSubjectAuthenticator;
|
||||||
|
private final String spnegoToken;
|
||||||
|
|
||||||
|
private boolean authenticated = false;
|
||||||
|
private String principal = null;
|
||||||
|
private GSSCredential delegationCredential;
|
||||||
|
private String responseToken = null;
|
||||||
|
|
||||||
|
public SPNEGOAuthenticator(KerberosServerSubjectAuthenticator kerberosSubjectAuthenticator, String spnegoToken) {
|
||||||
|
this.kerberosSubjectAuthenticator = kerberosSubjectAuthenticator;
|
||||||
|
this.spnegoToken = spnegoToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void authenticate() {
|
||||||
|
// TODO: debug
|
||||||
|
logger.info("SPNEGO Login with token: " + spnegoToken);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Subject serverSubject = kerberosSubjectAuthenticator.authenticateServerSubject();
|
||||||
|
authenticated = Subject.doAs(serverSubject, new AcceptSecContext());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("SPNEGO login failed: " + e.getMessage());
|
||||||
|
|
||||||
|
// TODO: debug and check if it is shown in the log
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("SPNEGO login failed: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
kerberosSubjectAuthenticator.logoutServerSubject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAuthenticated() {
|
||||||
|
return authenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrincipal() {
|
||||||
|
return principal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseToken() {
|
||||||
|
return responseToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GSSCredential getDelegationCredential() {
|
||||||
|
return delegationCredential;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AcceptSecContext implements PrivilegedExceptionAction<Boolean> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean run() throws Exception {
|
||||||
|
GSSContext gssContext = null;
|
||||||
|
try {
|
||||||
|
// TODO: debug
|
||||||
|
logger.info("Going to establish security context");
|
||||||
|
gssContext = establishContext();
|
||||||
|
logAuthDetails(gssContext);
|
||||||
|
|
||||||
|
// What should be done with delegation credential? Figure out if there are use-cases for storing it as claims in FederatedIdentity
|
||||||
|
if (gssContext.getCredDelegState()) {
|
||||||
|
delegationCredential = gssContext.getDelegCred();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gssContext.isEstablished()) {
|
||||||
|
principal = gssContext.getSrcName().toString();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (gssContext != null) {
|
||||||
|
gssContext.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GSSContext establishContext() throws GSSException, IOException {
|
||||||
|
Oid spnegoOid = new Oid(KerberosConstants.SPNEGO_OID);
|
||||||
|
GSSCredential credential = GSS_MANAGER.createCredential(null,
|
||||||
|
GSSCredential.DEFAULT_LIFETIME,
|
||||||
|
spnegoOid,
|
||||||
|
GSSCredential.ACCEPT_ONLY);
|
||||||
|
GSSContext gssContext = GSS_MANAGER.createContext(credential);
|
||||||
|
|
||||||
|
byte[] inputToken = Base64.decode(spnegoToken);
|
||||||
|
byte[] respToken = gssContext.acceptSecContext(inputToken, 0, inputToken.length);
|
||||||
|
responseToken = Base64.encodeBytes(respToken);
|
||||||
|
|
||||||
|
return gssContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void logAuthDetails(GSSContext gssContext) throws GSSException {
|
||||||
|
|
||||||
|
// TODO: debug
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
String message = new StringBuilder("SPNEGO Security context accepted with token: " + responseToken)
|
||||||
|
.append(", established: " + gssContext.isEstablished())
|
||||||
|
.append(", credDelegState: " + gssContext.getCredDelegState())
|
||||||
|
.append(", mutualAuthState: " + gssContext.getMutualAuthState())
|
||||||
|
.append(", lifetime: " + gssContext.getLifetime())
|
||||||
|
.append(", confState: " + gssContext.getConfState())
|
||||||
|
.append(", integState: " + gssContext.getIntegState())
|
||||||
|
.append(", srcName: " + gssContext.getSrcName())
|
||||||
|
.append(", targName: " + gssContext.getTargName())
|
||||||
|
.toString();
|
||||||
|
logger.info(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
org.keycloak.broker.kerberos.KerberosIdentityProviderFactory
|
|
@ -18,6 +18,7 @@
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
<module>oidc</module>
|
<module>oidc</module>
|
||||||
<module>saml</module>
|
<module>saml</module>
|
||||||
|
<module>kerberos</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
5
dependencies/server-all/pom.xml
vendored
5
dependencies/server-all/pom.xml
vendored
|
@ -93,6 +93,11 @@
|
||||||
<artifactId>keycloak-broker-saml</artifactId>
|
<artifactId>keycloak-broker-saml</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-broker-kerberos</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-social-github</artifactId>
|
<artifactId>keycloak-social-github</artifactId>
|
||||||
|
|
|
@ -785,6 +785,14 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
|
||||||
$scope.identityProvider.config.postBindingResponse = true;
|
$scope.identityProvider.config.postBindingResponse = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.initKerberosProvider = function() {
|
||||||
|
if (instance && instance.id) {
|
||||||
|
$scope.identityProvider.config.debug = $scope.getBoolean($scope.identityProvider.config.debug);
|
||||||
|
} else {
|
||||||
|
$scope.identityProvider.config.debug = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('RealmTokenDetailCtrl', function($scope, Realm, realm, $http, $location, $route, Dialog, Notifications, TimeUnit) {
|
module.controller('RealmTokenDetailCtrl', function($scope, Realm, realm, $http, $location, $route, Dialog, Notifications, TimeUnit) {
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
|
||||||
|
<div id="content-area" class="col-sm-9" role="main" data-ng-init="initKerberosProvider()">
|
||||||
|
<data-kc-navigation data-kc-current="social" data-kc-realm="realm.realm" data-kc-social="realm.social"></data-kc-navigation>
|
||||||
|
<h2></h2>
|
||||||
|
<div id="content">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
|
||||||
|
<li class="active">{{identityProvider.name}} Provider Settings</li>
|
||||||
|
</ol>
|
||||||
|
<h2 class="pull-left">{{identityProvider.name}} Provider Settings</h2>
|
||||||
|
<p class="subtitle"><span class="required">*</span> Required fields</p>
|
||||||
|
<form class="form-horizontal" name="realmForm" novalidate>
|
||||||
|
<fieldset>
|
||||||
|
<div class="form-group clearfix">
|
||||||
|
<label class="col-sm-2 control-label" for="identifier">Alias <span class="required">*</span></label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input class="form-control" id="identifier" type="text" ng-model="identityProvider.id" required>
|
||||||
|
</div>
|
||||||
|
<span tooltip-placement="right" tooltip="The alias unique identifies an identity provider and it is also used to build the redirect uri." class="fa fa-info-circle"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group clearfix">
|
||||||
|
<label class="col-sm-2 control-label" for="name">Name <span class="required">*</span></label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input class="form-control" id="name" type="text" ng-model="identityProvider.name" required>
|
||||||
|
</div>
|
||||||
|
<span tooltip-placement="right" tooltip="The friendly name for this identity provider." class="fa fa-info-circle"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group clearfix">
|
||||||
|
<label class="col-sm-2 control-label" for="serverPrincipal">Server principal <span class="required">*</span></label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input class="form-control" id="serverPrincipal" type="text" ng-model="identityProvider.config.serverPrincipal" required>
|
||||||
|
</div>
|
||||||
|
<span tooltip-placement="right" tooltip="Full name of server principal for HTTP service including server and domain name. For example HTTP/host.foo.org@FOO.ORG" class="fa fa-info-circle"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group clearfix">
|
||||||
|
<label class="col-sm-2 control-label" for="keyTab">KeyTab <span class="required">*</span></label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input class="form-control" id="keyTab" type="text" ng-model="identityProvider.config.keyTab" required>
|
||||||
|
</div>
|
||||||
|
<span tooltip-placement="right" tooltip="Location of Kerberos KeyTab file containing the credentials of server principal. For example /etc/krb5.keytab" class="fa fa-info-circle"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="debug">Debug </label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input ng-model="identityProvider.config.debug" id="debug" onoffswitch />
|
||||||
|
</div>
|
||||||
|
<span tooltip-placement="right" tooltip="Enable/disable debug logging to standard output for Krb5LoginModule." class="fa fa-info-circle"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="enabled">Enabled</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input ng-model="identityProvider.enabled" id="enabled" onoffswitch />
|
||||||
|
</div>
|
||||||
|
<span tooltip-placement="right" tooltip="Enable/disable this identity provider." class="fa fa-info-circle"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="updateProfileFirstLogin">Update Profile on First Login</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input ng-model="identityProvider.updateProfileFirstLogin" name="identityProvider.updateProfileFirstLogin" id="updateProfileFirstLogin" onoffswitch />
|
||||||
|
</div>
|
||||||
|
<span tooltip-placement="right" tooltip="Indicates if user must update his profile right after the first login." class="fa fa-info-circle"></span>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div class="pull-right form-actions">
|
||||||
|
<button kc-save>Save</button>
|
||||||
|
<button kc-delete data-ng-click="remove()" data-ng-show="!newIdentityProvider">Delete</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in a new issue