Search in sources :

Example 6 with ApiAuthException

use of com.amplifyframework.api.ApiException.ApiAuthException in project amplify-android by aws-amplify.

the class AuthRuleRequestDecorator method decorate.

/**
 * Decorate given GraphQL request instance with additional variables for owner-based or
 * group-based authorization.
 *
 * This will only work if the request is compliant with the AppSync specifications.
 * @param request an instance of {@link GraphQLRequest}.
 * @param authType the mode of authorization being used to authorize the request
 * @param <R> The type of data contained in the GraphQLResponse expected from this request.
 * @return the input request with additional variables that specify model's owner and/or
 *          groups
 * @throws ApiException If an error is encountered while processing the auth rules associated
 *          with the request or if the authorization fails
 */
public <R> GraphQLRequest<R> decorate(@NonNull GraphQLRequest<R> request, @NonNull AuthorizationType authType) throws ApiException {
    if (!(request instanceof AppSyncGraphQLRequest)) {
        return request;
    }
    AppSyncGraphQLRequest<R> appSyncRequest = (AppSyncGraphQLRequest<R>) request;
    AuthRule ownerRuleWithReadRestriction = null;
    Map<String, Set<String>> readAuthorizedGroupsMap = new HashMap<>();
    // and it's not clear what a good solution would be until AppSync supports real time filters.
    for (AuthRule authRule : appSyncRequest.getModelSchema().getAuthRules()) {
        if (isReadRestrictingOwner(authRule)) {
            if (ownerRuleWithReadRestriction == null) {
                ownerRuleWithReadRestriction = authRule;
            } else {
                throw new ApiAuthException("Detected multiple owner type auth rules with a READ operation", "We currently do not support this use case. Please limit your type to just one owner " + "auth rule with a READ operation restriction.");
            }
        } else if (isReadRestrictingStaticGroup(authRule)) {
            // Group read-restricting groups by the claim name
            String groupClaim = authRule.getGroupClaimOrDefault();
            List<String> groups = authRule.getGroups();
            Set<String> readAuthorizedGroups = readAuthorizedGroupsMap.get(groupClaim);
            if (readAuthorizedGroups != null) {
                readAuthorizedGroups.addAll(groups);
            } else {
                readAuthorizedGroupsMap.put(groupClaim, new HashSet<>(groups));
            }
        }
    }
    // them.
    if (ownerRuleWithReadRestriction != null && userNotInReadRestrictingGroups(readAuthorizedGroupsMap, authType)) {
        String idClaim = ownerRuleWithReadRestriction.getIdentityClaimOrDefault();
        String key = ownerRuleWithReadRestriction.getOwnerFieldOrDefault();
        String value = getIdentityValue(idClaim, authType);
        try {
            return appSyncRequest.newBuilder().variable(key, "String!", value).build();
        } catch (AmplifyException error) {
            // This should not happen normally
            throw new ApiAuthException("Failed to set owner field on AppSyncGraphQLRequest.", error, AmplifyException.REPORT_BUG_TO_AWS_SUGGESTION);
        }
    }
    return request;
}
Also used : ApiAuthException(com.amplifyframework.api.ApiException.ApiAuthException) HashSet(java.util.HashSet) Set(java.util.Set) AmplifyException(com.amplifyframework.AmplifyException) HashMap(java.util.HashMap) AppSyncGraphQLRequest(com.amplifyframework.api.aws.AppSyncGraphQLRequest) ArrayList(java.util.ArrayList) List(java.util.List) AuthRule(com.amplifyframework.core.model.AuthRule) HashSet(java.util.HashSet)

Example 7 with ApiAuthException

use of com.amplifyframework.api.ApiException.ApiAuthException in project amplify-android by aws-amplify.

the class IamRequestDecorator method decorate.

/**
 * Adds the appropriate header to the provided HTTP request.
 * @param req The request to be signed.
 * @return A new instance of the request containing the signature headers.
 * @throws ApiAuthException If the signing process fails.
 */
public final okhttp3.Request decorate(okhttp3.Request req) throws ApiAuthException {
    // Clone the request into a new DefaultRequest object and populate it with credentials
    final DefaultRequest<?> dr = new DefaultRequest<>(serviceName);
    // set the endpoint
    dr.setEndpoint(req.url().uri());
    // copy all the headers
    for (String headerName : req.headers().names()) {
        dr.addHeader(headerName, req.header(headerName));
    }
    // set the http method
    dr.setHttpMethod(HttpMethodName.valueOf(req.method()));
    // set the request body
    final byte[] bodyBytes;
    RequestBody body = req.body();
    boolean isEmptyRequestBody = false;
    try {
        if (body != null && body.contentLength() > 0) {
            // write the body to a byte array.
            final Buffer buffer = new Buffer();
            body.writeTo(buffer);
            bodyBytes = IOUtils.toByteArray(buffer.inputStream());
        } else {
            isEmptyRequestBody = true;
            bodyBytes = "".getBytes();
        }
        dr.setParameters(splitQuery(req.url().url()));
    } catch (IOException exception) {
        throw new ApiAuthException("Unable to calculate SigV4 signature for the request", exception, "Check your application logs for details.");
    }
    dr.setContent(new ByteArrayInputStream(bodyBytes));
    // set the query string parameters
    v4Signer.sign(dr, credentialsProvider.getCredentials());
    // Copy the signed/credentialed request back into an OKHTTP Request object.
    okhttp3.Request.Builder okReqBuilder = new okhttp3.Request.Builder();
    // set the headers from default request, since it contains the signed headers as well.
    for (Map.Entry<String, String> e : dr.getHeaders().entrySet()) {
        okReqBuilder.addHeader(e.getKey(), e.getValue());
    }
    // Set the URL and Method
    okReqBuilder.url(req.url());
    final RequestBody requestBody;
    if (!isEmptyRequestBody) {
        requestBody = RequestBody.create(bodyBytes, JSON_MEDIA_TYPE);
    } else {
        requestBody = null;
    }
    okReqBuilder.method(req.method(), requestBody);
    // continue with chain.
    return okReqBuilder.build();
}
Also used : Buffer(okio.Buffer) ApiAuthException(com.amplifyframework.api.ApiException.ApiAuthException) DefaultRequest(com.amazonaws.DefaultRequest) DefaultRequest(com.amazonaws.DefaultRequest) IOException(java.io.IOException) ByteArrayInputStream(java.io.ByteArrayInputStream) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) RequestBody(okhttp3.RequestBody)

Aggregations

ApiAuthException (com.amplifyframework.api.ApiException.ApiAuthException)7 ApiException (com.amplifyframework.api.ApiException)5 AmplifyException (com.amplifyframework.AmplifyException)2 GraphQLRequest (com.amplifyframework.api.graphql.GraphQLRequest)2 Request (okhttp3.Request)2 DefaultRequest (com.amazonaws.DefaultRequest)1 AWS4Signer (com.amazonaws.auth.AWS4Signer)1 AWSCredentialsProvider (com.amazonaws.auth.AWSCredentialsProvider)1 Tokens (com.amazonaws.mobile.client.results.Tokens)1 AppSyncGraphQLRequest (com.amplifyframework.api.aws.AppSyncGraphQLRequest)1 RequestDecorator (com.amplifyframework.api.aws.auth.RequestDecorator)1 ApiGatewayIamSigner (com.amplifyframework.api.aws.sigv4.ApiGatewayIamSigner)1 AppSyncV4Signer (com.amplifyframework.api.aws.sigv4.AppSyncV4Signer)1 CognitoUserPoolsAuthProvider (com.amplifyframework.api.aws.sigv4.CognitoUserPoolsAuthProvider)1 DefaultCognitoUserPoolsAuthProvider (com.amplifyframework.api.aws.sigv4.DefaultCognitoUserPoolsAuthProvider)1 AuthRule (com.amplifyframework.core.model.AuthRule)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1