Uploaded image for project: 'Keycloak'
  1. Keycloak
  2. KEYCLOAK-12221

Scripts unable to phrase user, throws typeerror

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Minor
    • Resolution: Done
    • Affects Version/s: 8.0.0
    • Fix Version/s: 8.0.2
    • Component/s: Authentication
    • Labels:
      None
    • Steps to Reproduce:
      Hide

      Use the following script, and make it a required flow in a browser auth flow.
      I use keyclock-gatekeeper as a proxy for the service, using a client that uses the auth flow with the script. Pictures attached to help a little, as I'm sure I'm not using the right words for the flow stuff.

      Script:

      /*
       * Template for JavaScript based authenticator's.
       * See org.keycloak.authentication.authenticators.browser.ScriptBasedAuthenticatorFactory
       */
      
      // import enum for error lookup
      AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");
      
      /**
       * An example authenticate function.
       *
       * The following variables are available for convenience:
       * user - current user {@see org.keycloak.models.UserModel}
       * realm - current realm {@see org.keycloak.models.RealmModel}
       * session - current KeycloakSession {@see org.keycloak.models.KeycloakSession}
       * httpRequest - current HttpRequest {@see org.jboss.resteasy.spi.HttpRequest}
       * script - current script {@see org.keycloak.models.ScriptModel}
       * authenticationSession - current authentication session {@see org.keycloak.sessions.AuthenticationSessionModel}
       * LOG - current logger {@see org.jboss.logging.Logger}
       *
       * You one can extract current http request headers via:
       * httpRequest.getHttpHeaders().getHeaderString("Forwarded")
       *
       * @param context {@see org.keycloak.authentication.AuthenticationFlowContext}
       */
      function authenticate(context) {
          
          var rolename = 'alteria_admins';
          var username = user ? user.username : "anonymous";
          //var realmRole1 = session.getContext().getRealm().getRole("alteria_admins");
          //LOG.info(script.name + " trace auth for: " + username + " Role found?:" + realmRole);
          var rrole = realm.getRole(rolename);
          
          if (rrole === null) {
              LOG.debug(script.name + "ERROR: No '" + rolename + "' for realm '" + realm.getName() + "' found.");
          }
          
          if (user.hasRole(rrole)){
              return context.success();
          }
      
          context.failure(AuthenticationFlowError.INVALID_USER);
          //return;
          //return denyAccess(context, rrole);
      }
      
      function denyAccess(context, rrole) {
          var formBuilder = context.form();
          var client = session.getContext().getClient();
          var description = !rrole.getAttribute('deniedMessage').isEmpty() ? rrole.getAttribute('deniedMessage') : ['Access Denied'];
          var form = formBuilder
              .setAttribute('clientUrl', client.getRootUrl())
              .setAttribute('clientName', client.getName())
              .setAttribute('description', description[0])
              .createForm('denied-auth.ftl');
          return context.failure(AuthenticationFlowError.INVALID_USER, form);
       }
      
      Show
      Use the following script, and make it a required flow in a browser auth flow. I use keyclock-gatekeeper as a proxy for the service, using a client that uses the auth flow with the script. Pictures attached to help a little, as I'm sure I'm not using the right words for the flow stuff. Script: /* * Template for JavaScript based authenticator's. * See org.keycloak.authentication.authenticators.browser.ScriptBasedAuthenticatorFactory */ // import enum for error lookup AuthenticationFlowError = Java.type( "org.keycloak.authentication.AuthenticationFlowError" ); /** * An example authenticate function. * * The following variables are available for convenience: * user - current user {@see org.keycloak.models.UserModel} * realm - current realm {@see org.keycloak.models.RealmModel} * session - current KeycloakSession {@see org.keycloak.models.KeycloakSession} * httpRequest - current HttpRequest {@see org.jboss.resteasy.spi.HttpRequest} * script - current script {@see org.keycloak.models.ScriptModel} * authenticationSession - current authentication session {@see org.keycloak.sessions.AuthenticationSessionModel} * LOG - current logger {@see org.jboss.logging.Logger} * * You one can extract current http request headers via: * httpRequest.getHttpHeaders().getHeaderString( "Forwarded" ) * * @param context {@see org.keycloak.authentication.AuthenticationFlowContext} */ function authenticate(context) { var rolename = 'alteria_admins' ; var username = user ? user.username : "anonymous" ; // var realmRole1 = session.getContext().getRealm().getRole( "alteria_admins" ); //LOG.info(script.name + " trace auth for : " + username + " Role found?:" + realmRole); var rrole = realm.getRole(rolename); if (rrole === null ) { LOG.debug(script.name + "ERROR: No '" + rolename + "' for realm '" + realm.getName() + "' found." ); } if (user.hasRole(rrole)){ return context.success(); } context.failure(AuthenticationFlowError.INVALID_USER); // return ; // return denyAccess(context, rrole); } function denyAccess(context, rrole) { var formBuilder = context.form(); var client = session.getContext().getClient(); var description = !rrole.getAttribute( 'deniedMessage' ).isEmpty() ? rrole.getAttribute( 'deniedMessage' ) : [ 'Access Denied' ]; var form = formBuilder .setAttribute( 'clientUrl' , client.getRootUrl()) .setAttribute( 'clientName' , client.getName()) .setAttribute( 'description' , description[0]) .createForm( 'denied-auth.ftl' ); return context.failure(AuthenticationFlowError.INVALID_USER, form); }
    • Docs QE Status:
      NEW
    • QE Status:
      NEW

      Description

      I have a script I use for my admin backends. It checks a user has a certain role and if they do, then grant auth tokens.
      As of Keycloak 8.0.0, the script throws the following error:

      [0m[31m15:09:42,996 ERROR [org.keycloak.authentication.authenticators.browser.ScriptBasedAuthenticator] (default task-32) org.keycloak.scripting.ScriptExecutionException: Could not execute script 'admin' problem was: TypeError: null has no such function "hasRole" in <eval> at line number 38
      

      As a result, my admin backends are now un-accessible.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              mposolda Marek Posolda
              Reporter:
              ryonez Ryonez Coruscare (Inactive)
              Votes:
              2 Vote for this issue
              Watchers:
              6 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: