-
Notifications
You must be signed in to change notification settings - Fork 50
client_oauth2
!-- Accessing to an OAuth2 GraphQL server -->
- Accessing to an OAuth2 GraphQL server
- Note for Jersey users, and old users of the plugin (prior to 1.12)
- Sample
- The http error codes
- Some CURL command to check the OAuth configuration
- Enable the proper dependencies
- Configure OAuth2 on client side, with Spring Boot
- Enable OAuth2 on client side, with Spring Boot
Since the 1.12 release, the generated code for the client side allows to use Spring. This also allows to use various Spring capabilities, like Spring Security, and easy configuration with Spring Boot.
To access to a GraphQL server protected by OAuth2, you'll need to create a basic Spring app, and this page describes how to add the OAuth2 capability to this basic Spring app.
This page details how to use Spring Boot to configure Spring Security. This allows to:
- Get an OAuth token from an Authorization server
- Access to a GraphQL server that is protected by OAuth, that is, a GraphQL server that expect to receive a token that can be validated against the above Autorization server.
This page won't detail more the OAuth protocol. You'll find more information on the web. And a good idea is to start by OAuth presentation.
To connect to an OAuth server, you must use Spring capabilities. So the Jersey implementation of this plugin can't do that.
If you're using the (now old) QueryExecutorImpl
class, you won't be able to use this feature. Since the 1.12 release, the default QueryExecutor
is the QueryExecutorSpringReactiveImpl
which is based on Spring, with Spring reactive. Once the configuration below is done, this allows to access to OAuth protected urls for queries, mutations and subscriptions.
If you don't know if you're using QueryExecutorImpl
class or not, that is, if we use the plugin runtime as is, then all this is transparent. By building with the graphql plugin in its 1.12 (or newer) version, then you'll use the QueryExecutorSpringReactiveImpl
and all its capabilities. Including what's documented below.
This page is based on the graphql-maven-plugin-samples-allGraphQLCases-client sample.
This sample can be executed, when the servers below are started. They are available in the maven plugin project:
- The OAuth2 Authorization server is in the graphql-maven-plugin-samples-OAuth-authorization-server module.
- To start it, just execute the
com.marcosbarbero.lab.sec.oauth.opaque.OAuth2OpaqueAuthorizationServerApp
class, as a java application. - This server listen on the 8181 port. If you want to change it, you'll have to change its application.yml properties file, and the other application properties files accordingly.
- To start it, just execute the
- The GraphQL server is in the graphql-maven-plugin-samples-allGraphQLCases-server module.
- To start it, you'll have to build it, then execute the org.allGraphQLCases.server.util.GraphQLServerMain, generated by the graphql plugin in the target/generated-sources/graphql-maven-plugin folder.
- This server listen on the 8180 port. If you want to change it, you'll have to change its application.yml properties file, and the other application properties files accordingly.
Here is an important notice about the HTTP status code that you may encounter here:
- 401 means there is no OAuth authorization. There is an issue with the configuration, and probably no OAuth token is given to the resource server. Or the token is invalid.
- 403 means that the resource server receives the OAuth authorization, and the token is valid. But for some reason, you're not allowed to access to this resource.
As usual, it may happen (hum, ok, it always happens :) ) that some issue prevents your code to work as expected. So here are some useful commands, to check if the whole system is properly configured or not.
All these commands are based on the graphql-maven-plugin-samples-allGraphQLCases resource server, and the graphql-maven-plugin-samples-OAuth-authorization-server authorization server, as provided in the maven GraphQL plugin project.
These commands:
- Are based on the curl command line tool.
- The -i parameter allows to show the full response
- The --noproxy "*" is necessary in my config, to avoid curl to send all these commands in the proxy, as the servers are local ones.
- Contains tokens that you'll need to update, according to the one you'll get from the first request.
A sample query, to get an OAuth token:
curl -u "clientId:secret" -X POST "http://localhost:8181/oauth/token?grant_type=client_credentials" --noproxy "*" -i
Then, reuse the previous token in the next query:
curl -i -X POST "http://localhost:8180/graphql" --noproxy "*" -H "Authorization: Bearer 8c8e4a5b-d903-4ed6-9738-6f7f364b87ec"
And, to check the token:
curl -i -X GET "http://localhost:8181/profile/me" --noproxy "*" -H "Authorization: Bearer 8c8e4a5b-d903-4ed6-9738-6f7f364b87ec"
Of course, in order to make all this work, you need some code in your classpath.
If you included com.graphql-java-generator:graphql-java-client-dependencies:pom, in your dependencies, everything should be ok.
If not, you need to include these dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
To configure OAuth2, there are tons of documentations on the web. But you should start from this sample. Below is the application.properties file of the graphql-maven-plugin-samples-allGraphQLCases-client module. This file must on the root of the resource folder. Here it is:
graphql.endpoint.url = http://localhost:8180/graphql
graphql.endpoint.subscriptionUrl = http://localhost:8180/graphql/subscription
# We don't need the Netty web server to start
spring.main.web-application-type = none
# Configuration for OAuth2, for our local OAuth authorization server
spring.security.oauth2.client.registration.provider_test.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.provider_test.client-id=clientId
spring.security.oauth2.client.registration.provider_test.client-secret=secret
spring.security.oauth2.client.provider.provider_test.token-uri=http://localhost:8181/oauth/token
The first part is the GraphQL configuration part.
The second part deals with OAuth:
- This sample uses the client_credentials OAuth grant type.
- We're using the provider_test OAuth provider. You find the provider's name in each spring configuration properties. It is given to spring when defining the serverOAuth2AuthorizedClientExchangeFilterFunction Spring bean (see below)
If you need some other grant types, check on the web, for more information on the Spring Boot configuration to do that. All the job is done in this configuration file. There should be no impact on the code, out of defining the `ServerOAuth2AuthorizedClientExchangeFilterFunction as explained below.
We're starting with the basic Spring app.
Adding the OAuth2 capability is as simple as adding the ServerOAuth2AuthorizedClientExchangeFilterFunction
, like in the sample below:
@SpringBootApplication(scanBasePackageClasses = { MinimalOAuthApp.class, GraphQLConfiguration.class, MyQueryTypeExecutor.class })
public class MinimalOAuthApp implements CommandLineRunner {
@Autowired
MyQueryTypeExecutor queryType;
public static void main(String[] args) {
SpringApplication.run(MinimalOAuthApp.class, args);
}
/**
* This method is started by Spring, once the Spring context has been loaded. This is run, as this class implements
* {@link CommandLineRunner}
*/
@Override
public void run(String... args) throws Exception {
String query = "{appearsIn name }";
System.out.println("Executing this query: '" + query + "'");
System.out.println(queryType.withoutParameters(query));
}
@Bean
ServerOAuth2AuthorizedClientExchangeFilterFunction serverOAuth2AuthorizedClientExchangeFilterFunction(
ReactiveClientRegistrationRepository clientRegistrations) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
oauth.setDefaultClientRegistrationId("provider_test");
return oauth;
}
}
What happened there?
Just some Spring magic... ! :)
The serverOAuth2AuthorizedClientExchangeFilterFunction
is marked as Spring bean (same as the @Component on a class). So its auto loaded into the Spring's beans container. This tells Spring Boot to configure Spring Securities.
The serverOAuth2AuthorizedClientExchangeFilterFunction is responsible for each subsequence http request to:
- Check that there is a valid OAuth2 token
- If there is no token, a request to the OAuth authorization server is issued
- If there is an expired token, a refresh request is issued
- Add the relevant header into the http request
The important point, here, is to define the provider's name as it is named in the application.properties file. In this sample, its name is provider_test.
Creating a first app (non spring)
Connect to more than one GraphQL servers
Easily execute GraphQL requests with GraphQL Repositories
Access to an OAuth2 GraphQL server
How to personalize the client app
Howto personalize the generated code
Client migration from 1.x to 2.x
Implement an OAuth2 GraphQL server
Howto personalize the generated code
Server migration from 1.x to 2.x