AWS AmplifyでFacebookログインを実装した時にかなりつまりました。
同じような方がいると思いますので、メモとして残しておきます。
環境
- Amplify 4.13.4
- Yarn 1.22.4
- Node.js 10.15.1
- Vue.js 2.6.11
Facebookの設定1
- Facebook for Developersへ登録します
- Create Appでアプリを登録します.アプリの利用目的は今回はその他を選択しました
- アプリ名は適当に入力してアプリIDを作成します
- 上部にあるアプリIDと左側の設定 > ベーシックからシークレットIDをコピーしておきます(後ほど使います)
Amplifyの設定
Authの設定
- Facebookログインの機能を追加します
- Facebook側でログインをした後、リダイレクトされる先は一旦ログイン画面としています.ご自身の環境に合わせて修正ください
- LocalとProductionそれぞれ2つ追加しています.Localのポートなどはご自身の環境に合わせて修正ください
- FacebookのアプリIDとシークレットキーを聞かれたら、控えておいた値を入力するようにします
$ amplify add auth
Using service: Cognito, provided by: awscloudformation
The current configured provider is Amazon Cognito.
Do you want to use the default authentication and security configuration? Default configuration with Social Provider (Federation)
Warning: you will not be able to edit these selections.
How do you want users to be able to sign in? Email
Do you want to configure advanced settings? No, I am done.
What domain name prefix you want us to create for you? test1ec8a379-1ec8a379
Enter your redirect signin URI: https://localhost:8081/login/ # Local
? Do you want to add another redirect signin URI Yes
Enter your redirect signin URI: https://www.test.com/login/ # Production
? Do you want to add another redirect signin URI No
Enter your redirect signout URI: https://localhost:8081/login/
? Do you want to add another redirect signout URI Yes
Enter your redirect signout URI: https://www.test.com/login/
? Do you want to add another redirect signout URI No
Select the social providers you want to configure for your user pool: Facebook
You've opted to allow users to authenticate via Facebook. If you haven't already, you'll need to go to https://developers.facebook.com and create an App ID.
Enter your Facebook App ID for your OAuth flow: [FacebookのApp ID]
Enter your Facebook App Secret for your OAuth flow: [FacebookのSecret ID]
Successfully added resource test1ec8a379 locally
Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud
- 今回Emailのみを連携対象としていますが、例えばuser名も連携したいと言う場合もあると思います.その場合は、authのparameters.jsonを修正ください
- どんな項目が連携項目かはCognitoのユーザプール > フェデレーション > 属性マッピングで確認できます
amplify/backend/auth/test1ec8a379/parameters.json
{
-- 中略 --
"hostedUIProviderMeta": "[{\"ProviderName\":\"Facebook\",\"authorize_scopes\":\"email,public_profile\",\"AttributeMapping\":{\"email\":\"email\",\"username\":\"id\"}}]", # こちらに\"name\":\"name\"を追加
"oAuthMetadata": "{\"AllowedOAuthFlows\":[\"code\"],\"AllowedOAuthScopes\":[\"phone\",\"email\",\"openid\",\"profile\",\"aws.cognito.signin.user.admin\"],\"CallbackURLs\":[\"https://localhost:8081/login/\",\"https://www.test.com/login/\"],\"LogoutURLs\":[\"https://localhost:8081/login/\",\"https://www.test.com/login/\"]}",
}
- Cognitoのユーザープールでアプリの統合 > ドメイン名からAmazon Cognitoドメインを控えておきます
フロントアプリ側の設定
リダイレクト先の修正
- こちらで書かれているようにLocalとProductionなど複数のリダイレクト先を設定すると、アプリ側でうまくリダイレクトができません.
- そこでAmplifyのconfig情報であるaws-exports.jsを読み込む場所でホストに合致するリダイレクト先を設定するようにします
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import Amplify, * as AmplifyModules from 'aws-amplify'
import { AmplifyPlugin } from 'aws-amplify-vue'
import awsConfig from './aws-exports'
import store from './store'
require('@/assets/sass/styles.scss')
// redirectURLが複数存在する場合、エラーになるため対象ドメインに絞り込む
if (awsConfig.oauth.redirectSignIn.includes(',')) {
const filterHost = url => new URL(url).host === location.host
awsConfig.oauth.redirectSignIn = awsConfig.oauth.redirectSignIn
.split(',')
.filter(filterHost)
.shift()
awsConfig.oauth.redirectSignOut = awsConfig.oauth.redirectSignOut
.split(',')
.filter(filterHost)
.shift()
}
Amplify.configure(awsConfig)
-- 中略 --
ログイン画面の実装
- Amplifyが用意しているコンポーネントは使わず、自前で作る例です
LoginPage.vue
<template>
<button @click='loginByFacebook'>
<span>Facebookでログイン</span>
</button>
</template>
<script>
import { Hub } from 'aws-amplify'
import awsExport from '../../aws-exports'
export default {
mounted () {
this.hubSocialLogin()
},
destroyed () {
if (Hub) Hub.remove('auth')
},
methods: {
hubSocialLogin () {
Hub.listen('auth', (data) => {
try {
switch (data.payload.event) {
case 'signIn':
router.push({ path: '/hoge' })
break
case 'signIn_failure':
break
default:
break
}
} catch (error) {
}
})
},
loginByFacebook () {
const CognitoDomain = awsExport.oauth.domain
const CognitoAppClientID = awsExport.aws_user_pools_web_client_id
const RedirectURI = awsExport.oauth.redirectSignIn
const url = `https://${CognitoDomain}/oauth2/authorize?identity_provider=Facebook&redirect_uri=${RedirectURI}&response_type=code&client_id=${CognitoAppClientID}`
window.location.assign(url)
}
}
}
</script>
CI/CDの設定
- ここがかなり苦労しました。今の状態でPreview環境や本番環境でデプロイするとエラーになります。
2019-11-25T16:28:56.016Z [INFO]: # Executing command: amplifyPush --environment prod
2019-11-25T16:28:56.020Z [INFO]: # Getting Amplify CLI Cloud-Formation stack info from environment cache
2019-11-25T16:28:56.026Z [INFO]: # Start initializing Amplify environment: prod
2019-11-25T16:28:56.028Z [INFO]: # Initializing new Amplify environment: prod (amplify init)
2019-11-25T16:29:16.860Z [INFO]: Note: It is recommended to run this command from the root of your app directory
2019-11-25T16:29:21.331Z [WARNING]: - Initializing your environment: prod
2019-11-25T16:29:21.786Z [WARNING]: ✔ Initialized provider successfully.
2019-11-25T16:29:21.832Z [WARNING]: ✖ There was an error initializing your environment.
2019-11-25T16:29:21.833Z [INFO]: init failed
2019-11-25T16:29:21.834Z [INFO]: Error: auth headless init is missing the following inputParams facebookAppIdUserPool, facebookAppSecretUserPool, googleAppIdUserPool, googleAppSecretUserPool
at updateConfigOnEnvInit (/root/.nvm/versions/node/v10.16.0/lib/node_modules/@aws-amplify/cli/node_modules/amplify-category-auth/provider-utils/awscloudformation/index.js:315:15)
at /root/.nvm/versions/node/v10.16.0/lib/node_modules/@aws-amplify/cli/node_modules/amplify-category-auth/index.js:241:28
at /root/.nvm/versions/node/v10.16.0/lib/node_modules/@aws-amplify/cli/node_modules/promise-sequential/index.js:16:18
at process._tickCallback (internal/process/next_tick.js:68:7)
- こちらを参考にして対処しました
amplify.yml
version: 0.1
backend:
phases:
build:
commands:
- chmod u+x ./amplifypush.sh
- ./amplifypush.sh
frontend:
phases:
preBuild:
commands:
- yarn install
build:
commands:
- yarn run build
artifacts:
baseDirectory: dist
files:
- "**/*"
cache:
paths:
- node_modules/**/*
amplifypush.sh
#!/usr/bin/env bash
set -e
IFS='|'
help_output () {
echo "usage: amplify-push <--environment|-e <name>> <--simple|-s>"
echo " --environment The name of the Amplify environment to use"
echo " --simple Optional simple flag auto-includes stack info from env cache"
exit 1
}
init_env () {
ENV=$1
AMPLIFY=$2
PROVIDERS=$3
CODEGEN=$4
AWSCONFIG=$5
CATEGORIES=$6
echo "# Start initializing Amplify environment: ${ENV}"
if [[ -z ${STACKINFO} ]];
then
echo "# Initializing new Amplify environment: ${ENV} (amplify init)"
amplify init --amplify ${AMPLIFY} --providers ${PROVIDERS} --codegen ${CODEGEN} --categories ${CATEGORIES} --yes;
echo "# Environment ${ENV} details:"
amplify env get --name ${ENV}
else
echo "STACKINFO="${STACKINFO}
echo "# Importing Amplify environment: ${ENV} (amplify env import)"
amplify env import --name ${ENV} --config "${STACKINFO}" --awsInfo ${AWSCONFIG} --categories ${CATEGORIES} --yes;
echo "# Initializing existing Amplify environment: ${ENV} (amplify init)"
amplify init --amplify ${AMPLIFY} --providers ${PROVIDERS} --codegen ${CODEGEN} --categories ${CATEGORIES} --yes;
echo "# Environment ${ENV} details:"
amplify env get --name ${ENV}
fi
echo "# Done initializing Amplify environment: ${ENV}"
}
ENV=""
IS_SIMPLE=false
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"
case ${key} in
-e|--environment)
ENV=$2
shift
;;
-r|--region)
REGION=$2
shift
;;
-s|--simple)
IS_SIMPLE=true
shift
;;
*)
POSITIONAL+=("$1")
shift
;;
esac
done
set -- "${POSITIONAL[@]}"
# if no provided environment name, use default env variable, then user override
if [[ ${ENV} = "" ]];
then
ENV=${AWS_BRANCH}
fi
if [[ ${USER_BRANCH} != "" ]];
then
ENV=${USER_BRANCH}
fi
# Check valid environment name
if [[ -z ${ENV} || "${ENV}" =~ [^a-zA-Z0-9\-]+ ]] ; then help_output ; fi
AWSCONFIG="{\
\"configLevel\":\"project\",\
\"useProfile\":true,\
\"profileName\":\"default\"\
}"
AMPLIFY="{\
\"envName\":\"${ENV}\"\
}"
PROVIDERS="{\
\"awscloudformation\":${AWSCONFIG}\
}"
CODEGEN="{\
\"generateCode\":false,\
\"generateDocs\":false\
}"
AUTHCONFIG="{\
\"facebookAppIdUserPool\":\"アプリID\",\
\"facebookAppSecretUserPool\":\"シークレットキー\"\
}"
CATEGORIES="{\
\"auth\":$AUTHCONFIG\
}"
# Handle old or new config file based on simple flag
if [[ ${IS_SIMPLE} ]];
then
echo "# Getting Amplify CLI Cloud-Formation stack info from environment cache"
export STACKINFO="$(envCache --get stackInfo)"
init_env ${ENV} ${AMPLIFY} ${PROVIDERS} ${CODEGEN} ${AWSCONFIG} ${CATEGORIES}
echo "# Store Amplify CLI Cloud-Formation stack info in environment cache"
STACKINFO="$(amplify env get --json --name ${ENV})"
envCache --set stackInfo ${STACKINFO}
echo "STACKINFO="${STACKINFO}
else
# old config file, above steps performed outside of this script
init_env ${ENV} ${AMPLIFY} ${PROVIDERS} ${CODEGEN} ${AWSCONFIG} ${CATEGORIES}
fi
Facebookの設定2
- Facebookログイン機能を追加します
- ダッシュボードの「製品の追加」から「Facebookログイン」を選択します
- 左メニューのFacebookログインの設定を選択し、有効なOAuthリダイレクトURIにCognitoのドメインで控えておいた値を元に
https://<ドメイン>.auth.ap-northeast-1.amazoncognito.com/oauth2/idpresponse
と入力します.こちらはLocalと本番環境それぞれ入力できます
- 上部のアプリIDの隣にある開発中のタブをライブにします.
- プライバシーポリシーのURLを設定していないと、ライブにできないのでご注意ください
確認
Facebookでログインできることを確認します.
またCognito側でアカウントのステータスがEXTERNAL_PROVIDERでユーザプールが生成されていることも確認できると思います