Google OAuth2でログインしたユーザーがGoogleグループのメンバーかチェックする(Python,Streamlit)
はじめに
Python(というかStreamlit)で作ったアプリに認証をつけたく、Google OAuth2で認証をつけました。認証機能の実装はyag_aysさんの記事を参考にしたので、そちらを参照いただければと思います。
さて、Google OAuth2で認証した場合、単純な設定で許可できるユーザーは以下のいずれかになります。
- Googleのユーザーだったら誰でもOK
- 自分の組織のユーザーのみOK
後者の組織の制限で十分な場合もあると思いますが、今回はより利用者を絞りたかったので特定のGoogleグループのメンバーのみを許可する機能が欲しくなりました。
ということで、Google OAuth2でログインしたユーザーが特定のGoogleグループに所属しているかどうかを判断する処理を実装しました。
使用するAPI
Googleグループを操作できるAPIを調べた所、次の2つが出てきました。
- Directory API (Admin console)
- Groups API (Cloud Identity)
今回使ったのは後者のCloud Identity Groups APIです。ログインしたユーザーの立場から該当のグループのメンバーかどうかだけが判断出来れば良いですので、管理者権限でグループを操作するDirectory APIの権限は過剰になります。また、Directory APIは使用する権限を得るのにGoogleの管理者権限が必要ですので、個人ならともかく組織では使用許可を取るのが面倒くさいです。
実際にやってみた
主にこちらの公式ドキュメントを参考に実装してみました。
前提
PythonのアプリでGoogle OAuth2の認証が実装できており、ログインしたユーザーの以下の情報が取得でできていることとします[1]。
- ログインしたユーザーのメールアドレス
- ログインしたユーザーのアクセストークン
Cloud Identityを使えるようにする
Cloud Identity APIを有効化する
Google CloudのコンソールからCloud Identity APIを有効化してください。有効化するためのリンクを貼っておきます。
OAuthのScopeを追加する
Google CloudのコンソールのOAuth同意画面から、スコープにcloud-identity.groups.readonly
を追加してください[2]。
コードを書く
必要なライブラリをインストールします。
pip install google-api-python-client google-auth
コードを書きます。先程貼った公式ドキュメントのほぼコピペで書けました。
from urllib.parse import urlencode
import google.oauth2.credentials
import googleapiclient.discovery
def check_user_group_membership(group_id: str, mail: str, access_token: str) -> bool:
"""
指定したユーザーが指定したグループに所属しているかどうかを確認する
:param group_id: グループID
:param mail: メールアドレス
:param access_token: アクセストークン
:return: 所属しているかどうか(True or False)
"""
try:
# 認証情報を作成
credentials = google.oauth2.credentials.Credentials(
access_token,
)
service = googleapiclient.discovery.build(
'cloudidentity', 'v1', credentials=credentials
)
query_params: str = urlencode(
{"query": f"member_key_id == '{mail}'"}
)
request = service.groups().memberships().checkTransitiveMembership(
parent=f"groups/{group_id}",
query=query_params,
)
request.uri += "&" + query_params
response = request.execute()
return response['hasMembership']
except Exception as e:
return False
グループIDを調べる
前述のコードには唐突にグループIDが出てきています。これはGoogleグループのメールアドレスではなく、Googleグループに振られた固有IDになります。通常は表に出て来ませんので、調べる必要があります。
グループIDの調べ方を調べた所、次のコマンドで取得できることが分かりました。
gcloud identity groups describe (groupのメールアドレス) --project=(GoogleCloudのプロジェクトID)
コマンドで取得できたので試していませんが、pythonのコードでメールアドレスからGroupIDを取得することも出来るはずです。それっぽい記事を見つけたので貼っておきます。
GroupIDが分かれば、先程貼った関数にグループのGroupID、ユーザーのメールアドレスとアクセストークンを投げ込めば、そのグループに所属しているかどうかの判別が可能です。所属してなければ以降の処理を拒否し、ログアウトさせれば良いということになります。
以上です。
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion