はじめに
普段からWebアプリケーションにログイン機能を実装する際、バックエンドにAmazonCognitoを利用してきました。
Cognitoはログイン認証をサーバレスに実現してくれるマネージドなサービスです。開発者はログインユーザの情報を管理する必要が(ほとんど)ありません。
またAWSのリソースへのアクセス権限を一時的に発行することもできるので、ログイン後のトークンを利用して、アプリケーションからAWSの各リソースを利用することができます。
今回はそんなCognitoの外部IDプロバイダ認証を利用してログインし、トークンを取得するまでの流れをGoogleとFacebookでやっていこうと思います。
Cognitoの準備
Cognitoのデプロイ
AmplifyCLIを利用してサクッと作っていきます。フロントはVue.jsを使っています。
この記事を参考にしていただければ、Cognitoを利用したログイン画面を用意することができると思います。
その他下準備
その他細かい設定を行っていきます。
アプリクライアントの設定
上記の手順でCognitoをデプロイするとアプリクライアントが2つ作成されていると思います。
今回はWebアプリケーションからログインするので、app_clientWeb
とついている方のクライアントを利用します。
その設定の中の「サインインとサインアウトの URL」にhttp://localhost:8080
を入力しておきます。
ドメインの設定
AmazonCognitoドメインを設定する必要があります。
左メニューから「ドメイン名」を選択して、ドメインのプレフィックスに任意の文字列を入力します。利用できるサブドメインだったら登録されます。
※このドメインは各外部IDプロバイダ認証からのリダレクトURIで利用するのでメモっておいてください。
これでCognitoの下準備は完了です。
Google認証
Google認証の設定はGoogleCloudPlatform(GCP)で進めていきます。
外部からGoogle認証を利用するために、認証情報の設定します。
① 左メニューバーの「APIとサービス」から「認証情報」を選択する
③ 「認証情報」を選択し、「OAuthクライアントID」を選択
※初めて作成する場合は画面が違いますが、同じように「OAuthクライアントID」を選択していただければ、その後は同じ内容です。
④ 必要な情報を入力していく
リダイレクトURIは https://<Cognitoドメイン>.auth.ap-northeast-1.amazoncognito.com/oauth2/idpresponse
になります。
⑤ クライアントIDとシークレットを取得
認証情報が作成されるとIDとシークレットが表示されるので、後ほど使うのでメモっておいてください。
これでGoogleの設定は完了です。
Facebook認証
Facebook認証は「facebook for developers」で設定します。
① グローバルメニュー「マイアプリ」から「新しいアプリを追加する」を選択
③ ダッシュボードの「製品の追加」から「Facebookログイン」を選択
④ 左メニューの「Facebookログイン」の「設定」から、リダイレクトURIを設定
リダレクトURIはGoogleと同じです。
⑤ 左メニューの「設定」の「ベーシック」から「アプリID」と「app sercret」を取得
こちらも後ほど利用するのでメモっておいてください。
⑥ アプリを公開する
開発モードのままでは利用できなくなるので、公開する必要があります。
これでFacebookの設定は完了です。
アプリの設定
Webアプリケーションの処理はCognitoが用意してくれている、各外部IDプロバイダ認証用のリンクを呼ぶだけです。
ボタンのClickEventで着火させるといいかもしれませんね。
/**
* CognitoDomain: AmazonCognitoドメイン
* CognitoAppClientID: Cognitoに紐付いているアプリクライアントのID
* RedirectURI: リダイレクト先のURI
*/
// Google認証
function OAuthForGoogle() {
window.location.assign(
"https://" +
CognitoDomain +
".auth.ap-northeast-1.amazoncognito.com/oauth2/authorize?response_type=code&client_id=" +
CognitoAppClientID
"&redirect_uri=" +
RedirectURI
"&identity_provider=Google"
);
}
// Facebook認証
function OAuthForFacebook() {
window.location.assign(
"https://" +
CognitoDomain +
".auth.ap-northeast-1.amazoncognito.com/oauth2/authorize?response_type=code&client_id=" +
CognitoAppClientID
"&redirect_uri=" +
RedirectURI
"&identity_provider=Facebook"
);
}
Google認証時の画面
Facebook認証時の画面
Cognitoトークンの取得
ログインするとURLパラメータにcode
が埋まっています。このcode
を利用してCognitoトークンを取得します。
下記のソースコードはログインしたあとのcode
を利用して、Cognitoトークンとユーザー情報を取得し、Amplifyで使えるようにlocalStorageにセットする際の一例です。
const localStorageMainKey: string = "CognitoIdentityServiceProvider." + CognitoAppClientID;
const code: string = this.$route.query.code as string;
if (code && localStorage.getItem("loginStatus") !== "logined") {
const params: URLSearchParams = new URLSearchParams();
params.append("grant_type", "authorization_code");
params.append("redirect_uri", RedirectURI);
params.append("code", code);
params.append("client_id", CognitoAppClientID);
// Tokenの取得
axios.post(CognitoBaseURL + "/oauth2/token", params, {
headers : {
"Content-Type": "application/x-www-form-urlencoded"
}
}).then((token: any) => {
const bearer: string = "Bearer " + token.data.access_token;
// ユーザー情報の取得
axios.post(CognitoBaseURL + "/oauth2/userInfo", {}, {
headers : {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": bearer
}
}).then((userInfo: any) => {
// Amplifyを利用するためにlocalStorageにセットする
const localStorageSubKey: string = localStorageMainKey + "." + userInfo.data.sub;
localStorage.setItem(localStorageSubKey + ".accessToken", token.data.access_token);
localStorage.setItem(localStorageSubKey + ".idToken", token.data.id_token);
localStorage.setItem(localStorageSubKey + ".refreshToken", token.data.refresh_token);
localStorage.setItem(localStorageSubKey + ".clockDrift", "0");
localStorage.setItem(localStorageMainKey + ".LastAuthUser", userInfo.data.sub);
localStorage.setItem("loginStatus", "logined");
});
}).catch((err: any) => {
console.error(err);
});
}
さいごに
これで、GoogleとFacebookのアカウントを使ってログインし、Cognitoからトークンを取得することができました。
ただ前述したとおり、ログインしただけではトークンを返してくれないので、取得しに行かなければいけないのが、少し手間がかかるといった印象でした。
あとはTwitter認証をしたいと思っているので、また記事を更新しようと思っています。
ではまた!!!