|
29 | 29 | import com.amplifyframework.core.Amplify; |
30 | 30 | import com.amplifyframework.logging.Logger; |
31 | 31 |
|
| 32 | +import com.amazonaws.auth.AWSCredentialsProvider; |
| 33 | +import com.amazonaws.mobile.client.AWSMobileClient; |
| 34 | + |
32 | 35 | import java.util.Objects; |
33 | 36 |
|
34 | 37 | import okhttp3.Request; |
|
38 | 41 | */ |
39 | 42 | public final class ApiRequestDecoratorFactory { |
40 | 43 | private static final Logger LOG = Amplify.Logging.forNamespace("amplify:aws-api"); |
| 44 | + private static final String AUTH_DEPENDENCY_PLUGIN_KEY = "awsCognitoAuthPlugin"; |
41 | 45 | private static final RequestDecorator NO_OP_REQUEST_DECORATOR = new RequestDecorator() { |
42 | 46 | @Override |
43 | 47 | public Request decorate(Request request) { |
@@ -103,49 +107,62 @@ public RequestDecorator fromGraphQLRequest(GraphQLRequest<?> graphQLRequest) thr |
103 | 107 | * @return the appropriate request decorator for the given authorization type. |
104 | 108 | */ |
105 | 109 | private RequestDecorator forAuthType(@NonNull AuthorizationType authorizationType) throws ApiException { |
106 | | - if (AuthorizationType.AMAZON_COGNITO_USER_POOLS.equals(authorizationType)) { |
107 | | - // Note that if there was no user-provided cognito provider passed in to initialize |
108 | | - // the API plugin, we will try to default to using the DefaultCognitoUserPoolsAuthProvider. |
109 | | - // If that fails, we then have no choice but to bubble up the error. |
110 | | - CognitoUserPoolsAuthProvider cognitoUserPoolsAuthProvider = |
111 | | - apiAuthProviders.getCognitoUserPoolsAuthProvider() != null ? |
112 | | - apiAuthProviders.getCognitoUserPoolsAuthProvider() : |
113 | | - new DefaultCognitoUserPoolsAuthProvider(); |
114 | | - // By calling getLatestAuthToken() here instead of inside the lambda block, makes the exception |
115 | | - // handling a little bit cleaner. If getLatestAuthToken() is called from inside the lambda expression |
116 | | - // below, we'd have to surround it with a try catch. By doing it this way, if there's a problem, |
117 | | - // the ApiException will just be bubbled up. Same for OPENID_CONNECT. |
118 | | - final String token = cognitoUserPoolsAuthProvider.getLatestAuthToken(); |
119 | | - return new JWTTokenRequestDecorator(() -> token); |
120 | | - } else if (AuthorizationType.OPENID_CONNECT.equals(authorizationType)) { |
121 | | - if (apiAuthProviders.getOidcAuthProvider() == null) { |
122 | | - throw new ApiException("Attempting to use OPENID_CONNECT authorization " + |
123 | | - "without an OIDC provider.", |
124 | | - "Configure an OidcAuthProvider when initializing the API plugin."); |
125 | | - } |
126 | | - final String token = apiAuthProviders.getOidcAuthProvider().getLatestAuthToken(); |
127 | | - return new JWTTokenRequestDecorator(() -> token); |
128 | | - } else if (AuthorizationType.API_KEY.equals(authorizationType)) { |
129 | | - if (apiAuthProviders.getApiKeyAuthProvider() != null) { |
130 | | - return new ApiKeyRequestDecorator(apiAuthProviders.getApiKeyAuthProvider()); |
131 | | - } else if (apiKey != null) { |
132 | | - return new ApiKeyRequestDecorator(() -> apiKey); |
133 | | - } else { |
134 | | - throw new ApiException("Attempting to use API_KEY authorization without an API key provider or " + |
135 | | - "an API key in the config file", |
136 | | - "Verify that an API key is in the config file or an " + |
137 | | - "ApiKeyAuthProvider is setup during the API plugin initialization."); |
138 | | - } |
139 | | - } else if (AuthorizationType.AWS_IAM.equals(authorizationType)) { |
140 | | - if (apiAuthProviders.getAWSCredentialsProvider() == null) { |
141 | | - throw new ApiException("Attempting to use AWS_IAM authorization without " + |
142 | | - "an AWS credentials provider.", |
143 | | - "Configure an AWSCredentialsProvider when initializing the API plugin."); |
144 | | - } |
145 | | - AppSyncV4Signer appSyncV4Signer = new AppSyncV4Signer(region); |
146 | | - return new IamRequestDecorator(appSyncV4Signer, apiAuthProviders.getAWSCredentialsProvider()); |
147 | | - } else { |
148 | | - return NO_OP_REQUEST_DECORATOR; |
| 110 | + switch (authorizationType) { |
| 111 | + case AMAZON_COGNITO_USER_POOLS: |
| 112 | + // Note that if there was no user-provided cognito provider passed in to initialize |
| 113 | + // the API plugin, we will try to default to using the DefaultCognitoUserPoolsAuthProvider. |
| 114 | + // If that fails, we then have no choice but to bubble up the error. |
| 115 | + CognitoUserPoolsAuthProvider cognitoUserPoolsAuthProvider = |
| 116 | + apiAuthProviders.getCognitoUserPoolsAuthProvider() != null ? |
| 117 | + apiAuthProviders.getCognitoUserPoolsAuthProvider() : |
| 118 | + new DefaultCognitoUserPoolsAuthProvider(); |
| 119 | + // By calling getLatestAuthToken() here instead of inside the lambda block, makes the exception |
| 120 | + // handling a little bit cleaner. If getLatestAuthToken() is called from inside the lambda expression |
| 121 | + // below, we'd have to surround it with a try catch. By doing it this way, if there's a problem, |
| 122 | + // the ApiException will just be bubbled up. Same for OPENID_CONNECT. |
| 123 | + final String token = cognitoUserPoolsAuthProvider.getLatestAuthToken(); |
| 124 | + return new JWTTokenRequestDecorator(() -> token); |
| 125 | + case OPENID_CONNECT: |
| 126 | + if (apiAuthProviders.getOidcAuthProvider() == null) { |
| 127 | + throw new ApiException("Attempting to use OPENID_CONNECT authorization " + |
| 128 | + "without an OIDC provider.", |
| 129 | + "Configure an OidcAuthProvider when initializing the API plugin."); |
| 130 | + } |
| 131 | + final String oidcToken = apiAuthProviders.getOidcAuthProvider().getLatestAuthToken(); |
| 132 | + return new JWTTokenRequestDecorator(() -> oidcToken); |
| 133 | + case API_KEY: |
| 134 | + if (apiAuthProviders.getApiKeyAuthProvider() != null) { |
| 135 | + return new ApiKeyRequestDecorator(apiAuthProviders.getApiKeyAuthProvider()); |
| 136 | + } else if (apiKey != null) { |
| 137 | + return new ApiKeyRequestDecorator(() -> apiKey); |
| 138 | + } else { |
| 139 | + throw new ApiException("Attempting to use API_KEY authorization without an API key provider or " + |
| 140 | + "an API key in the config file", |
| 141 | + "Verify that an API key is in the config file or an " + |
| 142 | + "ApiKeyAuthProvider is setup during the API plugin initialization."); |
| 143 | + } |
| 144 | + case AWS_IAM: |
| 145 | + AWSCredentialsProvider credentialsProvider = apiAuthProviders.getAWSCredentialsProvider() != null |
| 146 | + ? apiAuthProviders.getAWSCredentialsProvider() |
| 147 | + : getDefaultCredentialsProvider(); |
| 148 | + AppSyncV4Signer appSyncV4Signer = new AppSyncV4Signer(region); |
| 149 | + return new IamRequestDecorator(appSyncV4Signer, credentialsProvider); |
| 150 | + case NONE: |
| 151 | + default: |
| 152 | + return NO_OP_REQUEST_DECORATOR; |
| 153 | + } |
| 154 | + } |
| 155 | + |
| 156 | + private AWSCredentialsProvider getDefaultCredentialsProvider() throws ApiException { |
| 157 | + // Obtains AWSMobileClient from Auth Category. |
| 158 | + // Throw if AWSCognitoAuthPlugin not configured. |
| 159 | + try { |
| 160 | + return (AWSMobileClient) Amplify.Auth.getPlugin(AUTH_DEPENDENCY_PLUGIN_KEY).getEscapeHatch(); |
| 161 | + } catch (IllegalStateException exception) { |
| 162 | + throw new ApiException("Attempting to use AWS_IAM authorization without " + |
| 163 | + "an AWS credentials provider.", |
| 164 | + "Configure an AWSCredentialsProvider when initializing the API plugin or register" + |
| 165 | + "an instance of AWSCognitoAuthPlugin to Amplify."); |
149 | 166 | } |
150 | 167 | } |
151 | 168 | } |
0 commit comments