How to call API Gateway with Cognito Credentials through retrofit2 on Android?

后端 未结 3 977
傲寒
傲寒 2020-12-30 11:32

I use retrofit2 in my android apps for any http/rest call. Now I need to call an api generated with Amazon AWS API Gateway.

The AWS documentation say I

3条回答
  •  孤城傲影
    2020-12-30 11:55

    It took me several days to figure out how to make it work. Don't know why they don't point out the class instead of dozen of document pages. There are 4 steps in total, you must call in worker thread, I am using Rxjava but you can use AsyncTask instead:

        Observable.create((Observable.OnSubscribe) subscriber -> {
    //Step 1: Get credential, ask server team for Identity pool id and regions            
    CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
                    this, // Context
                    "Identity Pool ID", // Identity Pool ID
                    Regions.US_EAST_1 // Region
                );
    
    //Step 2: Get these 3 three keys, test with postman v4.9.3 to see if identity is correct  
                String identityId = credentialsProvider.getIdentityId();
                Log.show("identityId = " + identityId);
    
                String AccessKey = credentialsProvider.getCredentials().getAWSAccessKeyId();
                String SecretKey = credentialsProvider.getCredentials().getAWSSecretKey();
                String SessionKey = credentialsProvider.getCredentials().getSessionToken();
    
                Log.show("AccessKey = " + AccessKey);
                Log.show("SecretKey = " + SecretKey);
                Log.show("SessionKey = " + SessionKey);
    //Step 3: Create an aws requets and sign by using AWS4Signer class
                AmazonWebServiceRequest amazonWebServiceRequest = new AmazonWebServiceRequest() {
                };
    
                ClientConfiguration clientConfiguration = new ClientConfiguration();
    
                String API_GATEWAY_SERVICE_NAME = "execute-api";
    
                Request request = new DefaultRequest(amazonWebServiceRequest,API_GATEWAY_SERVICE_NAME);
                request.setEndpoint(URI.create("YOUR_URI"));
                request.setHttpMethod(HttpMethodName.GET);
    
                AWS4Signer signer = new AWS4Signer();
                signer.setServiceName(API_GATEWAY_SERVICE_NAME);
                signer.setRegionName(Region.getRegion(Regions.US_EAST_1).getName());
                signer.sign(request, credentialsProvider.getCredentials());
    
                Log.show("Request header " + request.getHeaders().toString());
    //Step 4: Create new request with authorization headers 
    
                OkHttpClient httpClient = new OkHttpClient();
                Map headers = request.getHeaders();
                List key = new ArrayList();
                List value = new ArrayList();
    
                for (Map.Entry entry : headers.entrySet())
                {
                    key.add(entry.getKey());
                    value.add(entry.getValue());
                }
    
                try {
                    okhttp3.Request request2 = new okhttp3.Request.Builder()
                            .url("Your_url") // remember to add / to the end of the url, otherwise the signature will be different 
                            .addHeader(key.get(0), value.get(0))
                            .addHeader(key.get(1), value.get(1))
                            .addHeader(key.get(2), value.get(2))
                            .addHeader(key.get(3), value.get(3))
    
                            .addHeader("Content-Type", "application/x-www-form-urlencoded")
                            .build();
                    Response response = null;
    
                    response = httpClient.newCall(request2).execute();
                    String body = response.body().string();
                    Log.show("response " + body);
                } catch (Exception e) {
                    Log.show("error " + e);
                }
    
                subscriber.onNext(identityId);
    
            }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() {
                @Override
                public void onCompleted() {
    
                }
    
                @Override
                public void onError(Throwable e) {
                    Log.show("Throwable = " + e.getMessage());
                }
    
                @Override
                public void onNext(String s) {
    
                }
            });
    

    The key here is the AWS4Signer class does 4 steps as documented here, you don't need to build one from scratch. In order to use AWS4Signer and AmazonWebServiceRequest, you need to import aws sdk in gradle:

    compile 'com.amazonaws:aws-android-sdk-cognito:2.3.9'
    

提交回复
热议问题