You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by pz...@apache.org on 2018/03/14 18:36:02 UTC

[3/3] knox git commit: KNOX-1202 - Added UI elements to indicate invalid param values

KNOX-1202 - Added UI elements to indicate invalid param values


Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/2e8716d8
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/2e8716d8
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/2e8716d8

Branch: refs/heads/master
Commit: 2e8716d89854a407314e5910cb6b37db0400d050
Parents: 97d865e
Author: Phil Zampino <pz...@apache.org>
Authored: Wed Mar 14 13:31:43 2018 -0400
Committer: Phil Zampino <pz...@apache.org>
Committed: Wed Mar 14 14:17:45 2018 -0400

----------------------------------------------------------------------
 .../new-desc-wizard.component.html              | 33 ++++++++--
 .../new-desc-wizard.component.ts                | 41 ++++++++++--
 .../acls-authzn-provider-config.ts              | 17 ++++-
 .../cas-provider-config.ts                      | 54 ++++++++-------
 .../default-idassertion-provider-config.ts      | 38 ++++++-----
 .../display-binding-provider-config.ts          | 12 +++-
 .../kerberos-provider-config.ts                 | 41 ++++++++----
 .../ldap-provider-config.ts                     | 69 ++++++++++++--------
 .../oauth-provider-config.ts                    | 28 +++++++-
 .../oidc-provider-config.ts                     | 65 +++++++++++-------
 .../pam-provider-config.ts                      | 19 +++++-
 .../provider-config-wizard.component.html       |  1 +
 .../provider-config-wizard.component.ts         | 14 +++-
 .../regex-idassertion-provider-config.ts        | 19 +++++-
 .../saml-provider-config.ts                     | 44 +++++++++++--
 .../sso-cookie-provider-config.ts               | 28 +++++++-
 .../switchcase-idassertion-provider-config.ts   | 29 +++++---
 .../src/app/utils/validation-utils.ts           | 52 +++++++++++++++
 .../applications/admin-ui/app/index.html        |  2 +-
 .../app/inline.0c599dd7846e2462c94c.bundle.js   |  1 -
 .../app/inline.a7f3e89f1023e555e44a.bundle.js   |  1 +
 .../app/main.743b2fb8ac3467eb4d6e.bundle.js     |  1 +
 .../app/main.bfb4b6a3d7d72f4c8841.bundle.js     |  1 -
 23 files changed, 468 insertions(+), 142 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.html
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.html b/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.html
index 4ab8bec..f1de99d 100644
--- a/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.html
+++ b/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.html
@@ -6,7 +6,10 @@
     <div class="panel-body">
 
       <div> <!-- Descriptor Name -->
-        <strong>Name</strong> <input type="text" [(ngModel)]="descriptorName">
+        <span>
+          <strong>Name</strong> <input type="text" [(ngModel)]="descriptorName">
+        </span>
+        <span *ngIf="!isValidDescriptorName()" style="color: red">invalid</span>
       </div> <!-- Descriptor Name -->
 
       <br>
@@ -72,19 +75,37 @@
           <table>
             <tr>
               <td><strong>Address</strong></td>
-              <td><input type="text" [(ngModel)]="descriptor.discoveryAddress"></td>
+              <td>
+                <span>
+                  <input type="text" [(ngModel)]="descriptor.discoveryAddress">
+                </span>
+                <span *ngIf="!isValidDiscoveryAddress()" style="color: red">invalid</span>
+              </td>
             </tr>
             <tr>
               <td><strong>Cluster</strong></td>
-              <td><input type="text" [(ngModel)]="descriptor.discoveryCluster"></td>
+              <td>
+                <span>
+                  <input type="text" [(ngModel)]="descriptor.discoveryCluster">
+                </span>
+                <span *ngIf="!isValidDiscoveryCluster()" style="color: red">invalid</span>
+              </td>
             </tr>
             <tr>
               <td><strong>Username</strong></td>
-              <td><input type="text" [(ngModel)]="descriptor.discoveryUser"></td>
+              <td>
+                <span>
+                  <input type="text" [(ngModel)]="descriptor.discoveryUser">
+                </span>
+              </td>
             </tr>
             <tr>
               <td><strong>Password Alias</strong></td>
-              <td><input type="text" [(ngModel)]="descriptor.discoveryPassAlias"></td>
+              <td>
+                <span>
+                  <input type="text" [(ngModel)]="descriptor.discoveryPassAlias">
+                </span>
+              </td>
             </tr>
           </table>
         </div>
@@ -99,7 +120,7 @@
             (click)="newDescriptorModal.dismiss()">Cancel</button>
     <button type="button"
             class="btn btn-primary btn-sm"
-            [disabled]="!descriptor || !descriptorName || !validate()"
+            [disabled]="!validate()"
             (click)="newDescriptorModal.close()">Ok</button>
   </bs-modal-footer>
 </bs-modal>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.ts b/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.ts
index 0759cae..d9752a1 100644
--- a/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.ts
+++ b/gateway-admin-ui/src/app/new-desc-wizard/new-desc-wizard.component.ts
@@ -167,13 +167,46 @@ export class NewDescWizardComponent implements OnInit {
   validate(): boolean {
     let isValid: boolean = true;
 
-    // Validate the discovery address
-    if (this.descriptor.discoveryAddress) {
-      isValid = isValid && ValidationUtils.isValidURL(this.descriptor.discoveryAddress);
-      isValid = isValid && ValidationUtils.isValidString(this.descriptor.discoveryCluster);
+    if (this.descriptor) {
+
+      isValid = isValid && this.isValidDescriptorName();
+
+      // Validate the discovery address
+      if (this.descriptor.discoveryAddress) {
+        isValid = isValid && this.isValidDiscoveryAddress();
+        isValid = isValid && this.isValidDiscoveryCluster();
+      }
+    } else {
+      isValid = false;
+    }
+
+    return isValid;
+  }
+
+  isValidDescriptorName(): boolean {
+    let isValid: boolean = false;
+
+    if (this.descriptorName) {
+      isValid = ValidationUtils.isValidString(this.descriptorName);
     }
 
     return isValid;
   }
 
+  isValidDiscoveryAddress(): boolean {
+    if (this.descriptor.discoveryAddress) {
+      return (ValidationUtils.isValidURL(this.descriptor.discoveryAddress));
+    } else {
+      return true;
+    }
+  }
+
+  isValidDiscoveryCluster(): boolean {
+    if (this.descriptor.discoveryAddress) {
+      return (ValidationUtils.isValidString(this.descriptor.discoveryCluster));
+    } else {
+      return true;
+    }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/acls-authzn-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/acls-authzn-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/acls-authzn-provider-config.ts
index a7a5291..d423887 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/acls-authzn-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/acls-authzn-provider-config.ts
@@ -49,7 +49,21 @@ export class ACLsAuthznProviderConfig extends DisplayBindingProviderConfig {
     return ACLsAuthznProviderConfig.displayPropertyNameBindings.get(name);
   }
 
-  isValid(): boolean {
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
+
+    switch (paramName) {
+      case ACLsAuthznProviderConfig.DEFAULT_MODE:
+        isValid = this.isValidMode();
+        break;
+      default:
+        isValid = true;
+    }
+
+    return isValid;
+  }
+
+  private isValidMode(): boolean {
     let isValid: boolean = true;
 
     let defaultMode = this.getParam(this.getDisplayNamePropertyBinding(ACLsAuthznProviderConfig.DEFAULT_MODE));
@@ -59,4 +73,5 @@ export class ACLsAuthznProviderConfig extends DisplayBindingProviderConfig {
 
     return isValid;
   }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/cas-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/cas-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/cas-provider-config.ts
index 00a2437..644a0e3 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/cas-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/cas-provider-config.ts
@@ -40,8 +40,6 @@ export class CASProviderConfig extends AuthenticationProviderConfig {
                                         ]);
 
 
-  private static SUPPORTED_PROTOCOLS: string[] = [ 'CAS10', 'CAS20', 'CAS20_PROXY', 'CAS30', 'CAS30_PROXY', 'SAML' ];
-
   constructor() {
     super('pac4j', AuthenticationProviderConfig.FEDERATION_ROLE);
   }
@@ -54,34 +52,46 @@ export class CASProviderConfig extends AuthenticationProviderConfig {
     return CASProviderConfig.displayPropertyNameBindings.get(name);
   }
 
-  isValid(): boolean {
-    let isValid: boolean = true;
-
-    let cbURL = this.getParam(this.getDisplayNamePropertyBinding(CASProviderConfig.CALLBACK_URL));
-    if (cbURL) {
-      let isCBURLValid = ValidationUtils.isValidURL(cbURL);
-      if (!isCBURLValid) {
-        console.debug(CASProviderConfig.CALLBACK_URL + ' value is not a valid URL.');
-      }
-      isValid = isValid && isCBURLValid;
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
+
+    switch (paramName) {
+      case CASProviderConfig.CALLBACK_URL:
+      case CASProviderConfig.LOGIN_URL:
+        isValid = this.isValidURL(paramName);
+        break;
+      case CASProviderConfig.PROTOCOL:
+        isValid = this.isValidProtocol();
+        break;
+      default:
+        isValid = true;
     }
 
-    let loginURL = this.getParam(this.getDisplayNamePropertyBinding(CASProviderConfig.LOGIN_URL));
-    if (loginURL) {
-      let isLoginURLValid = ValidationUtils.isValidURL(loginURL);
-      if (!isLoginURLValid) {
-        console.debug(CASProviderConfig.LOGIN_URL + ' value is not a valid URL.');
+    return isValid;
+  }
+
+  private isValidURL(param: string): boolean {
+    let isValid: boolean = true;
+    let url = this.getParam(this.getDisplayNamePropertyBinding(param));
+    if (url) {
+      isValid = ValidationUtils.isValidHttpURL(url);
+      if (!isValid) {
+        console.debug(param + ' value is not a valid URL.');
       }
-      isValid = isValid && isLoginURLValid;
     }
+    return isValid;
+  }
+
+  private isValidProtocol(): boolean {
+    let isValid: boolean = true;
 
     let protocol = this.getParam(this.getDisplayNamePropertyBinding(CASProviderConfig.PROTOCOL));
     if (protocol) {
-      let isProtocolValid = (CASProviderConfig.SUPPORTED_PROTOCOLS.indexOf(protocol) > -1);
-      if (!isProtocolValid) {
-        console.debug(CASProviderConfig.PROTOCOL + ' value is not a supported protocol');
+      isValid = isValid = ValidationUtils.isValidCASProtocol(protocol);
+      if (!isValid) {
+        console.debug(CASProviderConfig.PROTOCOL + ' value is not a valid protocol: ' +
+                      ValidationUtils.CAS_PROTOCOLS.toString());
       }
-      isValid = isValid && isProtocolValid;
     }
 
     return isValid;

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/default-idassertion-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/default-idassertion-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/default-idassertion-provider-config.ts
index aa119a1..a4b1830 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/default-idassertion-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/default-idassertion-provider-config.ts
@@ -16,6 +16,7 @@
  */
 
 import {IdentityAssertionProviderConfig} from "./identity-assertion-provider-config";
+import {ValidationUtils} from "../utils/validation-utils";
 
 export class DefaultIdAssertionProviderConfig extends IdentityAssertionProviderConfig {
 
@@ -32,8 +33,6 @@ export class DefaultIdAssertionProviderConfig extends IdentityAssertionProviderC
       [DefaultIdAssertionProviderConfig.GROUP_PRINCIPAL_MAPPING, 'group.principal.mapping']
     ]);
 
-  private static MAPPING_REGEXP = new RegExp('^(?:(?:[\\w\\*\\,]*=(?:[\\w][^\\*\\=])+[;]?)*)$');
-
   constructor() {
     console.debug('new DefaultIdAssertionProviderConfig()');
     super('Default');
@@ -47,25 +46,30 @@ export class DefaultIdAssertionProviderConfig extends IdentityAssertionProviderC
     return DefaultIdAssertionProviderConfig.displayPropertyNameBindings.get(name);
   }
 
-  isValid(): boolean {
-    let isValid: boolean = true;
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
 
-    let pMap = this.getParam(this.getDisplayNamePropertyBinding(DefaultIdAssertionProviderConfig.PRINCIPAL_MAPPING));
-    if (pMap) {
-      let isPMapValid = DefaultIdAssertionProviderConfig.MAPPING_REGEXP.test(pMap);
-      if (!isPMapValid) {
-        console.debug(DefaultIdAssertionProviderConfig.PRINCIPAL_MAPPING + ' value is not a valid mapping');
-      }
-      isValid = isValid && isPMapValid;
+    switch (paramName) {
+      case DefaultIdAssertionProviderConfig.PRINCIPAL_MAPPING:
+      case DefaultIdAssertionProviderConfig.GROUP_PRINCIPAL_MAPPING:
+        isValid = this.isValidPrincipalMapping(paramName);
+        break;
+      default:
+        isValid = true;
     }
 
-    let gpMap = this.getParam(this.getDisplayNamePropertyBinding(DefaultIdAssertionProviderConfig.GROUP_PRINCIPAL_MAPPING));
-    if (gpMap) {
-      let isGMapValid = DefaultIdAssertionProviderConfig.MAPPING_REGEXP.test(gpMap);
-      if (!isGMapValid) {
-        console.debug(DefaultIdAssertionProviderConfig.GROUP_PRINCIPAL_MAPPING + ' value is not a valid mapping');
+    return isValid;
+  }
+
+  private isValidPrincipalMapping(param: string) {
+    let isValid: boolean = true;
+
+    let mapping = this.getParam(this.getDisplayNamePropertyBinding(param));
+    if (mapping) {
+      isValid = ValidationUtils.isValidPrincipalMapping(mapping);
+      if (!isValid) {
+        console.debug(param + ' value is not a valid principal mapping.')
       }
-      isValid = isValid && isGMapValid;
     }
 
     return isValid;

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/display-binding-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/display-binding-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/display-binding-provider-config.ts
index 9ded8f6..2fb0eda 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/display-binding-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/display-binding-provider-config.ts
@@ -63,10 +63,20 @@ export abstract class DisplayBindingProviderConfig extends ProviderConfig {
     return false;
   }
 
-  isValid(): boolean {
+  isValidParamValue(paramName: string) {
     return true;
   }
 
+  isValid(): boolean {
+    let isValid: boolean = true;
+
+    for (let param of this.getDisplayPropertyNames()) {
+      isValid = isValid && this.isValidParamValue(param);
+    }
+
+    return isValid;
+  }
+
   abstract getDisplayPropertyNames(): string[];
 
   abstract getDisplayNamePropertyBinding(name: string): string;

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/kerberos-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/kerberos-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/kerberos-provider-config.ts
index e615c44..dff3124 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/kerberos-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/kerberos-provider-config.ts
@@ -111,27 +111,46 @@ export class KerberosProviderConfig extends AuthenticationProviderConfig {
     }
   }
 
-  isValid(): boolean {
+  isValidParamValue(paramName: string): boolean {
     let isValid: boolean = true;
 
-    let allowAnon = this.getParam(this.getDisplayNamePropertyBinding(KerberosProviderConfig.ANON_ALLOWED));
-    if (allowAnon) {
-      let isValidAllowAnon = ValidationUtils.isValidBoolean(allowAnon);
-      if (!isValidAllowAnon) {
-        console.debug(KerberosProviderConfig.ANON_ALLOWED + ' value is not valid.');
-      }
-      isValid = isValid && isValidAllowAnon;
+    switch (paramName) {
+      case KerberosProviderConfig.ANON_ALLOWED:
+        isValid = this.isValidAllowAnon();
+        break;
+      case KerberosProviderConfig.TOKEN_VALIDITY:
+        isValid = this.isValidTokenExpiration();
+        break;
+      default:
+        isValid = true;
     }
 
+    return isValid;
+  }
+
+  private isValidTokenExpiration(): boolean {
+    let isValid: boolean = true;
+
     let tokenExpiration = this.getParam(this.getDisplayNamePropertyBinding(KerberosProviderConfig.TOKEN_VALIDITY));
     if (tokenExpiration) {
-      let isValidTokenExpiration = ValidationUtils.isValidNumber(tokenExpiration);
-      if (!isValidTokenExpiration) {
+      isValid = ValidationUtils.isValidNumber(tokenExpiration);
+      if (!isValid) {
         console.debug(KerberosProviderConfig.TOKEN_VALIDITY + ' value is not valid.');
       }
-      isValid = isValid && isValidTokenExpiration;
     }
+    return isValid;
+  }
 
+  private isValidAllowAnon(): boolean {
+    let isValid: boolean = true;
+
+    let allowAnon = this.getParam(this.getDisplayNamePropertyBinding(KerberosProviderConfig.ANON_ALLOWED));
+    if (allowAnon) {
+      isValid = ValidationUtils.isValidBoolean(allowAnon);
+      if (!isValid) {
+        console.debug(KerberosProviderConfig.ANON_ALLOWED + ' value is not valid.');
+      }
+    }
     return isValid;
   }
 

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/ldap-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/ldap-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/ldap-provider-config.ts
index 719124a..ada9f99 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/ldap-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/ldap-provider-config.ts
@@ -21,19 +21,6 @@ import {ValidationUtils} from "../utils/validation-utils";
 
 export class LDAPProviderConfig extends AuthenticationProviderConfig implements OrderedParamContainer {
 
-  private static DN_TEMPLATE_REGEXP: RegExp =
-    new RegExp('(?:[A-Za-z][\\w-]*|\\d+(?:\\.\\d+)*)' +
-               '=(?:#(?:[\\dA-Fa-f]{2})+|(?:[^,=\\+<>#;\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*")' +
-               '(?:\\+(?:[A-Za-z][\\w-]*|\\d+(?:\\.\\d+)*)' +
-               '=(?:#(?:[\\dA-Fa-f]{2})' +
-               '+|(?:[^,=\\+<>#;\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*"))' +
-               '*(?:,(?:[A-Za-z][\\w-]*|\\d+(?:\\.\\d+)*)' +
-               '=(?:#(?:[\\dA-Fa-f]{2})+|(?:[^,=\\+<>#;\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*")' +
-               '(?:\\+(?:[A-Za-z][\\w-]*|\\d+(?:\\.\\d+)*)=(?:#(?:[\\dA-Fa-f]{2})+|(?:[^,=\\+<>#;\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*"))*)*');
-
-
-  private static LDAP_URL_SCHEMES: string[] = [ 'ldap', 'ldaps' ];
-
   private static SESSION_TIMEOUT       = 'Session Timeout';
   private static DN_TEMPLATE           = 'User DN Template';
   private static URL                   = 'URL';
@@ -115,39 +102,65 @@ export class LDAPProviderConfig extends AuthenticationProviderConfig implements
     return result;
   }
 
-  isValid(): boolean {
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
+
+    switch (paramName) {
+      case LDAPProviderConfig.SESSION_TIMEOUT:
+        isValid = this.isTimeoutValid();
+        break;
+      case LDAPProviderConfig.DN_TEMPLATE:
+        isValid = this.isDnTemplateValid();
+        break;
+      case LDAPProviderConfig.URL:
+        isValid = this.isLdapURLValid();
+        break;
+      default:
+        isValid = true;
+    }
+
+    return isValid;
+  }
+
+  private isTimeoutValid(): boolean {
     let isValid: boolean = true;
 
     let timeout = this.getParam(this.getDisplayNamePropertyBinding(LDAPProviderConfig.SESSION_TIMEOUT));
     if (timeout) {
-      let isTimeoutValid = ValidationUtils.isValidNumber(timeout);
-      if (!isTimeoutValid) {
+      isValid = ValidationUtils.isValidNumber(timeout);
+      if (!isValid) {
         console.debug(LDAPProviderConfig.SESSION_TIMEOUT + ' value is not valid.');
       }
-      isValid = (isValid && isTimeoutValid);
     }
+    return isValid;
+  }
+
+  private isLdapURLValid(): boolean {
+    let isValid: boolean = true;
 
     let url = this.getParam(this.getDisplayNamePropertyBinding(LDAPProviderConfig.URL));
     if (url) {
-      // Ensure that it's a valid LDAP(S) URL
-      let isURLValid = ValidationUtils.isValidURLOfScheme(url, LDAPProviderConfig.LDAP_URL_SCHEMES);
-      if (!isURLValid) {
-        console.debug(LDAPProviderConfig.URL + ' value is not valid.');
+      isValid = ValidationUtils.isValidLdapURL(url);
+      if (!isValid) {
+        console.debug(LDAPProviderConfig.URL+ ' value is not valid.');
       }
-      isValid = isValid && isURLValid;
     } else {
-      isValid = false;
+      isValid = false; // URL must be specified
     }
 
+    return isValid;
+  }
+
+  private isDnTemplateValid(): boolean {
+    let isValid: boolean = true;
+
     let dnTemplate = this.getParam(this.getDisplayNamePropertyBinding(LDAPProviderConfig.DN_TEMPLATE));
     if (dnTemplate) {
-      let isDNTemplateValid = LDAPProviderConfig.DN_TEMPLATE_REGEXP.test(dnTemplate);
-      if (!isDNTemplateValid) {
-        console.debug(LDAPProviderConfig.DN_TEMPLATE + ' value is not a valid DN template.');
+      isValid = ValidationUtils.isValidDNTemplate(dnTemplate);
+      if (!isValid) {
+        console.debug(LDAPProviderConfig.DN_TEMPLATE + ' value is not valid.');
       }
-      isValid = isValid && isDNTemplateValid;
     }
-
     return isValid;
   }
 

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/oauth-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/oauth-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/oauth-provider-config.ts
index 777690f..b359a5d 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/oauth-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/oauth-provider-config.ts
@@ -46,8 +46,32 @@ export class OAUTHProviderConfig extends AuthenticationProviderConfig {
     return OAUTHProviderConfig.displayPropertyNameBindings.get(name);
   }
 
-  isValid(): boolean {
-    return ValidationUtils.isValidURL(this.getParam(this.getDisplayNamePropertyBinding(OAUTHProviderConfig.CALLBACK_URL)));
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
+
+    switch (paramName) {
+      case OAUTHProviderConfig.CALLBACK_URL:
+        isValid = this.isValidCallbackURL();
+        break;
+      default:
+        isValid = true;
+    }
+
+    return isValid;
+  }
+
+  private isValidCallbackURL(): boolean {
+    let isValid: boolean = true;
+
+    let url = this.getParam(this.getDisplayNamePropertyBinding(OAUTHProviderConfig.CALLBACK_URL));
+    if (url) {
+      isValid = ValidationUtils.isValidHttpURL(url);
+      if (!isValid) {
+        console.debug(OAUTHProviderConfig.CALLBACK_URL + ' value is not a valid URL.');
+      }
+    }
+
+    return isValid;
   }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/oidc-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/oidc-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/oidc-provider-config.ts
index 00528f0..49d2b4e 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/oidc-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/oidc-provider-config.ts
@@ -17,7 +17,6 @@
 
 import {AuthenticationProviderConfig} from "./authentication-provider-config";
 import {ValidationUtils} from "../utils/validation-utils";
-import {SAMLProviderConfig} from "./saml-provider-config";
 
 export class OIDCProviderConfig extends AuthenticationProviderConfig {
 
@@ -70,43 +69,65 @@ export class OIDCProviderConfig extends AuthenticationProviderConfig {
     return (name === OIDCProviderConfig.PROVIDER_SECRET);
   }
 
-  isValid(): boolean {
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
+
+    switch (paramName) {
+      case OIDCProviderConfig.CALLBACK_URL:
+      case OIDCProviderConfig.PROVIDER_DISCOVERY_URL:
+        isValid = this.isValidURL(paramName);
+        break;
+      case OIDCProviderConfig.USE_NONCE:
+        isValid = this.isValidUseNonce();
+        break;
+      case OIDCProviderConfig.MAX_CLOCK_SKEW:
+        isValid = this.isValidClockSkew();
+        break;
+      default:
+        isValid = true;
+    }
+
+    return isValid;
+  }
+
+  private isValidURL(param: string): boolean {
     let isValid: boolean = true;
 
-    let cbURL = this.getParam(this.getDisplayNamePropertyBinding(OIDCProviderConfig.CALLBACK_URL));
-    if (cbURL) {
-      let isCBURLValid = ValidationUtils.isValidURL(cbURL);
-      if (!isCBURLValid) {
-        console.debug(OIDCProviderConfig.CALLBACK_URL + ' value is not a valid URL.');
+    let url = this.getParam(this.getDisplayNamePropertyBinding(param));
+    if (url) {
+      isValid = ValidationUtils.isValidHttpURL(url);
+      if (!isValid) {
+        console.debug(param + ' value is not a valid URL.');
       }
-      isValid = isValid && isCBURLValid;
     }
 
-    let pdURL = this.getParam(this.getDisplayNamePropertyBinding(OIDCProviderConfig.PROVIDER_DISCOVERY_URL));
-    if (pdURL) {
-      let isPDURLValid = ValidationUtils.isValidURL(pdURL);
-      if (!isPDURLValid) {
-        console.debug(OIDCProviderConfig.PROVIDER_DISCOVERY_URL + ' value is not a valid URL.');
-      }
-      isValid = isValid && isPDURLValid;
-    }
+    return isValid;
+  }
+
+
+  private isValidUseNonce(): boolean {
+    let isValid: boolean = true;
 
     let useNonce = this.getParam(this.getDisplayNamePropertyBinding(OIDCProviderConfig.USE_NONCE));
     if (useNonce) {
-      let isNonceValid = ValidationUtils.isValidBoolean(useNonce);
-      if (!isNonceValid) {
+      isValid = ValidationUtils.isValidBoolean(useNonce);
+      if (!isValid) {
         console.debug(OIDCProviderConfig.USE_NONCE + ' value is not a valid boolean.');
       }
-      isValid = isValid && isNonceValid;
     }
 
+    return isValid;
+  }
+
+  private isValidClockSkew(): boolean {
+    let isValid: boolean = true;
+
     let clockSkew = this.getParam(this.getDisplayNamePropertyBinding(OIDCProviderConfig.MAX_CLOCK_SKEW));
     if (clockSkew) {
-      let isSkewValid = ValidationUtils.isValidNumber(clockSkew);
-      if (!isSkewValid) {
+      isValid = ValidationUtils.isValidNumber(clockSkew);
+      if (!isValid) {
         console.debug(OIDCProviderConfig.MAX_CLOCK_SKEW + ' value is not a valid number');
       }
-      isValid = isValid && isSkewValid;
     }
 
     return isValid;

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/pam-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/pam-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/pam-provider-config.ts
index 243a4e0..9aa05e0 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/pam-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/pam-provider-config.ts
@@ -76,10 +76,23 @@ export class PAMProviderConfig extends AuthenticationProviderConfig implements O
     return result;
   }
 
-  isValid(): boolean {
-    let isValid = true;
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
+
+    switch (paramName) {
+      case PAMProviderConfig.SESSION_TIMEOUT:
+        isValid = this.isValidTimeout();
+        break;
+      default:
+        isValid = true;
+    }
+
+    return isValid;
+  }
+
+  private isValidTimeout(): boolean {
+    let isValid: boolean = true;
 
-    // Since the other properties are set internally, just validate the session timeout value
     let timeout = this.getParam(this.getDisplayNamePropertyBinding(PAMProviderConfig.SESSION_TIMEOUT));
     if (timeout) {
       isValid = ValidationUtils.isValidNumber(timeout);

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.html
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.html b/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.html
index c6ffec8..50a470d 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.html
+++ b/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.html
@@ -92,6 +92,7 @@
                      [checked]="getPasswordDisplay(pt)"
                      (click)="togglePasswordDisplay(pt)">show
             </span>
+            <span *ngIf="!isValidParamValue(pt)" style="color: red">invalid</span>
           </td>
         </tr>
       </table>

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts b/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts
index 6fc9afe..65adb2a 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts
@@ -236,7 +236,7 @@ export class ProviderConfigWizardComponent implements OnInit {
             pc.setParam(property, value);
             console.debug('ProviderConfigWizard --> Set ProviderConfig param value: ' + property + '=' + value);
           } else {
-            console.debug('No provider property configured for ' + name);
+            console.debug('ProviderConfigWizard --> No provider property configured for ' + name);
           }
         }
       }
@@ -288,10 +288,20 @@ export class ProviderConfigWizardComponent implements OnInit {
     return result;
   }
 
+  isValidParamValue(paramName: string) {
+    let isValid: boolean = true;
+    let pc: ProviderConfig = this.getCategoryWizard().getProviderConfig();
+    if (pc) {
+      if (pc instanceof DisplayBindingProviderConfig) {
+        isValid = (pc as DisplayBindingProviderConfig).isValidParamValue(paramName);
+      }
+    }
+    return isValid;
+  }
+
   isProviderConfigValid(pc: ProviderConfig): boolean {
     let isValid: boolean = true;
     if (pc instanceof DisplayBindingProviderConfig) {
-      console.debug('Checking validity of ' + this.selectedCategory + ' ' + (pc as DisplayBindingProviderConfig).getType() + ' provider...');
       isValid = (pc as DisplayBindingProviderConfig).isValid();
     }
     return isValid;

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/regex-idassertion-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/regex-idassertion-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/regex-idassertion-provider-config.ts
index 8ca0f1f..cdf6685 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/regex-idassertion-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/regex-idassertion-provider-config.ts
@@ -51,15 +51,28 @@ export class RegexAssertionProviderConfig extends IdentityAssertionProviderConfi
     return RegexAssertionProviderConfig.displayPropertyNameBindings.get(name);
   }
 
-  isValid(): boolean {
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
+
+    switch (paramName) {
+      case RegexAssertionProviderConfig.ORIG_ON_FAIL:
+        isValid = this.isValidUseOriginal();
+        break;
+      default:
+        isValid = true;
+    }
+
+    return isValid;
+  }
+
+  private isValidUseOriginal(): boolean {
     let isValid: boolean = true;
 
     let useOrig = this.getParam(this.getDisplayNamePropertyBinding(RegexAssertionProviderConfig.ORIG_ON_FAIL));
     if (useOrig) {
       isValid = ValidationUtils.isValidBoolean(useOrig);
       if (!isValid) {
-        console.debug('RegexAssertionProviderConfig --> ' + RegexAssertionProviderConfig.ORIG_ON_FAIL +
-                      ' value is not a valid boolean.')
+        console.debug(RegexAssertionProviderConfig.ORIG_ON_FAIL + ' value is not a valid boolean.')
       }
     }
 

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/saml-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/saml-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/saml-provider-config.ts
index 139cfe8..78f7d8f 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/saml-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/saml-provider-config.ts
@@ -74,16 +74,46 @@ export class SAMLProviderConfig extends AuthenticationProviderConfig {
     return (name && SAMLProviderConfig.SECRET_PROPERTIES.indexOf(name) > -1);
   }
 
-  isValid(): boolean {
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
+
+    switch (paramName) {
+      case SAMLProviderConfig.CALLBACK_URL:
+        isValid = this.isValidCallbackURL();
+        break;
+      case SAMLProviderConfig.MAX_AUTH_LIFETIME:
+        isValid = this.isValidMaxAuthLifetime();
+        break;
+      default:
+        isValid = true;
+    }
+
+    return isValid;
+  }
+
+  private isValidCallbackURL(): boolean {
+    let isValid: boolean = true;
+
+    let url = this.getParam(this.getDisplayNamePropertyBinding(SAMLProviderConfig.CALLBACK_URL));
+    if (url) {
+      isValid = ValidationUtils.isValidHttpURL(url);
+      if (!isValid) {
+        console.debug(SAMLProviderConfig.CALLBACK_URL + ' value is not a valid URL.');
+      }
+    }
+
+    return isValid;
+  }
+
+  private isValidMaxAuthLifetime(): boolean {
     let isValid: boolean = true;
 
-    let cb = this.getParam(this.getDisplayNamePropertyBinding(SAMLProviderConfig.CALLBACK_URL));
-    if (cb) {
-      let isValidCB = ValidationUtils.isValidURL(cb);
-      if (!isValidCB) {
-        console.debug('SAMLProviderConfig --> ' + SAMLProviderConfig.CALLBACK_URL + ' value is not a valid URL.');
+    let malt = this.getParam(this.getDisplayNamePropertyBinding(SAMLProviderConfig.MAX_AUTH_LIFETIME));
+    if (malt) {
+      isValid = ValidationUtils.isValidNumber(malt);
+      if (!isValid) {
+        console.debug(SAMLProviderConfig.MAX_AUTH_LIFETIME + ' value is not a valid number.');
       }
-      isValid = isValidCB && isValidCB;
     }
 
     return isValid;

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/sso-cookie-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/sso-cookie-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/sso-cookie-provider-config.ts
index ba94197..3ec308b 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/sso-cookie-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/sso-cookie-provider-config.ts
@@ -41,7 +41,31 @@ export class SSOCookieProviderConfig extends AuthenticationProviderConfig {
     return SSOCookieProviderConfig.displayPropertyNameBindings.get(name);
   }
 
-  isValid(): boolean {
-    return ValidationUtils.isValidURL(this.getParam(this.getDisplayNamePropertyBinding(SSOCookieProviderConfig.PROVIDER_URL)));
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
+
+    switch (paramName) {
+      case SSOCookieProviderConfig.PROVIDER_URL:
+        isValid = this.isValidProviderURL();
+        break;
+      default:
+        isValid = true;
+    }
+
+    return isValid;
+  }
+
+  private isValidProviderURL(): boolean {
+    let isValid: boolean = true;
+
+    let url = this.getParam(this.getDisplayNamePropertyBinding(SSOCookieProviderConfig.PROVIDER_URL));
+    if (url) {
+      isValid = ValidationUtils.isValidHttpURL(url);
+      if (!isValid) {
+        console.debug(SSOCookieProviderConfig.PROVIDER_URL + ' value is not a valid URL.');
+      }
+    }
+    return isValid;
   }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/provider-config-wizard/switchcase-idassertion-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/switchcase-idassertion-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/switchcase-idassertion-provider-config.ts
index 3667ae0..65ac856 100644
--- a/gateway-admin-ui/src/app/provider-config-wizard/switchcase-idassertion-provider-config.ts
+++ b/gateway-admin-ui/src/app/provider-config-wizard/switchcase-idassertion-provider-config.ts
@@ -46,17 +46,30 @@ export class SwitchCaseAssertionProviderConfig extends IdentityAssertionProvider
     return SwitchCaseAssertionProviderConfig.displayPropertyNameBindings.get(name);
   }
 
-  isValid(): boolean {
-    let isValid: boolean = true;
+  isValidParamValue(paramName: string): boolean {
+    let isValid: boolean;
 
-    let pc = this.getParam(this.getDisplayNamePropertyBinding(SwitchCaseAssertionProviderConfig.PRINCIPAL_CASE));
-    if (pc) {
-      isValid = isValid && (SwitchCaseAssertionProviderConfig.CASE_VALUES.indexOf(pc.toLowerCase()) > -1);
+    switch (paramName) {
+      case SwitchCaseAssertionProviderConfig.PRINCIPAL_CASE:
+      case SwitchCaseAssertionProviderConfig.GROUP_PRINCIPAL_CASE:
+        isValid = this.isValidCase(paramName);
+        break;
+      default:
+        isValid = true;
     }
 
-    let gpc = this.getParam(this.getDisplayNamePropertyBinding(SwitchCaseAssertionProviderConfig.GROUP_PRINCIPAL_CASE));
-    if (gpc) {
-      isValid = isValid && (SwitchCaseAssertionProviderConfig.CASE_VALUES.indexOf(gpc.toLowerCase()) > -1);
+    return isValid;
+  }
+
+  private isValidCase(param: string): boolean {
+    let isValid: boolean = true;
+
+    let value = this.getParam(this.getDisplayNamePropertyBinding(param));
+    if (value) {
+      isValid = (SwitchCaseAssertionProviderConfig.CASE_VALUES.indexOf(value.toLowerCase()) > -1);
+      if (!isValid) {
+        console.debug(param + ' value is not a valid case: ' + SwitchCaseAssertionProviderConfig.CASE_VALUES.toString());
+      }
     }
 
     return isValid;

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-admin-ui/src/app/utils/validation-utils.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/utils/validation-utils.ts b/gateway-admin-ui/src/app/utils/validation-utils.ts
index f7dcfcc..a3f1707 100644
--- a/gateway-admin-ui/src/app/utils/validation-utils.ts
+++ b/gateway-admin-ui/src/app/utils/validation-utils.ts
@@ -16,6 +16,8 @@
  */
 
 
+import {CASProviderConfig} from "../provider-config-wizard/cas-provider-config";
+
 export class ParsedURL {
 
   static REGEXP: RegExp = new RegExp('^(([^:\/?#]+):)?\/\/(([^\/?#]+):([^\/?#]+))?([^?#]*)(\/?([^#]*))?(#(.*))?');
@@ -48,6 +50,25 @@ export class ParsedURL {
 
 export class ValidationUtils {
 
+  private static DN_TEMPLATE_REGEXP: RegExp =
+    new RegExp('(?:[A-Za-z][\\w-]*|\\d+(?:\\.\\d+)*)' +
+      '=(?:#(?:[\\dA-Fa-f]{2})+|(?:[^,=\\+<>#;\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*")' +
+      '(?:\\+(?:[A-Za-z][\\w-]*|\\d+(?:\\.\\d+)*)' +
+      '=(?:#(?:[\\dA-Fa-f]{2})' +
+      '+|(?:[^,=\\+<>#;\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*"))' +
+      '*(?:,(?:[A-Za-z][\\w-]*|\\d+(?:\\.\\d+)*)' +
+      '=(?:#(?:[\\dA-Fa-f]{2})+|(?:[^,=\\+<>#;\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*")' +
+      '(?:\\+(?:[A-Za-z][\\w-]*|\\d+(?:\\.\\d+)*)=(?:#(?:[\\dA-Fa-f]{2})+|(?:[^,=\\+<>#;\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\\+<>#;\\"]|\\[\\dA-Fa-f]{2})*"))*)*');
+
+
+  private static PRINCIPAL_MAPPING_REGEXP = new RegExp('^(?:(?:[a-zA-Z\\*]+[\\,]?)+=[a-zA-Z]+[;]?)*$');
+
+  static LDAP_URL_SCHEMES: string[] = [ 'ldap', 'ldaps' ];
+
+  static HTTP_URL_SCHEMES: string[] = [ 'http', 'https' ];
+
+  static CAS_PROTOCOLS: string[] = [ 'CAS10', 'CAS20', 'CAS20_PROXY', 'CAS30', 'CAS30_PROXY', 'SAML' ];
+
 
   static parseBoolean(value: string): boolean {
     let parsed: boolean;
@@ -132,4 +153,35 @@ export class ValidationUtils {
     return isValid;
   }
 
+  static isValidLdapURL(url: string): boolean {
+    return ValidationUtils.isValidURLOfScheme(url, ValidationUtils.LDAP_URL_SCHEMES);
+  }
+
+  static isValidHttpURL(url: string): boolean {
+    return ValidationUtils.isValidURLOfScheme(url, ValidationUtils.HTTP_URL_SCHEMES);
+  }
+
+  static isValidDNTemplate(dnTemplate: string): boolean {
+    return ValidationUtils.DN_TEMPLATE_REGEXP.test(dnTemplate);
+  }
+
+  static isValidCASProtocol(protocol: string): boolean {
+    let isValid: boolean = false;
+
+    if (protocol) {
+      isValid = (ValidationUtils.CAS_PROTOCOLS.indexOf(protocol) > -1);
+    }
+
+    return isValid;
+  }
+
+  static isValidPrincipalMapping(mapping: string): boolean {
+    let isValid: boolean = false;
+
+    if (mapping) {
+      isValid = ValidationUtils.PRINCIPAL_MAPPING_REGEXP.test(mapping)
+    }
+
+    return isValid;
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
----------------------------------------------------------------------
diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
index 52a28a4..e7a9514 100644
--- a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
+++ b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
@@ -11,4 +11,4 @@
   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.
---><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox Manager</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Custom styles for this template --><link href="assets/sticky-footer.css" rel="stylesheet"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script><!-- Latest compiled and minified JavaScript --><scr
 ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><script src="assets/vkbeautify.js"></script><link href="styles.2ee5b7f4cd59a6cf015e.bundle.css" rel="stylesheet"/></head><body><div class="navbar-wrapper"><div class="container-fluid"><nav class="navbar navbar-inverse navbar-static-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img style="max-width:200px; margin-top: -9px;" src="assets/knox-logo-transparent.gif" alt="Apache Knox Manager"></a></div></div></nav></div><!-- Content --><resource-management></res
 ource-management><footer class="footer"><div class="container-fluid"><div>Knox Manager Version 0.1.0</div><gateway-version></gateway-version></div></footer><script type="text/javascript" src="inline.0c599dd7846e2462c94c.bundle.js"></script><script type="text/javascript" src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script type="text/javascript" src="main.bfb4b6a3d7d72f4c8841.bundle.js"></script></div></body></html>
\ No newline at end of file
+--><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox Manager</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Custom styles for this template --><link href="assets/sticky-footer.css" rel="stylesheet"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script><!-- Latest compiled and minified JavaScript --><scr
 ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><script src="assets/vkbeautify.js"></script><link href="styles.2ee5b7f4cd59a6cf015e.bundle.css" rel="stylesheet"/></head><body><div class="navbar-wrapper"><div class="container-fluid"><nav class="navbar navbar-inverse navbar-static-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img style="max-width:200px; margin-top: -9px;" src="assets/knox-logo-transparent.gif" alt="Apache Knox Manager"></a></div></div></nav></div><!-- Content --><resource-management></res
 ource-management><footer class="footer"><div class="container-fluid"><div>Knox Manager Version 0.1.0</div><gateway-version></gateway-version></div></footer><script type="text/javascript" src="inline.a7f3e89f1023e555e44a.bundle.js"></script><script type="text/javascript" src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script type="text/javascript" src="main.743b2fb8ac3467eb4d6e.bundle.js"></script></div></body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-applications/src/main/resources/applications/admin-ui/app/inline.0c599dd7846e2462c94c.bundle.js
----------------------------------------------------------------------
diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.0c599dd7846e2462c94c.bundle.js b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.0c599dd7846e2462c94c.bundle.js
deleted file mode 100644
index 074de3a..0000000
--- a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.0c599dd7846e2462c94c.bundle.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=o(o.s=u[l]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute("nonce",o.nc),u.src=o.p+""+e+"."+{0:"bfb4b6a3d7d72f4c8841",1:"aed76669724804835353"}[e]+".chunk.js";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chu
 nk "+e+" failed.")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw console.error(e),e}}([]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/2e8716d8/gateway-applications/src/main/resources/applications/admin-ui/app/inline.a7f3e89f1023e555e44a.bundle.js
----------------------------------------------------------------------
diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.a7f3e89f1023e555e44a.bundle.js b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.a7f3e89f1023e555e44a.bundle.js
new file mode 100644
index 0000000..a852b61
--- /dev/null
+++ b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.a7f3e89f1023e555e44a.bundle.js
@@ -0,0 +1 @@
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=o(o.s=u[l]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute("nonce",o.nc),u.src=o.p+""+e+"."+{0:"743b2fb8ac3467eb4d6e",1:"aed76669724804835353"}[e]+".chunk.js";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chu
 nk "+e+" failed.")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw console.error(e),e}}([]);
\ No newline at end of file