Auth0経由でGoogleログインしたユーザーでAWS AppSyncへ接続するサンプルアプリをReact Nativeで作ってみた

2020.12.29

最近React Nativeを触る機会があったので、簡易的にまとめてブログ化してみました。

ちなみに私はUnbuntu20.04を利用しているため、Androidのみでの作業となりますのでご了承ください。

構成図

Auth0経由でGoogleログインしたユーザーが、AppSync経由でDynamoDBに入っている一覧データを取得します。

事前準備

事前にReact Nativeの環境構築を行う必要があります。

公式ドキュメントを参考に済ませておいてください。

Auth0でApplicationの登録とサンプルアプリの起動

Auth0ダッシュボードの「Applications」から「CREATE APPLICATION」をクリックします。

アプリケーション名とアプリケーションタイプを選択します。

React Nativeのサンプルコードをダウンロードします。

ダウロード画面に遷移すると「Allowed Callback URLs」 「Allowed Logout URLs」の設定をするように表示されます。

設定は「Settings」タブから変更可能です。

ここまでできたら、ダウンロードしたサンプルアプリを起動してみます。

解凍したZipファイル内で、下記のコマンドを実行するとエミュレーターが立ち上がります。

cd 00-login
# ライブラリのインストール
yarn install
# react nativenの起動
yarn start
# エミュレータの起動
yarn run android

このまま問題なく起動するかと思いきや、 私の環境では下記のエラーが出ました。

* What went wrong:
Execution failed for task ':app:packageDebug'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > com.android.ide.common.signing.KeytoolException: Failed to read key androiddebugkey from store "/home/seiichi/workspace/react-native-auth0-sample/android/app/debug.keystore": DerInputStream.getLength(): lengthTag=63, too big.

正直ここらへんの設定はまだよく分かっていないのですが、いろいろ調べた結果、 android/appで鍵を再作成することで対処できました。わかる方いたら教えてください。。。

https://coderwall.com/p/r09hoq/android-generate-release-debug-keystores

keytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000

また、react native 0.62系はバグが多いらしいので、package.jsonを書き換えて、0.63系に変更しておきました。

もともと知見がないためココらへんのトラブルシュートでかなり時間をとられましたが、なんとか手元で動かすことができました。

ログイン画面

Googleログイン

アクセストークン取得

AWS AppSyncの作成と設定

こちらを参考にAppSyncの作成を行っていきます。

まず、AWSコンソールでAppSyncのリソースを作成していきます。

モデルの作成

OpenID Connect provider domain (Issuer URL)にAuth0のテナントのドメインを入力します。

さっそくAppSyncへリクエストを送信したいところですが、Auth0側で少し設定が必要です。

今回はOIDCなので、Auth0側にAPIを登録して、アクセストークンを取得します。

まずは、Auth0ダッシュボードから「CREATE API」をクリックし、APIを作成します。 「Identifier」には、AppSyncのエンドポイントURLを入力してください。

作成したAPIの「Test」タブにアクセストークンが表示されているのでそのまま利用します。

最後にDynamoDBにデータが入っていないので登録しておきます。

AWSコンソールから先ほど取得したアクセストークンを使ってクエリを実行してみます。

React NativeでGoogle認証後にAppSyncへリクエストを送信してみる

こちらを参考にライブラリのインストールやコードの修正をおこなっていきます。

ライブラリのインストール

  • aws-mobile-appsync-sdk-js
yarn add aws-appsync aws-appsync-react
# React Native 0.60以上は下記も必要
yarn add @react-native-community/netinfo@5.9.4 @react-native-community/async-storage
  • apollo
yarn add apollo-client react-apollo@2.5.8

React-apollo 3.0aws-appsync-reactの間で既知の不具合があるようです。今回はバージョンを下げることで対処しました。

  • graphql
yarn add graphql graphql-tag

configファイルの取得

AWSコンソールからaws-exports.jsをダウンロードして、app配下に設置しておきます。

// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile =  {
    "aws_appsync_graphqlEndpoint": "your_graphqlEndpoint",
    "aws_appsync_region": "ap-northeast-1",
    "aws_appsync_authenticationType": "OPENID_CONNECT",
    "aws_appsync_apiKey": "<your_apiKey>",
};

export default awsmobile;

コードの修正

app/App.jsを修正

import React, {Component} from 'react';
import {Alert, Text} from 'react-native';
import {graphql, ApolloProvider} from 'react-apollo';
import Auth0 from 'react-native-auth0';
import AWSAppSyncClient, {AUTH_TYPE} from 'aws-appsync';
import {Rehydrated} from 'aws-appsync-react';
import gql from 'graphql-tag';
import appSyncConfig from './aws-exports';

var credentials = require('./auth0-configuration');
const auth0 = new Auth0(credentials);

const client = new AWSAppSyncClient({
  url: appSyncConfig.aws_appsync_graphqlEndpoint,
  region: appSyncConfig.aws_appsync_region,
  auth: {
    type: AUTH_TYPE.OPENID_CONNECT,
    jwtToken: async () => {
      try {
        const credentials = await auth0.webAuth.authorize({
          scope: 'openid profile email',
          audience: appSyncConfig.aws_appsync_graphqlEndpoint,
        });
        Alert.alert('accessToken: ' + credentials.accessToken);
        return credentials.accessToken;
      } catch (error) {
        Alert.alert(error);
      }
    },
  },
  disableOffline: true,
});

const WithProvider = () => (
  <ApolloProvider client={client}>
    <Rehydrated>
      <App />
    </Rehydrated>
  </ApolloProvider>
);

class App extends Component {
  render() {
    return <UserComponent />;
  }
}

const listUsers = gql`
  query MyQuery {
    listMyModelTypes {
      items {
        id
        name
      }
    }
  }
`;

class User extends Component {
  render() {
    return (
      <>
        {this.props.users.map((user, index) => (
          <Text key={user.id} style={{fontSize: 40}}>
            id={user.id}, name={user.name}
          </Text>
        ))}
      </>
    );
  }
}

const UserComponent = graphql(listUsers, {
  options: {
    fetchPolicy: 'network-only',
  },
  props: props => ({
    users: props.data.listMyModelTypes ? props.data.listMyModelTypes.items : [],
  }),
})(User);

export default WithProvider;

動作確認

コマンドを実行

yarn start
yarn run android

エミュレーター

まとめ

簡易的ですが、Auth0経由でGoogleログインしたユーザーがAppSyncにGraphQLのクエリを投げるところまをReact Nativeで実装できました。

本番利用する際には、Google APIsへの正式登録などが必要になってきますので、注意が必要です。

どなたかの役に立てば幸いです。