Forum Discussion

davecoleman's avatar
davecoleman
Contributor
5 years ago

OAuth 2.0 Token request automation - stop request of new token after each REST Request run

Hi all,

I currently am running a Functional suite of tests (7 GET methods) which form the basis of a Load Test (LoadUI).

I have implemented OAuth automation as per here https://support.smartbear.com/readyapi/docs/requests/auth/types/oauth2/automate/sample.html#calling-the-automated-retrieval-procedure

and this script

// Import the required classes
import com.eviware.soapui.impl.rest.actions.oauth.OltuOAuth2ClientFacade
import com.eviware.soapui.support.editor.inspectors.auth.TokenType
import com.eviware.soapui.model.support.ModelSupport


def authType = submit.getRequest().getAuthType()
if(authType == "OAuth 2.0"){ // Set up variables
def authProfileName = submit.getRequest().getActiveAuthProfile().getName() def project = ModelSupport.getModelItemProject(context.getModelItem()) def authProfile = project.getAuthRepository().getEntry(authProfileName) def oldToken = authProfile.getAccessToken() def tokenType = TokenType.ACCESS // Create a facade object def oAuthFacade = new OltuOAuth2ClientFacade(tokenType) // Request an access token in headless mode oAuthFacade.requestAccessToken(authProfile, true, true) // Wait until the access token gets updated //while(oldToken == authProfile.getAccessToken()) {} //The sleep method can be used instead of a while loop //sleep(3000) for(int i = 0; i<=3000; i++){ if(oldToken != authProfile.getAccessToken()){ break } sleep(1) } // Post the info to the log //log.info("Set new token: " + authProfile.getAccessToken()) }

this completes what we need; it get a token on first run of the Test Suite / case

but we are now having the following issue;

  1. 1. Requests new token.
  2. 2. Run request in test
  3. 3. Requests new token
  4. 4. Run next request in test
  5. 5. repeat

This means our keycloak server is taking the same hits as our Application server in the Webservice environment.

 

Does any have a script available to check for a new Token every 60 seconds ?

Or a script to check the existing token to see if it is expired?

  • Unfortunately this script calls for a token before each request (in a Load test, it brought down our Keycloak server and not the intended app server!)

     

    What worked for us is the following script. 

    You need to add the jjwt library to Ready API to use it. You can download it here https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt/0.9.1 and just copy it to the bin/ext folder of your Ready API install directory.

    // Import the required classes
    import com.eviware.soapui.impl.rest.actions.oauth.OltuOAuth2ClientFacade;
    import com.eviware.soapui.support.editor.inspectors.auth.TokenType;
    import com.eviware.soapui.model.support.ModelSupport;
    import io.jsonwebtoken.*;

    // Set up variables
    def project = ModelSupport.getModelItemProject(context.getModelItem());
    def authProfile = project.getAuthRepository().getEntry("TEST_ENV");
    def oldToken = authProfile.getAccessToken();
    def tokenType = TokenType.ACCESS;

    // Create a facade object
    def oAuthFacade = new OltuOAuth2ClientFacade(tokenType);

    def currentTimePlus3min = new Date(System.currentTimeMillis() + 180 * 1000);
    def expiry;

    try{
    def index = oldToken.lastIndexOf('.')
    def withoutSignature = oldToken.substring(0, index+1);
    expiry = Jwts.parser().parse(withoutSignature).getBody().getExpiration();
    }catch(e){
    expiry = new Date(System.currentTimeMillis());;
    }

    log.info("Token Expiry"+expiry+" "+ "currentTimePlus3min"+ currentTimePlus3min);

    //If the Token will expire in the next 3 minuites get a new token
    if(currentTimePlus3min > expiry ){

    // Request an access token in headless mode
    oAuthFacade.requestAccessToken(authProfile, true, true);

    // Wait until the access token gets updated
    //while(oldToken == authProfile.getAccessToken()) {}
    //The sleep method can be used instead of a while loop
    //sleep(3000);
    for(int i = 0; i<=3000; i++){
    if(oldToken != authProfile.getAccessToken()){
    break
    }
    sleep(1)
    }

    // Post the info to the log
    log.info("Set new token: " + authProfile.getAccessToken());
    }

    Hope this helps someone else. it will request a new token every 3 minutes.

    • sonya_m's avatar
      sonya_m
      SmartBear Alumni (Retired)

      Hi davecoleman ,

       

      It looks like this script does what you need:

      https://support.smartbear.com/readyapi/docs/requests/auth/types/oauth2/automate/sample.html#calling-the-automated-retrieval-procedure

       

      It checks whether an access token is up-to-date and retrieves a new one if necessary.

       

      This script needs to be placed into event handlers >> to call the update script when needed, for example, before each request is made or before project execution starts. For better stability, we recommend that you use the SubmitListener.beforeSubmit event that will execute the code before the request body is formed.<<

      • davecoleman's avatar
        davecoleman
        Contributor

        Unfortunately this script calls for a token before each request (in a Load test, it brought down our Keycloak server and not the intended app server!)

         

        What worked for us is the following script. 

        You need to add the jjwt library to Ready API to use it. You can download it here https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt/0.9.1 and just copy it to the bin/ext folder of your Ready API install directory.

        // Import the required classes
        import com.eviware.soapui.impl.rest.actions.oauth.OltuOAuth2ClientFacade;
        import com.eviware.soapui.support.editor.inspectors.auth.TokenType;
        import com.eviware.soapui.model.support.ModelSupport;
        import io.jsonwebtoken.*;

        // Set up variables
        def project = ModelSupport.getModelItemProject(context.getModelItem());
        def authProfile = project.getAuthRepository().getEntry("TEST_ENV");
        def oldToken = authProfile.getAccessToken();
        def tokenType = TokenType.ACCESS;

        // Create a facade object
        def oAuthFacade = new OltuOAuth2ClientFacade(tokenType);

        def currentTimePlus3min = new Date(System.currentTimeMillis() + 180 * 1000);
        def expiry;

        try{
        def index = oldToken.lastIndexOf('.')
        def withoutSignature = oldToken.substring(0, index+1);
        expiry = Jwts.parser().parse(withoutSignature).getBody().getExpiration();
        }catch(e){
        expiry = new Date(System.currentTimeMillis());;
        }

        log.info("Token Expiry"+expiry+" "+ "currentTimePlus3min"+ currentTimePlus3min);

        //If the Token will expire in the next 3 minuites get a new token
        if(currentTimePlus3min > expiry ){

        // Request an access token in headless mode
        oAuthFacade.requestAccessToken(authProfile, true, true);

        // Wait until the access token gets updated
        //while(oldToken == authProfile.getAccessToken()) {}
        //The sleep method can be used instead of a while loop
        //sleep(3000);
        for(int i = 0; i<=3000; i++){
        if(oldToken != authProfile.getAccessToken()){
        break
        }
        sleep(1)
        }

        // Post the info to the log
        log.info("Set new token: " + authProfile.getAccessToken());
        }

        Hope this helps someone else. it will request a new token every 3 minutes.