ソーシャルプロバイダーサインインの追加
Apple、Amazon、Facebook、Googleなどのソーシャルプロバイダーで既存のアカウントを使用して、ユーザーがアプリにサインインおよび認証できるようにすることができます。バックエンドリソースを設定したら、そのプロバイダーでユーザーをサインインさせるようにアプリを設定できます。このプロセスにより、認証情報が安全に交換され、ユーザー情報が収集されます。この情報は、アプリで新しいユーザーを作成したり、ソーシャルアカウントを既存のユーザーにリンクしたりするために使用できます。ソーシャルプロバイダーサインインを組み込むことで、ユーザーに合理化された登録、より多くのサインインオプション、および既存のアカウントとアプリ間の統合されたエクスペリエンスを提供できます。
このガイドでは、まずプロバイダーでの開発者アカウントを設定することで、ソーシャルプロバイダーによるサインインを追加する方法を説明します。この手順の後、Authカテゴリを設定し、ソーシャルサインインをアプリに統合できます。
始める前に、以下が必要です:
- Amplifyプロジェクト
- Amplifyライブラリのインストールと設定
詳細を見るOAuth認証の仕組みを確認する
ソーシャルプロバイダーサインインを組み込む推奨方法は、OAuthリダイレクトを使用することです。これにより、ユーザーはソーシャルメディアアカウントを使用してサインインし、Cognitoユーザープールに対応するユーザーが作成されます。
OAuth 2.0は、Webおよびモバイルアプリケーションが限定的な方法でユーザー情報(「スコープ」)にアクセスするために使用する共通の認可フレームワークです。OAuthでよく聞かれる例えは、飛行機への搭乗やホテルへの宿泊です。身分証明書を提示することが認証部分(アプリへのサインイン)であり、搭乗券/ホテルキーを使用することが認可されたアクセスです。
AmplifyのOAuthサポートはCognito User Poolsを使用し、ソーシャルプロバイダーとのフェデレーションをサポートしています。これにより、サインイン後に対応するユーザーがUser Poolに自動的に作成されます。この設計では、アプリにソーシャルプロバイダーのSDKを含める必要はありません。これらのソーシャルプロバイダーで開発者アカウントを設定した後、amplify add authを実行してソーシャルプロバイダーオプションを選択することでAuthカテゴリを設定できます。その後、アプリでAuth.federatedSignIn()を使用して、事前構築された「Hosted UI」を表示するか、プロバイダー名(例:Auth.federatedSignIn({provider: 'Facebook'}))を渡して直接インターフェースし、独自のUIを構築することができます。 また、ソーシャルプロバイダーからのトークンを
Auth.federatedSignIn()で直接渡すことで、Identity Poolsから直接認証情報を取得することもできます。ただし、この場合はアプリでそのプロバイダーのSDKを使用し、プロバイダーからのトークンとその更新サイクルを手動で管理する必要があります。
ソーシャル認証プロバイダーの設定
Amplify AuthでソーシャルサインインをとSMS設定する前に、使用する各プロバイダーで開発者アカウントを設定する必要があります。
-
Facebook認証情報でサインインします。
-
上部ナビゲーションバーから_マイアプリ_を選択し、読み込まれたページで_アプリを作成_を選択します。
-
ユースケースとして、_Facebook Loginを設定_を選択します。
-
プラットフォームとして_ウェブサイト_を選択し、_いいえ、ゲームを作っていません_を選択します。
-
FacebookアプリID名を入力し、_アプリを作成_を選択します。
-
左ナビゲーションバーで_設定_を選択し、次に_ベーシック_を選択します。
-
_アプリID_と_アプリシークレット_をメモしてください。これらは次のセクションのCLIフローで使用します。
-
Googleデベロッパーコンソールにアクセスします。
-
_プロジェクトを選択_をクリックします。
-
_新しいプロジェクト_をクリックします。
-
プロジェクト名を入力し、_作成_をクリックします。
-
プロジェクトが作成されたら、左ナビゲーションメニューから_APIとサービス_を選択し、次に_認証情報_を選択します。
-
_同意画面を設定_をクリックします。
-
_作成_をクリックします。
-
必須フィールドである_アプリ情報_と_開発者の連絡先情報_を入力し、_保存して続行_を3回クリックして(OAuth同意画面 -> スコープ -> テストユーザー)同意画面の設定を完了します。
-
_認証情報_タブに戻り、_認証情報を作成_ドロップダウンリストから_OAuthクライアントID_を選択してOAuth2.0認証情報を作成します。
.
-
_アプリケーションの種類_として_ウェブアプリケーション_を選択し、OAuthクライアント名を付けます。
-
_作成_をクリックします。
-
_クライアントID_と_クライアントシークレット_をメモしてください。次のセクションのCLIフローで必要になります。
-
_OK_を選択します。
-
Amazon認証情報でサインインします。
-
AmazonクライアントIDとクライアントシークレットを受け取るには、Amazonセキュリティプロファイルを作成する必要があります。_セキュリティプロファイルを作成_を選択します。
-
セキュリティプロファイル名、セキュリティプロファイルの説明、および_プライバシー通知のURL_を入力します。
-
_保存_を選択します。
-
_クライアントIDを表示_と_クライアントシークレット_を選択してクライアントIDとシークレットを表示します。次のセクションのCLIフローで必要になります。
-
Apple開発者認証情報でサインインします。
-
メインの開発者ポータルページで、_証明書、識別子、プロファイル_を選択します。
-
左ナビゲーションバーで_識別子_を選択します。
-
_識別子_ページで、_プラスアイコン(+)_を選択します。
-
_新しい識別子を登録_ページで、_アプリID_を選択します。
-
_アプリIDを登録_ページの_アプリIDプレフィックス_で、_チームID_の値をメモしておきます。
-
_説明_テキストボックスに説明を入力し、iOSアプリの
bundleIDを入力します。 -
_機能_で、_Appleでサインイン_を選択します。
-
_続行_を選択し、設定を確認してから_登録_を選択します。
-
_識別子_ページの右側で_アプリID_を選択し、次に_サービスID_を選択します。
-
_プラスアイコン(+)_を選択し、_新しい識別子を登録_ページで_サービスID_を選択します。
-
_説明_テキストボックスに説明を入力し、サービスIDの識別子を入力します。
-
_続行_を選択してサービスIDを登録します。
ソーシャルプロバイダーでの開発者アカウントが設定されました。次のステップのためにAmplifyプロジェクトに戻ることができます。
Authカテゴリの設定
ソーシャルプロバイダーを設定したら、Amplify CLIを使用してAuth設定を更新できます。
CLIを開始するには、プロジェクトのルートフォルダで以下を実行します:
amplify add auth ## "amplify update auth" if already configured以下のオプションを選択します:
? Do you want to use the default authentication and security configuration? `Default configuration with Social Provider (Federation)`? How do you want users to be able to sign in? `Username`? Do you want to configure advanced settings? `No, I am done.`? What domain name prefix you want us to create for you? `(default)`? Enter your redirect signin URI: `http://localhost:3000/`? Do you want to add another redirect signin URI `No`? Enter your redirect signout URI: `http://localhost:3000/`? Do you want to add another redirect signout URI `No`? Select the social providers you want to configure for your user pool: `<choose your provider and follow the prompts to input the proper tokens>`次に、amplify pushを実行して変更を公開します。完了すると、Web UIの自動生成URLが表示されます。CLIを使用していつでもamplify statusを実行することで、ユーザープールのドメインURLを取得できます。
次に、このURLをソーシャルプロバイダーに通知する必要があります:
-
Facebook認証情報でFacebook開発者アカウントにサインインします。
-
上部ナビゲーションバーから_マイアプリ_を選択し、_アプリ_ページで以前に作成したアプリを選択します。
-
左ナビゲーションバーで_プロダクト_を選択します。まだ追加されていない場合は_Facebook Login_を追加します。
-
既に追加されている場合は、_設定_ドロップダウンの_設定_を選択します。
-
_有効なOAuthリダイレクトURI_に、
/oauth2/idpresponseエンドポイントを含むユーザープールドメインを入力します。https://<your-user-pool-domain>/oauth2/idpresponse
- 変更を保存します。
-
Googleデベロッパーコンソールにアクセスします。
-
左ナビゲーションバーで、ピン留め_または_その他のプロダクト(ピン留めされていない場合)の下にある_APIとサービス_を探します。
-
_APIとサービス_サブメニュー内で、_認証情報_を選択します。
-
最初のステップで作成したクライアントを選択し、_編集_ボタンをクリックします。
-
_承認済みのJavaScriptオリジン_フォームにユーザープールドメインを入力します。
-
_承認済みのリダイレクトURI_に、
/oauth2/idpresponseエンドポイントを含むユーザープールドメインを入力します。注意:エンドポイントを追加する際に
Invalid Redirect: domain must be added to the authorized domains list before submitting.というエラーメッセージが表示された場合は、_承認済みドメインリスト_にドメインを追加してください。 -
_保存_をクリックします。
-
Amazon認証情報でサインインします。
-
歯車アイコンにカーソルを合わせ、前のステップで作成したセキュリティプロファイルに関連する_Web設定_を選択し、_編集_を選択します。
-
_許可されたオリジン_にユーザープールドメインを入力し、_許可された返却URL_に
/oauth2/idpresponseエンドポイントを含むユーザープールドメインを入力します。 -
_保存_を選択します。
-
Apple開発者認証情報でサインインします。
-
メインの開発者ポータルページで、_証明書、識別子、プロファイル_を選択します。
-
左ナビゲーションバーで_識別子_を選択し、右側のドロップダウンリストから_サービスID_を選択します。
-
上記のセクションで認証プロバイダーを設定したときに作成されたサービスIDを選択します。
-
_Appleでサインイン_を有効にし、_設定_を選択します。
-
_プライマリアプリID_で、以前に作成したアプリIDを選択します。
-
_ドメインとサブドメイン_にユーザープールドメインを入力します。
-
_返却URL_に
/oauth2/idpresponseエンドポイントを含むユーザープールドメインを入力します。 -
_次へ_をクリックし、情報を確認して_完了_を選択します。
-
_サービスID設定の編集_で_続行_をクリックし、情報を確認して_保存_を選択します。
-
_証明書、識別子、プロファイル_のメインページで、_キー_を選択します。
-
_キー_ページで、_プラスアイコン(+)_を選択します。
-
_キー名_の下にキーの名前を入力します。
-
_Appleでサインイン_を有効にし、_設定_を選択します。
-
_プライマリアプリID_で、以前に作成したアプリIDを選択します。
-
_保存_をクリックします。
-
_新しいキーを登録_で_続行_をクリックし、情報を確認して_登録_を選択します。
-
新しいページにリダイレクトされます。_キーID_をメモし、秘密鍵を含む.p8ファイルをダウンロードします。
Authカテゴリを設定し、ソーシャルプロバイダーでURLを更新しました。これでアプリのフロントエンドを設定できます。
フロントエンドの設定
OAuthエンドポイント(Cognito Hosted UIを使用)を設定した後、Auth.federatedSignIn()関数を呼び出すことでアプリを統合できます。この関数はユーザーをCognito Hosted UIにリダイレクトし、ユーザー名パスワードでのサインインオプションと設定されたすべてのソーシャルプロバイダーのオプションを提供します。また、provider引数にLoginWithAmazon、Facebook、Google、またはSignInWithAppleを渡すと(例:Auth.federatedSignIn({ provider: 'LoginWithAmazon' }))、Hosted UIをバイパスしてソーシャルプロバイダーと直接フェデレーションすることもできます。以下の例を参照してください。
カスタム状態を追加したい場合は、文字列値を渡すことで(例:Auth.federatedSignIn({ customState: 'xyz' }))、Hubを使用してカスタム状態をリッスンできます。また、Auth.federatedSignIn()を使用してsignIn_failureイベントをリッスンすることで、Hubイベントシステムを使用してエラーをキャッチすることもできます。
import React, { useEffect, useState } from 'react';import { Amplify, Auth, Hub } from 'aws-amplify';import { CognitoHostedUIIdentityProvider } from '@aws-amplify/auth';import awsConfig from './aws-exports';
Amplify.configure(awsConfig);
function App() { const [user, setUser] = useState(null); const [customState, setCustomState] = useState<string | null>(null);
useEffect(() => { const unsubscribe = Hub.listen("auth", ({ payload: { event, data }}) => { switch (event) { case "signIn": setUser(data); break; case "signOut": setUser(null); break; case "customOAuthState": setCustomState(data); } });
getUser();
return unsubscribe; }, []);
const getUser = async (): Promise<void> => { try { const currentUser = await Auth.currentAuthenticatedUser(); setUser(currentUser); } catch(error) { console.error(error); console.log("Not signed in"); } };
return ( <div className="App"> <button onClick={() => Auth.federatedSignIn()}>Open Hosted UI</button> <button onClick={() => Auth.federatedSignIn({provider: CognitoHostedUIIdentityProvider.Facebook })}>Open Facebook</button> <button onClick={() => Auth.federatedSignIn({provider: CognitoHostedUIIdentityProvider.Google })}>Open Google</button> <button onClick={() => Auth.federatedSignIn({provider: CognitoHostedUIIdentityProvider.Amazon })}>Open Amazon</button> <button onClick={() => Auth.federatedSignIn({provider: CognitoHostedUIIdentityProvider.Apple })}>Open Apple</button> <button onClick={() => Auth.signOut()}>Sign Out</button> <div>{user?.getUsername()}</div> </div> );}
//You can catch errors by listening to the signIn-failure event Hub.listen('auth', (data) => { if (data.payload.event === 'signIn_failure') { // Do something here }})import React, { useEffect, useState } from 'react';import { Amplify, Auth, Hub } from 'aws-amplify';import { CognitoHostedUIIdentityProvider } from '@aws-amplify/auth';import awsConfig from './aws-exports';
Amplify.configure(awsConfig);
function App() { const [user, setUser] = useState(null); const [customState, setCustomState] = useState(null);
useEffect(() => { const unsubscribe = Hub.listen('auth', ({ payload: { event, data } }) => { switch (event) { case 'signIn': setUser(data); break; case 'signOut': setUser(null); break; case 'customOAuthState': setCustomState(data); } });
Auth.currentAuthenticatedUser() .then((currentUser) => setUser(currentUser)) .catch(() => console.log('Not signed in'));
return unsubscribe; }, []);
return ( <div className="App"> <button onClick={() => Auth.federatedSignIn()}>Open Hosted UI</button> <button onClick={() => Auth.federatedSignIn({ provider: CognitoHostedUIIdentityProvider.Facebook }) } > Open Facebook </button> <button onClick={() => Auth.federatedSignIn({ provider: CognitoHostedUIIdentityProvider.Google }) } > Open Google </button> <button onClick={() => Auth.federatedSignIn({ provider: CognitoHostedUIIdentityProvider.Amazon }) } > Open Amazon </button> <button onClick={() => Auth.federatedSignIn({ provider: CognitoHostedUIIdentityProvider.Apple }) } > Open Apple </button> <button onClick={() => Auth.signOut()}>Sign Out</button> <div>{user && user.getUsername()}</div> </div> );}
//You can catch errors by listening to the signIn-failure eventHub.listen('auth', (data) => { if (data.payload.event === 'signIn_failure') { // Do something here }});リダイレクトURL
_サインインリダイレクトURI_の入力には、ローカル開発用のURIと本番用のURIを1つずつ入力できます。例:開発環境ではhttp://localhost:3000/、本番環境ではhttps://www.example.com/。_サインアウトリダイレクトURI_も同様です。
複数のリダイレクトURI入力がある場合、Amplifyプロジェクトを設定する際に両方を処理する必要があります。例えば:
import awsConfig from './aws-exports';
const isLocalhost = Boolean( window.location.hostname === 'localhost' || // [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' || // 127.0.0.1/8 is considered localhost for IPv4. window.location.hostname.match( /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ ));
// Assuming you have two redirect URIs, and the first is for localhost and second is for productionconst [localRedirectSignIn, productionRedirectSignIn] = awsConfig.oauth.redirectSignIn.split(',');
const [localRedirectSignOut, productionRedirectSignOut] = awsConfig.oauth.redirectSignOut.split(',');
const updatedAwsConfig = { ...awsConfig, oauth: { ...awsConfig.oauth, redirectSignIn: isLocalhost ? localRedirectSignIn : productionRedirectSignIn, redirectSignOut: isLocalhost ? localRedirectSignOut : productionRedirectSignOut }};
Amplify.configure(updatedAwsConfig);例複数のリダイレクトURIを使用した完全な例
import { useEffect, useState } from 'react';import { Amplify, Auth, Hub } from 'aws-amplify';import awsConfig from './aws-exports';
const isLocalhost = Boolean( window.location.hostname === 'localhost' || // [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' || // 127.0.0.1/8 is considered localhost for IPv4. window.location.hostname.match( /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ ));
// Assuming you have two redirect URIs, and the first is for localhost and second is for productionconst [ localRedirectSignIn, productionRedirectSignIn,] = awsConfig.oauth.redirectSignIn.split(',');
const [ localRedirectSignOut, productionRedirectSignOut,] = awsConfig.oauth.redirectSignOut.split(',');
const updatedAwsConfig = { ...awsConfig, oauth: { ...awsConfig.oauth, redirectSignIn: isLocalhost ? localRedirectSignIn : productionRedirectSignIn, redirectSignOut: isLocalhost ? localRedirectSignOut : productionRedirectSignOut, }}
Amplify.configure(updatedAwsConfig);
function App() { const [user, setUser] = useState(null);
useEffect(() => { Hub.listen('auth', ({ payload: { event, data }}) => { switch (event) { case 'signIn': case 'cognitoHostedUI': getUser(); break; case 'signOut': setUser(null); break; case 'signIn_failure': case 'cognitoHostedUI_failure': console.log('Sign in failure', data); break; } });
getUser(); }, []);
const getUser = async (): Promise<void> => { try { const userData = await Auth.currentAuthenticatedUser(); setUser(userData) } catch(error) { console.error(error); console.log("Not signed in"); } };
return ( <div> <p>User: {user ? JSON.stringify(user.attributes) : 'None'}</p> {user ? ( <button onClick={() => Auth.signOut()}>Sign Out</button> ) : ( <button onClick={() => Auth.federatedSignIn()}>Federated Sign In</button> )} </div> );}
export default App;import { useEffect, useState } from 'react';import { Amplify, Auth, Hub } from 'aws-amplify';import awsConfig from './aws-exports';
const isLocalhost = Boolean( window.location.hostname === 'localhost' || // [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' || // 127.0.0.1/8 is considered localhost for IPv4. window.location.hostname.match( /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ ));
// Assuming you have two redirect URIs, and the first is for localhost and second is for productionconst [localRedirectSignIn, productionRedirectSignIn] = awsConfig.oauth.redirectSignIn.split(',');
const [localRedirectSignOut, productionRedirectSignOut] = awsConfig.oauth.redirectSignOut.split(',');
const updatedAwsConfig = { ...awsConfig, oauth: { ...awsConfig.oauth, redirectSignIn: isLocalhost ? localRedirectSignIn : productionRedirectSignIn, redirectSignOut: isLocalhost ? localRedirectSignOut : productionRedirectSignOut }};
Amplify.configure(updatedAwsConfig);
function App() { const [user, setUser] = useState(null);
useEffect(() => { Hub.listen('auth', ({ payload: { event, data } }) => { switch (event) { case 'signIn': case 'cognitoHostedUI': getUser().then((userData) => setUser(userData)); break; case 'signOut': setUser(null); break; case 'signIn_failure': case 'cognitoHostedUI_failure': console.log('Sign in failure', data); break; } });
getUser().then((userData) => setUser(userData)); }, []);
function getUser() { return Auth.currentAuthenticatedUser() .then((userData) => userData) .catch(() => console.log('Not signed in')); }
return ( <div> <p>User: {user ? JSON.stringify(user.attributes) : 'None'}</p> {user ? ( <button onClick={() => Auth.signOut()}>Sign Out</button> ) : ( <button onClick={() => Auth.federatedSignIn()}> Federated Sign In </button> )} </div> );}
export default App;ソーシャルサインイン用の認証パラメーターでバックエンド環境をデプロイする
認証設定を作成または更新すると、Amplifyはローカルで設定を行いますが、バックエンド環境への変更は自動的にデプロイされません。amplify pushを実行して変更をバックエンド環境にデプロイする必要があります。
フロントエンドとバックエンドの継続的デプロイメントを使用してAmplify Consoleにアプリをデプロイできます。これらの手順に従ってください。
まとめ
おめでとうございます!ソーシャルプロバイダーサインインの追加ガイドを完了しました。このガイドでは、ソーシャル認証プロバイダーを設定し、ソーシャルサインイン用のAmplify Authカテゴリを設定し、フロントエンドをセットアップする方法を学びました。ユーザーはソーシャルプロバイダーアカウントを使用してアプリにサインインできるようになりました。
次のステップ
ソーシャルプロバイダーサインインを設定したので、これらのワークフローをカスタマイズする追加の方法についても学ぶことをお勧めします: