edit

How to integrate OAuth with Scaphold's GraphQL platform.

Hi GraphQL-Lovers!

Social authentication has been a hot topic for developers and users alike. There are many guides on how to implement it for traditional REST-based APIs, so here's one for the good guys.

Why social authentication? It all starts with the users. Most people have online social accounts on Facebook, Twitter, Google, and more. So they're thinking,

“I'll check out your app if I can just log in with my existing Facebook or Twitter account.”

The benefits are two-fold.

  1. Users are excited to get to remember one less account name and password. Hooray!

  2. Developers gets more content from these social authentication providers immediately upon log in, like emails, profile pictures, friends, etc…

Here's how it works at a high level:

Source: https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2

Source: https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2

  1. User must grant the application permission to access secured resources from an OAuth provider (i.e. Facebook, Google, etc).

  2. After the user successfully grants the application access, the OAuth provider generates a user access token and passes it back to the application.

  3. The application sends this user access token to the OAuth provider along with its own identity in order to authenticate.

  4. Upon successful authentication, the OAuth provider grants authorization and returns an app access token.

  5. Now that authorization is completed, the application may use the app access token for authentication to fetch authorized resources from the OAuth provider.

  6. App access token is verified and the requested OAuth provider's resources are sent back to the application.

    This isn't easy!

To do this yourself, you will have to perform the same workflow for every OAuth provider you wish to authenticate with. The best tool that we've found to help manage all these connections is Auth0. We'll be using this tool for the GraphQL walkthrough to help us set up OAuth.

Today, we'll explore two of the most popular social providers:

Facebook and Google.

Here's the agenda:

  1. Create an Auth0 account.

  2. Configure Facebook and Google connections.

  3. Use Auth0 account keys to configure an Auth0 integration on Scaphold.

  4. Obtain access token from Facebook client SDK, exchange it for an ID token, and send GraphQL request to authenticate.

  5. Store JSON Web Token (JWT) as Authorization header in HTTP requests.

  6. Once logged in, send another GraphQL request with a Google ID token to link both social authentication credentials.

  7. Voilá!

Let's start by creating a free Auth0 account.

This will help you manage your app credentials like client IDs and secrets for your OAuth providers. By connecting your apps on your social accounts like Facebook, Google, and Twitter, you'll then have the correct account credentials to utilize these services for your authentication flow.

For more information on configuring your social connections on Auth0, check out these guides: Facebook / Google

Once you've tested out your connections to see that they work, save your Auth0 Domain, Client ID, and Client Secret.

Next, configure Auth0 in Scaphold from the Integrations Portal to include the OAuth providers that you plan to use for your app. This will enable a new mutation in your schema called loginUserWithAuth0 which you can use to log in users with connected OAuth providers.

In your client app, you'll likely be using a client SDK to handle user login. For instance, you can use the Facebook SDK for React Native to ask your users to log in with their existing Facebook accounts. Your app will redirect them to a Facebook sign-in page and once this succeeds, you'll receive an access token that you'll verify with your OAuth provider, and then the corresponding idToken will be sent to Scaphold.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
const FBSDK = require('react-native-fbsdk');
const rp = require('request-promise');

const {
  LoginButton,
  AccessToken
} = FBSDK;

var Login = React.createClass({
  render: function() {
    return (
      <View>
        <LoginButton
          publishPermissions={["publish_actions"]}
          onLoginFinished={
            (error, result) => {
              if (error) {
                alert("login has error: " + result.error);
              } else if (result.isCancelled) {
                alert("login is cancelled.");
              } else {
                AccessToken.getCurrentAccessToken().then(
                  (data) => {

                    /*
                     * Use Access Token to retrieve Auth0 ID Token
                     */

                    const options = {
                      method: 'POST',
                      uri: url,
                      body: {
                        client_id: 'xxxxxxxxxxx', // Your Auth0 Client ID
                        access_token: data.accessToken.toString(),
                        connection: 'facebook',
                        scope: 'openid'
                      },
                      json: true,
                      resolveWithFullResponse: true
                    };
                    return rp(options);
                  }).then(res => {

                    /*
                     * Example response
                     * {
                     *   "idToken": "eyJ0eXAiOiJKV1Qi...",
                     *   "access_token": "A9CvPwFojaBI...",
                     *   "token_type": "bearer"
                     * }
                     */

                    alert(res.body.idToken);

                    /*
                     * Send Scaphold login mutation (shown below)
                     */

                  }).catch(err => {
                    logger.error(err);
                    throw httpError(403, err);
                  });
                )
              }
            }
          }
          onLogoutFinished={() => alert("logout.")}/>
      </View>
    );
  }
});

Given the idToken, here's the GraphQL mutation you can use to log your user in to Scaphold:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// GraphQL Mutation

mutation LoginUserWithAuth0 ($input: LoginUserWithAuth0Input!) {
  loginUserWithAuth0 (input: $input) {
    user {
      id
      username
      createdAt
    }
  }
}

// Variables

{
  "input": {
    "idToken": "eyJ0eXAiOiJKV1Qi..." // idToken from above
  }
}

Once you've sent that request, the response should resemble this:

After Scaphold securely logs the user in with the idToken, we'll pass back the newly generated idToken that you'll need to add to your Authorization header for future requests. That way, Scaphold will be able to authenticate you to make future requests through Scaphold, and it will also provide us the capability to work on that user's behalf to access the OAuth provider's resources. In this case, we could authorize you to access their Facebook friends and their public profile information.

In addition, if you've logged in already and you make the same request again but with a new OAuth provider (i.e. Google), Scaphold will link your two accounts together, since we know the requests being made belong to the same user.

In a similar fashion to the Facebook work flow from earlier, you'll likely use a client SDK for Google sign-in. Upon logging in, you'll receive an access token and again verify it with the OAuth provider like so:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
GoogleSignin.signIn().then((user) => {
  /*
   * Send Access Token to Scaphold (shown below)
   */
  const options = {
    method: 'POST',
    uri: url,
    body: {
      client_id: 'xxxxxxxxxxx', // Your Auth0 Client ID
      access_token: user.accessToken,
      connection: "google_oauth2",
      scope: 'openid'
    },
    json: true,
    resolveWithFullResponse: true
  };
  return rp(options);
}).then(res => {
  alert(res.body.idToken);

  /*
   * Send Scaphold login mutation (like earlier above)
   */

}).catch((err) => {
  console.log('WRONG SIGNIN', err);
}).done();

With this idToken, you'll send a GraphQL request to Scaphold the same way as earlier.

Congratulations! Now, you'll have access to both Facebook and Google information using your users' Facebook and Google account credentials. Thanks for checking this out, and check out our community page for more tutorials on simple ways to get started with GraphQL!

Scaphold
Brought to you by Scaphold.io