smallrye / smallrye-graphql

Implementation for MicroProfile GraphQL
Apache License 2.0
160 stars 91 forks source link

Get Authorization header in an AWS API Gateway+AWS Lambda+Quarkus+GraphQL-Smallrye environment #1924

Open jfalcos opened 1 year ago

jfalcos commented 1 year ago

Hey everyone,

I've been using quarkus with resteasy and decided to give the smallrye graphql framework a shot. The first hurdle that I'm encountering is being able to access the JWT Authorization header. In general I have been unsuccessful at accessing the request sent by apigateway. I feel there might be a deserializer missing somewhere but I can't find where.

Current setup is using the sample quarkus smallrye template. I made the http request work by adding the lambda-rest dependency. I've attached my project folder for reference. Dependencies and injections might look weird because I've been trying a lot of different things hehe.

Appreciate any guidance! If there is not a way to easily get the header, appreciate some pointers on how to deserialize the request so that I can use it on my graphql resources.

Note: I did see a post in stackoverflow about someone suggesting to use the graphql client. The setup would be to have a rest endpoint, a custom lambda handler and then call the graphql endpoint with a graphql client within the server. But this seems an overkill for something as simple as getting an Authorization header. I'd rather keep things simple.

Thanks!

Command I'm using to build: cmd /c call "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat" && mvn install -Dnative -DskipTests -Dquarkus.native.container-build=true -Dquarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-mandrel-builder-image:22.3-java17

sample project.zip

phillip-kruger commented 1 year ago

Hi @Dunmord

I can not talk on the AWS or API Gateway side of things. But from a GraphQL Perspective

    @Inject
    SecurityIdentity securityIdentity;

    @Inject
    JsonWebToken jwt; 

See https://github.com/phillip-kruger/quarkus-graphql-examples/blob/565e9719db96ddf948cbcc29a84502571771aaab/security-example/src/main/java/com/github/phillipkruger/endpoint/PersonEndpoint.java#L34

    @Query
    public Map<String,String> details(){
        return Map.of("principal", securityIdentity.getPrincipal().getName(),
                "jwtname", jwt.getName());

    }

Screenshot_20231002_115314

    @Inject
    Context context;
    @Inject
    public CurrentVertxRequest request;

Example for Contect and CurrentVertxRequest: https://github.com/phillip-kruger/quarkus-graphql-examples/blob/565e9719db96ddf948cbcc29a84502571771aaab/context-example/src/main/java/com/github/phillipkruger/endpoint/PersonEndpoint.java#L49

@Query
    public Map<String, String> details(){

        return Map.of("executionId", context.getExecutionId(),
                    "query",context.getQuery(),
                    "selected fields", context.getSelectedFields().toString(),
                    "my-header", request.getCurrent().request().getHeader("My-Header"));

    }

Screenshot_20231002_122206

Please let me know if this works for you

jfalcos commented 1 year ago

Hey @phillip-kruger !

Thanks for such a quick reply. Getting the original vertex request worked to get the header. I was also not accessing the headers from the RoutingContext correctly. I assumed that serializing the object to a string would print all of it's properties but it didn't, I have to specifically use the getter method to access the headers. Thanks for the tip!

The SecurityContext didn't work right off the bat, but it's probably because I'm not using it correctly; I need to play more with it. It's complaining that I didn't set the URL for the oauth server. Which makes sense if I'm using my service to authorize but in this case APIGW is already doing the authorization and validation of the JWT for me, so I just need to access it without the oidc library trying to run to the server. Need to research more on that.

Lastly, I was wondering if I can put a feature request to have the API Gateway request object availaible in the GraphQL-Smallrye context the same way it's available in the resteasy context? That would make life awhole lot easier.

(Reference guide)

If I can do something like

 @Inject AwsProxyRequestContext awsProxyRequestContext2;

That would save me a ton of leg work. Not the end of the world, but saves on iteration time.

Thanks again!

phillip-kruger commented 1 year ago

Hi @Dunmord

W.r.t the token, you should not need OIDC in your case, but maybe just JWT, or even just smallrye-jwt (see https://quarkus.io/guides/security-jwt#add-smallrye-jwt). @sberyozkin can help here.

Maybe this will also help: https://github.com/quarkusio/quarkus/discussions/28080

W.r.t the AwsProxyRequestContext, best would be to log an issue with all the details.