javaamazon-web-servicesamazon-cognitoaws-java-sdksrp-protocol

Cognito SRP Authentication JAVA SDK


Iam trying to authenticate a Java app with Cognito. I have used for python the warrant library that worked very good. But i want to do the same in java now.

My Python function i used for authentication with the warrant library

def SRPauthentication(organizationAdmin,
                     password,
                     pool_id,
                     client_id,
                     client):
    aws = AWSSRP(username=organizationAdmin,
                 password=password,
                 pool_id=pool_id,
                 client_id=client_id,
                 client=client)
    tokens = aws.authenticate_user()
    authorization_token= tokens['AuthenticationResult']['IdToken']
    return authorization_token 

with this i could easily acces some secured APIs. Now i want to do the same with Java but i have problems.

This is my solution so far is this method:

  public static void GetCreds()
      {

          AWSCognitoIdentityProvider identityProvider = AWSCognitoIdentityProviderClientBuilder.defaultClient();
          AdminInitiateAuthRequest adminInitiateAuthRequest = new AdminInitiateAuthRequest().
                  withAuthFlow(AuthFlowType.USER_SRP_AUTH).
                  withClientId("234234234234").withUserPoolId("eu-central-1_sdfsdfdsf")
                  .addAuthParametersEntry("USERNAME", "UserK").
                   addAuthParametersEntry("PASSWORD","#######);

          adminInitiateAuthRequest.getAuthFlow();
          AdminInitiateAuthResult adminInitiateAuth = identityProvider.adminInitiateAuth(adminInitiateAuthRequest);
            System.out.println(adminInitiateAuth.getAuthenticationResult().getIdToken());
      }

When i run this i get an Exception:

Exception in thread "main" `com.amazonaws.services.cognitoidp.model.AWSCognitoIdentityProviderException: User: arn:aws:iam::XXXXXXXXXXXXXXXXX:user/khan is not authorized to perform: cognito-idp:AdminInitiateAuth on resource: arn:aws:cognito-idp:eu-central-1:XXXXXXXX:userpool/eu-central-1_XXXXXXX with an explicit deny (Service: AWSCognitoIdentityProvider; Status Code: 400; Error Code: AccessDeniedException; Request ID: 21be0b8e-adec-11e8-ad45-234234234)`

It says iam not authorized to perform this kind of instruction. So i guess iam doing something generally wrong. Because its working with my python code and in Java it recognizes my username from the credentials. The Cognito call should actually be independent from my aws credentials/useraccount right?

How to authenticate with Cognito using Java to get an Token to access secured aws services?

EDIT:

  AWSCognitoIdentityProvider identityProvider = AWSCognitoIdentityProviderClientBuilder.standard()
              .build();
      InitiateAuthRequest adminInitiateAuthRequest = new InitiateAuthRequest()
              .withAuthFlow(AuthFlowType.USER_SRP_AUTH)
              .withClientId("XXXXXXXXXXXXXXXXX")
              .addAuthParametersEntry("USERNAME", "user").
               addAuthParametersEntry("PASSWORD","za$Lwn")
              .addAuthParametersEntry("SRP_A",new AuthenticationHelper("eu-central-1XXXXXXXXX").getA().toString(16));

      adminInitiateAuthRequest.getAuthFlow();
      InitiateAuthResult adminInitiateAuth = identityProvider.initiateAuth(adminInitiateAuthRequest);
      System.out.println(adminInitiateAuth);

I changed the AdminInitateAuthRequest to InitateAuthRequest. After that i had the Error missing SRP_A parameter that i somehow fixed with a similiar question here And now i recive this :

{ChallengeName: PASSWORD_VERIFIER,ChallengeParameters: {SALT=877734234324234ed68300f39bc5b, SECRET_BLOCK=lrkwejrlewrjlewkjrewlrkjwerlewkjrewlrkjewrlkewjrlewkrjZ+Q==, USER_ID_FOR_SRP=user, USERNAME=user, SRP_B=43ecc1lwkerjwelrkjewlrjewrlkewjrpoipweoriwe9r873jr34h9r834hr3455f7d079d71e5012f1623ed54dd10b832792dafa3438cca3f59c0f462cbaee255d5b7c2werwerwerkjweorkjwerwerewrf5020e4f8b5452f3b89caef4a797456743602b80b5259261f90e52374adc06b456521a9026cce9c1cbe8b9ffd6040e8c1589d35546861422110ac7e38c1c93389b802a03e3e2e4a50e75d088275195f836f66e25f1a431dd56bb2},}

I have shorten the result with all the keys, but what to do next ?


Solution

  • Finally i could solve it with this code class. There are multiple challenges involved in SRP authentication. The InitiateAuthRequest is one first request that is necessary.

    This similiar question helped me : stackoverflow stackoverfow

    String PerformSRPAuthentication(String username, String password) {
        String authresult = null;
    
        InitiateAuthRequest initiateAuthRequest = initiateUserSrpAuthRequest(username);
        try {
            AnonymousAWSCredentials awsCreds = new AnonymousAWSCredentials();
            AWSCognitoIdentityProvider cognitoIdentityProvider = AWSCognitoIdentityProviderClientBuilder
                    .standard()
                    .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                    .withRegion(Regions.fromName(this.region))
                    .build();
            InitiateAuthResult initiateAuthResult = cognitoIdentityProvider.initiateAuth(initiateAuthRequest);
            if (ChallengeNameType.PASSWORD_VERIFIER.toString().equals(initiateAuthResult.getChallengeName())) {
                RespondToAuthChallengeRequest challengeRequest = userSrpAuthRequest(initiateAuthResult, password);
                RespondToAuthChallengeResult result = cognitoIdentityProvider.respondToAuthChallenge(challengeRequest);
                //System.out.println(result);
                System.out.println(CognitoJWTParser.getPayload(result.getAuthenticationResult().getIdToken()));
                authresult = result.getAuthenticationResult().getIdToken();
            }
        } catch (final Exception ex) {
            System.out.println("Exception" + ex);
    
        }
        return authresult;
    }
    
    
     private InitiateAuthRequest initiateUserSrpAuthRequest(String username) {
    
        InitiateAuthRequest initiateAuthRequest = new InitiateAuthRequest();
        initiateAuthRequest.setAuthFlow(AuthFlowType.USER_SRP_AUTH);
        initiateAuthRequest.setClientId(this.clientId);
        //Only to be used if the pool contains the secret key.
        //initiateAuthRequest.addAuthParametersEntry("SECRET_HASH", this.calculateSecretHash(this.clientId,this.secretKey,username));
        initiateAuthRequest.addAuthParametersEntry("USERNAME", username);
        initiateAuthRequest.addAuthParametersEntry("SRP_A", this.getA().toString(16));
        return initiateAuthRequest;
    }