Implementing GraphQL Server & client app using a private OAuth 2.0 Server
Recently I started learning about graphql as I had to implement a solution containing graphql data server utilising apollo, mysql & react.js.
After going through a few samples & tutorials it became clear graphql servers are supposed to provide data & are not meant to implement security for particular applications querying the data, as this responsibility lies logically with another part of the solution architecture. This is regardless of the fact that for smaller applications the same server app may implement both functionalities.
For reference look at the link below for enforcing graphql security:
However there is some confusion around this particularly for people new to graphql & implementing security for both a server based application as well as client applications being served via them. The reasons for this are:
- Popular solutions have integrated samples
Apollo graphql is the most popular graphql implementation and they offer Apollo graphql package integration with web servers such as express.js and Koa.js. This gives the impression that graphql should be used within such applications, which if used as REST applications are supposed to implement their own security. However logically this does not imply that the authentication and authorisation of the REST application should somehow be integrated with graphql server.
- Only basic authentication is widely understood
In simple applications basic authentication is used with username and passwords, in such applications same database will be used if additionally graphql implementation is provided potentially using the same database to store and retrieve authentication and authorisation details.
- Oauth and openID strategies are complicated and confusing
This can also be particularly confusing because nowadays application providers want to implement well defined security & identity management solutions such as oauth 2.0 etc.
After understanding the above challenges and reading through oauth & graphql documentation I prescribe the following parts for a descent size end to end solution:
- Graphql Server app: A server side application that will access a sql database or the likes, and serve it via a graphql package such as Apollo graphql server.
- Independent server app: The server app is independent of the client applications that it will serve. This means it should only concern itself will providing the data.
- SPAs or mobile apps: The client applications are either going to be single page applications or mobile apps, that will negotiate authentication & authorisation with an oauth 2.0 provider. This could be a react application or a react-native application for example.
- Use Open source Oauth Server: A oauth 2.0 server that will take care of security and identity management.
Surprisingly there are a few open source and free products out there that can be privately installed and provide this functionality without writing code. Examples are below:
https://fusionauth.io/ (FusionAuth adds authentication, authorisation, user management, reporting, analytics and much more in minutes not months.)
https://www.keycloak.org/index.html (Add authentication to applications and secure services with minimum fuss. No need to deal with storing users or authenticating users. It’s all available out of the box.)
Simplified Oauth 2:
The following link describes in simple terms oath 2.0 and various strategies out of which two are the most popular ones that I would follow namely, authorisation code & password.
The post is written by Aaron Parecki who is a oauth consultant and and written W3C specs himself. Please review this post before progressing below as it will help understand further details.
Implementation details for the solution are as follows:
Oauth Server Installation:
We have decided to use fusionauth as that is extensive and can pretty much be installed out of the box as a private instance and used for authentication and identity management. It allows registering multiple applications and their credentials such as appIds, redirect urls and tokens etc for individual front end applications.
It also provides RESTfull endpoints that can be used later by server side applications to validate the tokens issued by the oauth server to client applications to check that they are accessing secure applications.
So this server will stand in the middle of both the client and server applications. On one end it will register and authorise users for front-end apps. On the other end it will server an introspection endpoint for server apps that will query for with the credentials of the querying front-end apps.
Front End Application:
Any front end application that is already registered with the oath server such as fusionauth will basically re-direct the user to fusionauth interface for login or registration with a request. Keeping in mind the ouath 2.0 implementation as it is not possible for spa or mobile apps to keep the client secret safe, hence the request will only use clientId, redirect_url & scope in the request that is allowed to be public.
This process requires a redirect_url to be provided in the request process that is also already registered with fusionauth. This callback will be returned with an authorisation code, which the front end app will again exchange for access and refresh tokens.
These tokens will be stored in local storage by these apps, and will be later used to query data from the graphql server application for additional data. The front end apps will send the token as a bearer token within the header of the request to the graphql server as below:
Authorization: Bearer 0b79bab50daca910b000d4f1a2b675d604257e42
Server graphql application:
This can be a node.js application that primarily uses garphql-server and garphql pakages. This application will connect to an sql database to serve the data for the queries via graphql schema and resolvers.
However for security it will implement a context function on the graphql-server that will get the access token as a bearer token via the request header from either a front end web or mobile app. It will then verify that token via an introspection endpoint on the fusionauth server that is a RESTfull endpoint and will return details about the access token that will include the related info that will include expired date, email address etc.
Following links explains introspection endpoint details:
In order to reduce the load on the oauth server this information including access & refresh tokens can be stored in the local database and accessed first to check if the access token that has been provided exists for that email and if it has not expired. In case of expiration first it can be checked by introspection endpoint, or an error can be generated, or if a refresh token is available it can be used to get a new access token for the client based on individual approach.
The above explanation is one possible but practical approach to dealing with a scenario where oauth 2 server, client & server app authentication and authorisation has to be implemented with respect to graphql.
Hope it helps clarify the implementation of such a solution. Feel free to provide comments and describe your own experiences in such scenarios.