aws-amplify / amplify-android

The fastest and easiest way to use AWS from your Android app.
https://docs.amplify.aws/lib/q/platform/android/
Apache License 2.0
245 stars 115 forks source link

Pass Custom Header through AWSApiPlugin #1178

Closed meenakshi-rai closed 3 years ago

meenakshi-rai commented 3 years ago

Problem Statment

I am trying to pass external “accessToken” as header with each Amplify GraphQL API call while using Android Amplify SDK, and I need help with a solution for this.

Build gradle library version

dependencies {
    implementation 'com.amplifyframework:core:1.16.12'
    implementation 'com.amplifyframework:aws-api:1.16.12'
}

Code Used

val awsApiPlugin = AWSApiPlugin()
Amplify.addPlugin(awsApiPlugin)
Amplify.configure(applicationContext)

Looking for something similar to iOS Solution

When I use the iOS counterpart of Android Amplify API SDK, while configuring the API, I get an option with AWSAPIPlugin extension to add a custom interceptor using protocol URLRequestInterceptor. With the help of this cusomt URLRequestInterceptor I can pass “accessToken” as header, which is automatically consumed with each GraphQL API call, and I am trying to find something similar in Android

iOS Library Link

https://github.com/aws-amplify/amplify-ios

Podfile libraries version

pod 'Amplify', '~> 1.6.0'
pod 'AmplifyPlugins/AWSAPIPlugin', '~> 1.6.0'

Code Used

Code example used for iOS, where I created a CustomURLRequestInterceptor implementing URLRequestInterceptor which contains code for me to add headers as required.

val apiPlugin = try AWSAPIPlugin()
try Amplify.configure()
try apiPlugin.add(interceptor: CustomURLRequestInterceptor(), for: "<Api Name>")

// Custom CustomURLRequestInterceptor used to pass header with each graphQL API requests
struct CustomURLRequestInterceptor: URLRequestInterceptor {
    func intercept(_ request: URLRequest) throws -> URLRequest {

        guard let mutableRequest = (request as NSURLRequest).mutableCopy() as? NSMutableURLRequest else {
            throw APIError.unknown("Could not get mutable request", "")
        }
        mutableRequest.setValue("abcdefgh-abcd-abcd-abcd-abcdefghijkl", forHTTPHeaderField: "accessToken")
        return mutableRequest as URLRequest
    }
}
richardmcclellan commented 3 years ago

HI @meenakshi-rai, if you are using a 3rd party OIDC provider (if so, your amplifyconfiguration.json will have "authorizationType": "OPENID_CONNECT") , you can specify an auth provider for the AWSApiPlugin to use, like this:

val authProviders = ApiAuthProviders.builder()
    .oidcAuthProvider { "[OPEN-ID-CONNECT-TOKEN]" }
    .build()
Amplify.addPlugin(AWSApiPlugin(authProviders))

Here is the full documentation: https://docs.amplify.aws/lib/graphqlapi/authz/q/platform/android

This results in an Authorization header being included on each AppSync request. Will this solution meet your use case?

meenakshi-rai commented 3 years ago

HI @meenakshi-rai, if you are using a 3rd party OIDC provider (if so, your amplifyconfiguration.json will have "authorizationType": "OPENID_CONNECT") , you can specify an auth provider for the AWSApiPlugin to use, like this:

val authProviders = ApiAuthProviders.builder()
    .oidcAuthProvider { "[OPEN-ID-CONNECT-TOKEN]" }
    .build()
Amplify.addPlugin(AWSApiPlugin(authProviders))

Here is the full documentation: https://docs.amplify.aws/lib/graphqlapi/authz/q/platform/android

This results in an Authorization header being included on each AppSync request. Will this solution meet your use case?

Hi @richardmcclellan it is not just about Authorization header only, but I am trying to pass additional header (custom) with each graphQL API request, to meet our functional request.

Also for Auth I am looking to integrate IAM as authorization type, and make auth request as Unauthenticated Requests using CredentialProvider. Something similar to this article content, but using Amplify https://docs.aws.amazon.com/cognito/latest/developerguide/getting-credentials.html

richardmcclellan commented 3 years ago

Hi @meenakshi-rai, adding any random header to the request is not currently supported. Can you share more details about your use case? What does your backend architecture look like? What system is going to be expecting/processing this "accessToken" header?

meenakshi-rai commented 3 years ago

Hi @meenakshi-rai, adding any random header to the request is not currently supported. Can you share more details about your use case? What does your backend architecture look like? What system is going to be expecting/processing this "accessToken" header?

Hi @richardmcclellan

NOTE

jamesonwilliams commented 3 years ago

Hi @meenakshi-rai! Given that iOS provides an URLRequestInterceptor, I think it makes for Android to add some similar functionality.

I'm currently looking at ways to do this. We hope to have a solution for you soon.

jamesonwilliams commented 3 years ago

Our team has reviewed a design to support this functionality. #1207 (referenced above) adds support.

With it, a customer can add customizations to the underlying OkHttp instance(s) while setting up the plugin.

Specifically, to add some custom request headers, you can do:

AWSApiPlugin plugin = AWSApiPlugin.builder()
    .customizeClient("apiName", okHttpClientBuilder -> {
        okHttpClientBuilder.addInterceptor(chain -> {
            return chain.proceed(chain.request()
                .newBuilder()
                .addHeader("accessToken", getCustomAccessToken())
                .build();
            );
        });
    })
    .build();

We hope to release this functionality soon.

jamesonwilliams commented 3 years ago

Resolved in 1.17.0.

ethanonfire commented 3 months ago

can't find the method customizeClient in 1.17.0 or anywhere, are you sure it is not configureClient? @jamesonwilliams

jamesonwilliams commented 3 months ago

@ethanonfire ah yes you're right, this comment contains an error, the API is called configureClient

https://github.com/aws-amplify/amplify-android/blame/e1818755c4efc9215453726dcb239da01da91b3a/aws-api/src/main/java/com/amplifyframework/api/aws/AWSApiPlugin.java#L931